Merge pull request #561 from YosysHQ/dave/idstringlist

Use IdStringList for bel/wire/pip/group names
This commit is contained in:
David Shah 2021-02-03 09:48:07 +00:00 committed by GitHub
commit 9a79163eab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 770 additions and 495 deletions

View File

@ -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>, readwrite_wrapper<Context, decltype(&Context::top_module), &Context::top_module, conv_to_str<IdString>,
conv_from_str<IdString>>::def_wrap(ctx_cls, "top_module"); 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>, fn_wrapper_1a<Context, decltype(&Context::getNetByAlias), &Context::getNetByAlias, deref_and_wrap<NetInfo>,
conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias"); conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias");
fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>, fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>,

View File

@ -36,19 +36,19 @@ void archcheck_names(const Context *ctx)
log_info("Checking bel names..\n"); log_info("Checking bel names..\n");
for (BelId bel : ctx->getBels()) { for (BelId bel : ctx->getBels()) {
IdString name = ctx->getBelName(bel); IdStringList name = ctx->getBelName(bel);
BelId bel2 = ctx->getBelByName(name); BelId bel2 = ctx->getBelByName(name);
if (bel != bel2) { 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"); log_info("Checking wire names..\n");
for (WireId wire : ctx->getWires()) { for (WireId wire : ctx->getWires()) {
IdString name = ctx->getWireName(wire); IdStringList name = ctx->getWireName(wire);
WireId wire2 = ctx->getWireByName(name); WireId wire2 = ctx->getWireByName(name);
if (wire != wire2) { 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 #ifndef ARCH_ECP5
log_info("Checking pip names..\n"); log_info("Checking pip names..\n");
for (PipId pip : ctx->getPips()) { for (PipId pip : ctx->getPips()) {
IdString name = ctx->getPipName(pip); IdStringList name = ctx->getPipName(pip);
PipId pip2 = ctx->getPipByName(name); PipId pip2 = ctx->getPipByName(name);
if (pip != pip2) { 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 #endif
@ -109,7 +109,7 @@ void archcheck_locs(const Context *ctx)
if (bel == BelId()) if (bel == BelId())
continue; continue;
Loc loc = ctx->getBelLocation(bel); 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(x == loc.x);
log_assert(y == loc.y); log_assert(y == loc.y);
log_assert(z == loc.z); log_assert(z == loc.z);
@ -118,7 +118,7 @@ void archcheck_locs(const Context *ctx)
for (BelId bel : ctx->getBelsByTile(x, y)) { for (BelId bel : ctx->getBelsByTile(x, y)) {
Loc loc = ctx->getBelLocation(bel); 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(x == loc.x);
log_assert(y == loc.y); log_assert(y == loc.y);
log_assert(usedz.count(loc.z)); log_assert(usedz.count(loc.z));

View File

@ -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); 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 BaseCtx::timingWildcardObject()
{ {
TimingConstrObjectId id; TimingConstrObjectId id;
@ -76,6 +111,14 @@ TimingConstrObjectId BaseCtx::timingWildcardObject()
return id; return id;
} }
std::string &StrRingBuffer::next()
{
std::string &s = buffer.at(index++);
if (index >= N)
index = 0;
return s;
}
TimingConstrObjectId BaseCtx::timingClockDomainObject(NetInfo *clockDomain) TimingConstrObjectId BaseCtx::timingClockDomainObject(NetInfo *clockDomain)
{ {
NPNR_ASSERT(clockDomain->clkconstr != nullptr); NPNR_ASSERT(clockDomain->clkconstr != nullptr);
@ -248,25 +291,57 @@ void BaseCtx::removeConstraint(IdString constrName)
const char *BaseCtx::nameOfBel(BelId bel) const const char *BaseCtx::nameOfBel(BelId bel) const
{ {
const Context *ctx = getCtx(); 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 char *BaseCtx::nameOfWire(WireId wire) const
{ {
const Context *ctx = getCtx(); 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 char *BaseCtx::nameOfPip(PipId pip) const
{ {
const Context *ctx = getCtx(); 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 char *BaseCtx::nameOfGroup(GroupId group) const
{ {
const Context *ctx = getCtx(); 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 WireId Context::getNetinfoSourceWire(const NetInfo *net_info) const
@ -620,7 +695,7 @@ void BaseCtx::archInfoToAttributes()
if (ci->attrs.find(id("BEL")) != ci->attrs.end()) { if (ci->attrs.find(id("BEL")) != ci->attrs.end()) {
ci->attrs.erase(ci->attrs.find(id("BEL"))); 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; ci->attrs[id("BEL_STRENGTH")] = (int)ci->belStrength;
} }
if (ci->constr_x != ci->UNCONSTR) if (ci->constr_x != ci->UNCONSTR)
@ -650,10 +725,10 @@ void BaseCtx::archInfoToAttributes()
for (auto &item : ni->wires) { for (auto &item : ni->wires) {
if (!first) if (!first)
routing += ";"; routing += ";";
routing += getCtx()->getWireName(item.first).c_str(this); routing += getCtx()->getWireName(item.first).str(getCtx());
routing += ";"; routing += ";";
if (item.second.pip != PipId()) 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); routing += ";" + std::to_string(item.second.strength);
first = false; first = false;
} }
@ -672,7 +747,7 @@ void BaseCtx::attributesToArchInfo()
if (str != ci->attrs.end()) if (str != ci->attrs.end())
strength = (PlaceStrength)str->second.as_int64(); 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); getCtx()->bindBel(b, ci, strength);
} }

View File

@ -145,6 +145,152 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX IdString>
NEXTPNR_NAMESPACE_BEGIN 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 struct GraphicElement
{ {
enum type_t enum type_t
@ -667,6 +813,9 @@ struct BaseCtx
mutable std::unordered_map<std::string, int> *idstring_str_to_idx; mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
mutable std::vector<const std::string *> *idstring_idx_to_str; 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 // Project settings and config switches
std::unordered_map<IdString, Property> settings; std::unordered_map<IdString, Property> settings;
@ -782,6 +931,12 @@ struct BaseCtx
const char *nameOfPip(PipId pip) const; const char *nameOfPip(PipId pip) const;
const char *nameOfGroup(GroupId group) 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; bool allUiReload = true;

View File

@ -158,8 +158,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
all_placed = true; all_placed = true;
} }
if (ctx->verbose) if (ctx->verbose)
log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx), log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx), ctx->nameOfBel(best_bel));
ctx->getBelName(best_bel).c_str(ctx));
ctx->bindBel(best_bel, cell, STRENGTH_WEAK); ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
cell = ripup_target; cell = ripup_target;
@ -375,7 +374,7 @@ class ConstraintLegaliseWorker
if (confl_cell != nullptr) { if (confl_cell != nullptr) {
if (ctx->verbose) if (ctx->verbose)
log_info(" '%s' already placed at '%s'\n", ctx->nameOf(confl_cell), 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); NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG);
ctx->unbindBel(target); ctx->unbindBel(target);
rippedCells.insert(confl_cell->name); rippedCells.insert(confl_cell->name);
@ -489,7 +488,7 @@ class ConstraintLegaliseWorker
for (auto cell : sorted(ctx->cells)) for (auto cell : sorted(ctx->cells))
if (get_constraints_distance(ctx, cell.second) != 0) 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), 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; return score;
} }
}; };

View File

@ -154,7 +154,7 @@ class SAPlacer
auto loc = cell->attrs.find(ctx->id("BEL")); auto loc = cell->attrs.find(ctx->id("BEL"));
if (loc != cell->attrs.end()) { if (loc != cell->attrs.end()) {
std::string loc_name = loc->second.as_string(); 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()) { if (bel == BelId()) {
log_error("No Bel named \'%s\' located for " log_error("No Bel named \'%s\' located for "
"this chip (processing BEL attribute on \'%s\')\n", "this chip (processing BEL attribute on \'%s\')\n",
@ -409,18 +409,18 @@ class SAPlacer
if (ctx->force) { if (ctx->force) {
log_warning("post-placement validity check failed for Bel '%s' " log_warning("post-placement validity check failed for Bel '%s' "
"(%s)\n", "(%s)\n",
ctx->getBelName(bel).c_str(ctx), cell_text.c_str()); ctx->nameOfBel(bel), cell_text.c_str());
} else { } else {
log_error("post-placement validity check failed for Bel '%s' " log_error("post-placement validity check failed for Bel '%s' "
"(%s)\n", "(%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)) for (auto cell : sorted(ctx->cells))
if (get_constraints_distance(ctx, cell.second) != 0) 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), 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); timing_analysis(ctx);
ctx->unlock(); ctx->unlock();
return true; return true;
@ -563,9 +563,9 @@ class SAPlacer
} }
commit_cost_changes(moveChange); commit_cost_changes(moveChange);
#if 0 #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) 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 #endif
return true; return true;
swap_fail: swap_fail:
@ -590,7 +590,7 @@ class SAPlacer
{ {
BelId oldBel = cell->bel; BelId oldBel = cell->bel;
#if 0 #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 #endif
CellInfo *bound = ctx->getBoundBelCell(newBel); CellInfo *bound = ctx->getBoundBelCell(newBel);
if (bound != nullptr) if (bound != nullptr)

View File

@ -305,7 +305,7 @@ class HeAPPlacer
if (ctx->getBoundBelCell(cell.second->bel) != cell.second) if (ctx->getBoundBelCell(cell.second->bel) != cell.second)
log_error("Found cell %s with mismatched binding\n", cell.first.c_str(ctx)); log_error("Found cell %s with mismatched binding\n", cell.first.c_str(ctx));
if (ctx->debug) 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(); ctx->unlock();
@ -379,7 +379,7 @@ class HeAPPlacer
auto loc = cell->attrs.find(ctx->id("BEL")); auto loc = cell->attrs.find(ctx->id("BEL"));
if (loc != cell->attrs.end()) { if (loc != cell->attrs.end()) {
std::string loc_name = loc->second.as_string(); 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()) { if (bel == BelId()) {
log_error("No Bel named \'%s\' located for " log_error("No Bel named \'%s\' located for "
"this chip (processing BEL attribute on \'%s\')\n", "this chip (processing BEL attribute on \'%s\')\n",

View File

@ -74,6 +74,18 @@ template <> struct string_converter<const IdString>
inline std::string to_str(Context *ctx, IdString id) { return id.str(ctx); } 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 } // namespace PythonConversion
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -885,8 +885,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
auto pip = it->second.pip; auto pip = it->second.pip;
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
delay = ctx->getPipDelay(pip).maxDelay(); delay = ctx->getPipDelay(pip).maxDelay();
log_info(" %1.3f %s\n", ctx->getDelayNS(delay), log_info(" %1.3f %s\n", ctx->getDelayNS(delay), ctx->nameOfPip(pip));
ctx->getPipName(pip).c_str(ctx));
cursor = ctx->getPipSrcWire(pip); cursor = ctx->getPipSrcWire(pip);
} }
} }

View File

@ -59,7 +59,7 @@ template <> struct hash<std::pair<int, NEXTPNR_NAMESPACE_PREFIX BelId>>
return seed; 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>> template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX BelId>>
{ {
std::size_t std::size_t
@ -427,7 +427,7 @@ class TimingOptimiser
if (pn->users.at(i).cell == port->cell && pn->users.at(i).port == port->port) if (pn->users.at(i).cell == port->cell && pn->users.at(i).port == port->port)
crit = net_crit.at(pn->name).criticality.at(i); 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), 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()) if (std::find(path_cells.begin(), path_cells.end(), port->cell->name) != path_cells.end())
continue; continue;
@ -472,10 +472,9 @@ class TimingOptimiser
if (ctx->debug) { if (ctx->debug) {
for (auto cell : path_cells) { for (auto cell : path_cells) {
log_info("Candidate neighbours for %s (%s):\n", cell.c_str(ctx), log_info("Candidate neighbours for %s (%s):\n", cell.c_str(ctx), ctx->nameOfBel(ctx->cells[cell]->bel));
ctx->getBelName(ctx->cells[cell]->bel).c_str(ctx));
for (auto neigh : cell_neighbour_bels.at(cell)) { 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(); CellInfo *cell = ctx->cells.at(rt_entry.first).get();
cell_swap_bel(cell, rt_entry.second); cell_swap_bel(cell, rt_entry.second);
if (ctx->debug) 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 { } else {

View File

@ -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). 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 Cell Methods
----------- -----------
@ -99,15 +103,14 @@ Cell Methods
Get list of cell types that this architecture accepts. Get list of cell types that this architecture accepts.
Bel Methods 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.) 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 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.) 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 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.) 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 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.) Get the name for a group. (Group names must be unique.)

View File

@ -37,17 +37,6 @@
NEXTPNR_NAMESPACE_BEGIN 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) void IdString::initialize_arch(const BaseCtx *ctx)
@ -128,6 +117,22 @@ Arch::Arch(ArchArgs args) : args(args)
bucket.name = bel_type; bucket.name = bel_type;
buckets.push_back(bucket); 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; BelId ret;
auto it = bel_by_name.find(name);
if (it != bel_by_name.end())
return it->second;
Location loc; Location loc;
std::string basename; loc.x = id_to_x.at(name[0]);
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this)); loc.y = id_to_y.at(name[1]);
ret.location = loc; ret.location = loc;
const LocationTypePOD *loci = locInfo(ret); const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < int(loci->bel_data.size()); i++) { 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; ret.index = i;
break; return ret;
} }
} }
if (ret.index >= 0) return BelId();
bel_by_name[name] = ret;
return ret;
} }
BelRange Arch::getBelsByTile(int x, int y) const 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; WireId ret;
auto it = wire_by_name.find(name);
if (it != wire_by_name.end())
return it->second;
Location loc; Location loc;
std::string basename; loc.x = id_to_x.at(name[0]);
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this)); loc.y = id_to_y.at(name[1]);
ret.location = loc; ret.location = loc;
const LocationTypePOD *loci = locInfo(ret); const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < int(loci->wire_data.size()); i++) { 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.index = i;
ret.location = loc; return ret;
break;
} }
} }
if (ret.index >= 0) return WireId();
wire_by_name[name] = ret;
else
ret.location = Location();
return ret;
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
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); auto it = pip_by_name.find(name);
if (it != pip_by_name.end()) if (it != pip_by_name.end())
return it->second; return it->second;
@ -314,7 +310,8 @@ PipId Arch::getPipByName(IdString name) const
PipId ret; PipId ret;
Location loc; Location loc;
std::string basename; 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; ret.location = loc;
const LocationTypePOD *loci = locInfo(ret); const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < int(loci->pip_data.size()); i++) { 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; pip_by_name[getPipName(curr)] = curr;
} }
if (pip_by_name.find(name) == pip_by_name.end()) 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]; return pip_by_name[name];
} }
IdString Arch::getPipName(PipId pip) const IdStringList Arch::getPipName(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
int x = pip.location.x; // TODO: can we improve how pip names are stored/built?
int y = pip.location.y; 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));
std::string src_name = getWireName(getPipSrcWire(pip)).str(this); std::array<IdString, 3> ids{x_ids.at(pip.location.x), y_ids.at(pip.location.y), id(pip_name)};
std::replace(src_name.begin(), src_name.end(), '/', '.'); return IdStringList(ids);
std::string dst_name = getWireName(getPipDstWire(pip)).str(this);
std::replace(dst_name.begin(), dst_name.end(), '/', '.');
return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name);
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@ -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()) for (auto g : getGroups())
if (getGroupName(g) == name) if (getGroupName(g) == name)
@ -1214,7 +1210,7 @@ GroupId Arch::getGroupByName(IdString name) const
return GroupId(); return GroupId();
} }
IdString Arch::getGroupName(GroupId group) const IdStringList Arch::getGroupName(GroupId group) const
{ {
std::string suffix; std::string suffix;
@ -1223,10 +1219,11 @@ IdString Arch::getGroupName(GroupId group) const
suffix = "switchbox"; suffix = "switchbox";
break; break;
default: 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 std::vector<GroupId> Arch::getGroups() const

View File

@ -441,15 +441,18 @@ struct Arch : BaseCtx
const PackageInfoPOD *package_info; const PackageInfoPOD *package_info;
const SpeedGradePOD *speed_grade; const SpeedGradePOD *speed_grade;
mutable std::unordered_map<IdString, BelId> bel_by_name; mutable std::unordered_map<IdStringList, PipId> pip_by_name;
mutable std::unordered_map<IdString, WireId> wire_by_name;
mutable std::unordered_map<IdString, PipId> pip_by_name;
std::vector<CellInfo *> bel_to_cell; std::vector<CellInfo *> bel_to_cell;
std::unordered_map<WireId, NetInfo *> wire_to_net; std::unordered_map<WireId, NetInfo *> wire_to_net;
std::unordered_map<PipId, NetInfo *> pip_to_net; std::unordered_map<PipId, NetInfo *> pip_to_net;
std::unordered_map<WireId, int> wire_fanout; 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; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
@ -471,22 +474,23 @@ struct Arch : BaseCtx
int getGridDimY() const { return chip_info->height; }; int getGridDimY() const { return chip_info->height; };
int getTileBelDimZ(int, int) const { return max_loc_bels; }; int getTileBelDimZ(int, int) const { return max_loc_bels; };
int getTilePipDimZ(int, int) const { return 1; }; 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 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]]); 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()); NPNR_ASSERT(bel != BelId());
std::stringstream name; std::array<IdString, 3> ids{x_ids.at(bel.location.x), y_ids.at(bel.location.y),
name << "X" << bel.location.x << "/Y" << bel.location.y << "/" << locInfo(bel)->bel_data[bel.index].name.get(); id(locInfo(bel)->bel_data[bel.index].name.get())};
return id(name.str()); return IdStringList(ids);
} }
uint32_t getBelChecksum(BelId bel) const { return bel.index; } 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()); NPNR_ASSERT(wire != WireId());
std::array<IdString, 3> ids{x_ids.at(wire.location.x), y_ids.at(wire.location.y),
std::stringstream name; id(locInfo(wire)->wire_data[wire.index].name.get())};
name << "X" << wire.location.x << "/Y" << wire.location.y << "/" return IdStringList(ids);
<< locInfo(wire)->wire_data[wire.index].name.get();
return id(name.str());
} }
IdString getWireType(WireId wire) const IdString getWireType(WireId wire) const
@ -712,8 +714,8 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
PipId getPipByName(IdString name) const; PipId getPipByName(IdStringList name) const;
IdString getPipName(PipId pip) const; IdStringList getPipName(PipId pip) const;
IdString getPipType(PipId pip) const { return IdString(); } IdString getPipType(PipId pip) const { return IdString(); }
@ -891,8 +893,8 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
GroupId getGroupByName(IdString name) const; GroupId getGroupByName(IdStringList name) const;
IdString getGroupName(GroupId group) const; IdStringList getGroupName(GroupId group) const;
std::vector<GroupId> getGroups() const; std::vector<GroupId> getGroups() const;
std::vector<BelId> getGroupBels(GroupId group) const; std::vector<BelId> getGroupBels(GroupId group) const;
std::vector<WireId> getGroupWires(GroupId group) const; std::vector<WireId> getGroupWires(GroupId group) const;

View File

@ -30,7 +30,7 @@ namespace PythonConversion {
template <> struct string_converter<BelId> 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) std::string to_str(Context *ctx, BelId id)
{ {
@ -42,7 +42,7 @@ template <> struct string_converter<BelId>
template <> struct string_converter<WireId> 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) std::string to_str(Context *ctx, WireId id)
{ {
@ -54,7 +54,7 @@ template <> struct string_converter<WireId>
template <> struct string_converter<const 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) std::string to_str(Context *ctx, WireId id)
{ {
@ -66,7 +66,7 @@ template <> struct string_converter<const WireId>
template <> struct string_converter<PipId> 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) std::string to_str(Context *ctx, PipId id)
{ {

View File

@ -811,14 +811,12 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
NetInfo *lsrnet = nullptr; NetInfo *lsrnet = nullptr;
if (ci->ports.find(ctx->id("LSR")) != ci->ports.end() && ci->ports.at(ctx->id("LSR")).net != 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; lsrnet = ci->ports.at(ctx->id("LSR")).net;
if (ctx->getBoundWireNet(ctx->getWireByName( if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR0")) == lsrnet) {
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR0")))) == lsrnet) {
cc.tiles[tname].add_enum("LSR0.SRMODE", cc.tiles[tname].add_enum("LSR0.SRMODE",
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE")); 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")); cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
} }
if (ctx->getBoundWireNet(ctx->getWireByName( if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR1")) == lsrnet) {
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR1")))) == lsrnet) {
cc.tiles[tname].add_enum("LSR1.SRMODE", cc.tiles[tname].add_enum("LSR1.SRMODE",
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE")); 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")); 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; NetInfo *clknet = nullptr;
if (ci->ports.find(ctx->id("CLK")) != ci->ports.end() && ci->ports.at(ctx->id("CLK")).net != 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; clknet = ci->ports.at(ctx->id("CLK")).net;
if (ctx->getBoundWireNet(ctx->getWireByName( if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK0")) == clknet) {
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK0")))) == clknet) {
cc.tiles[tname].add_enum("CLK0.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK")); cc.tiles[tname].add_enum("CLK0.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK"));
} }
if (ctx->getBoundWireNet(ctx->getWireByName( if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK1")) == clknet) {
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK1")))) == clknet) {
cc.tiles[tname].add_enum("CLK1.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK")); 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.find(ctx->id("IOLTO")) == ci->ports.end() ||
ci->ports.at(ctx->id("IOLTO")).net == nullptr)) { ci->ports.at(ctx->id("IOLTO")).net == nullptr)) {
// Tie tristate low if unconnected for outputs or bidir // 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->getWireByLocAndBasename(bel.location, fmt_str("JPADDT" << pio.back()));
WireId jpt_wire = ctx->getWireByName(ctx->id(jpt));
PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin(); PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin();
WireId cib_wire = ctx->getPipSrcWire(jpt_pip); WireId cib_wire = ctx->getPipSrcWire(jpt_pip);
std::string cib_tile = std::string cib_tile =

View File

@ -176,8 +176,8 @@ class Ecp5GlobalRouter
} }
} }
if (upstream.size() > 30000) { if (upstream.size() > 30000) {
log_error("failed to route HPBX%02d00 to %s.%s\n", global_index, log_error("failed to route HPBX%02d00 to %s.%s\n", global_index, ctx->nameOfBel(user.cell->bel),
ctx->getBelName(user.cell->bel).c_str(ctx), user.port.c_str(ctx)); user.port.c_str(ctx));
} }
} }
// Set all the pips we found along the way // Set all the pips we found along the way
@ -238,8 +238,7 @@ class Ecp5GlobalRouter
if (visit.empty() || visit.size() > 50000) { if (visit.empty() || visit.size() > 50000) {
if (allow_fail) if (allow_fail)
return false; return false;
log_error("cannot route global from %s to %s.\n", ctx->getWireName(src).c_str(ctx), log_error("cannot route global from %s to %s.\n", ctx->nameOfWire(src), ctx->nameOfWire(dst));
ctx->getWireName(dst).c_str(ctx));
} }
cursor = visit.front(); cursor = visit.front();
visit.pop(); visit.pop();
@ -300,7 +299,7 @@ class Ecp5GlobalRouter
if (drv.cell == nullptr) { if (drv.cell == nullptr) {
return 0; return 0;
} else if (drv.cell->attrs.count(ctx->id("BEL"))) { } 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 { } else {
// Check if driver is a singleton // Check if driver is a singleton
BelId last_bel; BelId last_bel;
@ -325,8 +324,8 @@ class Ecp5GlobalRouter
} else { } else {
// Check for dedicated routing // Check for dedicated routing
if (has_short_route(ctx->getBelPinWire(drv_bel, drv.port), ctx->getBelPinWire(dcc->bel, id_CLKI))) { 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, // log_info("dedicated route %s -> %s\n", ctx->nameOfWire(ctx->getBelPinWire(drv_bel,
// drv.port)).c_str(ctx), ctx->getBelName(dcc->bel).c_str(ctx)); // drv.port)), ctx->nameOfWire(dcc->bel));
dedicated_routing = true; dedicated_routing = true;
return 0; return 0;
} }
@ -347,8 +346,8 @@ class Ecp5GlobalRouter
while (true) { while (true) {
if (visit.empty() || visit.size() > 10000) { if (visit.empty() || visit.size() > 10000) {
// log_info ("dist %s -> %s = inf\n", ctx->getWireName(src).c_str(ctx), // log_info ("dist %s -> %s = inf\n", ctx->nameOfWire(src),
// ctx->getWireName(dst).c_str(ctx)); // ctx->nameOfWire(dst));
return false; return false;
} }
cursor = visit.front(); cursor = visit.front();
@ -372,7 +371,7 @@ class Ecp5GlobalRouter
cursor = ctx->getPipSrcWire(fnd->second); cursor = ctx->getPipSrcWire(fnd->second);
length++; 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); // length);
return length < thresh; return length < thresh;
} }

View File

@ -522,7 +522,7 @@ class Ecp5Packer
trio->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str()); trio->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str());
} else { } else {
log_info("pin '%s' constrained to Bel '%s'.\n", trio->name.c_str(ctx), 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); trio->attrs[ctx->id("BEL")] = ctx->getBelName(pinBel).str(ctx);
} }
@ -1657,7 +1657,7 @@ class Ecp5Packer
CellInfo *dcu = clki->driver.cell; CellInfo *dcu = clki->driver.cell;
if (!dcu->attrs.count(ctx->id("BEL"))) if (!dcu->attrs.count(ctx->id("BEL")))
log_error("DCU must be constrained to a Bel!\n"); 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()) if (bel == BelId())
log_error("Invalid DCU bel '%s'\n", dcu->attrs.at(ctx->id("BEL")).c_str()); log_error("Invalid DCU bel '%s'\n", dcu->attrs.at(ctx->id("BEL")).c_str());
Loc loc = ctx->getBelLocation(bel); Loc loc = ctx->getBelLocation(bel);
@ -1704,7 +1704,7 @@ class Ecp5Packer
for (auto cell : sorted(ctx->cells)) { for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL"))) 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 // Place PLL connected to fixed drivers such as IO close to their source
for (auto cell : sorted(ctx->cells)) { for (auto cell : sorted(ctx->cells)) {
@ -1716,7 +1716,7 @@ class Ecp5Packer
const CellInfo *drivercell = drivernet->driver.cell; const CellInfo *drivercell = drivernet->driver.cell;
if (!drivercell->attrs.count(ctx->id("BEL"))) if (!drivercell->attrs.count(ctx->id("BEL")))
continue; 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); Loc drvloc = ctx->getBelLocation(drvbel);
BelId closest_pll; BelId closest_pll;
int closest_distance = std::numeric_limits<int>::max(); int closest_distance = std::numeric_limits<int>::max();
@ -1848,12 +1848,12 @@ class Ecp5Packer
WireId next; WireId next;
while (true) { while (true) {
if (upstream.empty() || upstream.size() > 30000) if (upstream.empty() || upstream.size() > 30000)
log_error("failed to route bank %d ECLK%d to %s.%s\n", bank, found_eclk, log_error("failed to route bank %d ECLK%d to %s.%s\n", bank, found_eclk, ctx->nameOfBel(usr_bel),
ctx->getBelName(usr_bel).c_str(ctx), usr_port.name.c_str(ctx)); usr_port.name.c_str(ctx));
next = upstream.front(); next = upstream.front();
upstream.pop(); upstream.pop();
if (ctx->debug) 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); IdString basename = ctx->getWireBasename(next);
if (basename == bnke_name || basename == global_name) { if (basename == bnke_name || basename == global_name) {
break; break;
@ -1913,17 +1913,17 @@ class Ecp5Packer
log_error("DQSBUFM can only be used with a pin-constrained PIO connected to its DQSI input" log_error("DQSBUFM can only be used with a pin-constrained PIO connected to its DQSI input"
"(while processing '%s').\n", "(while processing '%s').\n",
ci->name.c_str(ctx)); 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()); NPNR_ASSERT(pio_bel != BelId());
Loc pio_loc = ctx->getBelLocation(pio_bel); Loc pio_loc = ctx->getBelLocation(pio_bel);
if (pio_loc.z != 0) if (pio_loc.z != 0)
log_error("PIO '%s' does not appear to be a DQS site (expecting an 'A' pin).\n", 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; pio_loc.z = 8;
BelId dqsbuf = ctx->getBelByLocation(pio_loc); BelId dqsbuf = ctx->getBelByLocation(pio_loc);
if (dqsbuf == BelId() || ctx->getBelType(dqsbuf) != id_DQSBUFM) 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", 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); 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); bool got_dqsg = ctx->getPIODQSGroup(pio_bel, dqsbuf_dqsg[ci->name].first, dqsbuf_dqsg[ci->name].second);
NPNR_ASSERT(got_dqsg); 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 " log_error("IOLOGIC functionality (DDR, DELAY, DQS, etc) can only be used with pin-constrained PIO "
"(while processing '%s').\n", "(while processing '%s').\n",
curr->name.c_str(ctx)); 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()); NPNR_ASSERT(bel != BelId());
return bel; return bel;
}; };
auto create_pio_iologic = [&](CellInfo *pio, CellInfo *curr) { auto create_pio_iologic = [&](CellInfo *pio, CellInfo *curr) {
BelId bel = get_pio_bel(pio, curr); BelId bel = get_pio_bel(pio, curr);
log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx), log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx), ctx->nameOfBel(bel));
ctx->getBelName(bel).c_str(ctx));
Loc loc = ctx->getBelLocation(bel); Loc loc = ctx->getBelLocation(bel);
bool s = false; bool s = false;
if (loc.y == 0 || loc.y == (ctx->chip_info->height - 1)) 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("D2"), iol, id_TXDATA2);
replace_port(ci, ctx->id("D3"), iol, id_TXDATA3); replace_port(ci, ctx->id("D3"), iol, id_TXDATA3);
if (ci->type == ctx->id("ODDR71B")) { if (ci->type == ctx->id("ODDR71B")) {
Loc loc = Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
if (loc.z % 2 == 1) if (loc.z % 2 == 1)
log_error("ODDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx)); 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); 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("Q2"), iol, id_RXDATA2);
replace_port(ci, ctx->id("Q3"), iol, id_RXDATA3); replace_port(ci, ctx->id("Q3"), iol, id_RXDATA3);
if (ci->type == ctx->id("IDDR71B")) { if (ci->type == ctx->id("IDDR71B")) {
Loc loc = Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
if (loc.z % 2 == 1) if (loc.z % 2 == 1)
log_error("IDDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx)); 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); replace_port(ci, ctx->id("Q4"), iol, id_RXDATA4);
@ -2579,7 +2576,7 @@ class Ecp5Packer
if (!user.cell->attrs.count(ctx->id("BEL"))) if (!user.cell->attrs.count(ctx->id("BEL")))
continue; continue;
Loc user_loc = ctx->getBelLocation( 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()) { for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) != id_ECLKBRIDGECS) if (ctx->getBelType(bel) != id_ECLKBRIDGECS)
continue; continue;
@ -2594,8 +2591,8 @@ class Ecp5Packer
CellInfo *drv = input->driver.cell; CellInfo *drv = input->driver.cell;
if (!drv->attrs.count(ctx->id("BEL"))) if (!drv->attrs.count(ctx->id("BEL")))
continue; continue;
Loc drv_loc = ctx->getBelLocation( Loc drv_loc =
ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string()))); ctx->getBelLocation(ctx->getBelByNameStr(drv->attrs.at(ctx->id("BEL")).as_string()));
BelId closest; BelId closest;
int closest_x = -1; // aim for same side of chip int closest_x = -1; // aim for same side of chip
for (auto bel : ctx->getBels()) { for (auto bel : ctx->getBels()) {
@ -2639,7 +2636,7 @@ class Ecp5Packer
if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) { if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) {
if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr) if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr)
continue; 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()); NPNR_ASSERT(bel != BelId());
Loc pioLoc = ctx->getBelLocation(bel); Loc pioLoc = ctx->getBelLocation(bel);
if (ci->type == id_DQSBUFM) if (ci->type == id_DQSBUFM)
@ -2683,8 +2680,7 @@ class Ecp5Packer
const NetInfo *eclko = net_or_nullptr(ci, id_ECLKO); const NetInfo *eclko = net_or_nullptr(ci, id_ECLKO);
if (eclki != nullptr && eclki->driver.cell != nullptr) { if (eclki != nullptr && eclki->driver.cell != nullptr) {
if (eclki->driver.cell->type == id_ECLKBRIDGECS) { if (eclki->driver.cell->type == id_ECLKBRIDGECS) {
BelId bel = BelId bel = ctx->getBelByNameStr(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string());
ctx->getBelByName(ctx->id(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string()));
Loc loc = ctx->getBelLocation(bel); Loc loc = ctx->getBelLocation(bel);
ci->attrs[ctx->id("BEL")] = ci->attrs[ctx->id("BEL")] =
ctx->getBelName(ctx->getBelByLocation(Loc(loc.x, loc.y, 15))).str(ctx); ctx->getBelName(ctx->getBelByLocation(Loc(loc.x, loc.y, 15))).str(ctx);
@ -2697,7 +2693,7 @@ class Ecp5Packer
for (auto user : eclko->users) { for (auto user : eclko->users) {
if (user.cell->type == id_TRELLIS_ECLKBUF) { if (user.cell->type == id_TRELLIS_ECLKBUF) {
Loc eckbuf_loc = ctx->getBelLocation( 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()) { for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) != id_ECLKSYNCB) if (ctx->getBelType(bel) != id_ECLKSYNCB)
continue; continue;
@ -2726,7 +2722,7 @@ class Ecp5Packer
const CellInfo *uc = usr.cell; const CellInfo *uc = usr.cell;
if (uc->type != id_DQSBUFM || !uc->attrs.count(ctx->id("BEL"))) if (uc->type != id_DQSBUFM || !uc->attrs.count(ctx->id("BEL")))
continue; 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); Loc dqsb_loc = ctx->getBelLocation(dqsb_bel);
if (dqsb_loc.x > 15) if (dqsb_loc.x > 15)
right_bank_users = true; right_bank_users = true;
@ -2809,7 +2805,7 @@ class Ecp5Packer
CellInfo *drv = clki->driver.cell; CellInfo *drv = clki->driver.cell;
if (drv->type != id_ECLKSYNCB || !drv->attrs.count(ctx->id("BEL"))) if (drv->type != id_ECLKSYNCB || !drv->attrs.count(ctx->id("BEL")))
continue; 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 // Find a CLKDIVF that is routeable from the ECLKSYNC
std::queue<WireId> visit; std::queue<WireId> visit;
visit.push(ctx->getBelPinWire(bel, id_ECLKO)); visit.push(ctx->getBelPinWire(bel, id_ECLKO));

View File

@ -28,31 +28,31 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
WireInfo &Arch::wire_info(IdString wire) WireInfo &Arch::wire_info(IdStringList wire)
{ {
auto w = wires.find(wire); auto w = wires.find(wire);
if (w == wires.end()) 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; return w->second;
} }
PipInfo &Arch::pip_info(IdString pip) PipInfo &Arch::pip_info(IdStringList pip)
{ {
auto p = pips.find(pip); auto p = pips.find(pip);
if (p == pips.end()) 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; return p->second;
} }
BelInfo &Arch::bel_info(IdString bel) BelInfo &Arch::bel_info(IdStringList bel)
{ {
auto b = bels.find(bel); auto b = bels.find(bel);
if (b == bels.end()) 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; 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); NPNR_ASSERT(wires.count(name) == 0);
WireInfo &wi = wires[name]; WireInfo &wi = wires[name];
@ -64,7 +64,8 @@ void Arch::addWire(IdString name, IdString type, int x, int y)
wire_ids.push_back(name); 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); NPNR_ASSERT(pips.count(name) == 0);
PipInfo &pi = pips[name]; 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); 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(bels.count(name) == 0);
NPNR_ASSERT(bel_by_loc.count(loc) == 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); 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); NPNR_ASSERT(bel_info(bel).pins.count(name) == 0);
PinInfo &pi = bel_info(bel).pins[name]; 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}); 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); NPNR_ASSERT(bel_info(bel).pins.count(name) == 0);
PinInfo &pi = bel_info(bel).pins[name]; 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}); 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); NPNR_ASSERT(bel_info(bel).pins.count(name) == 0);
PinInfo &pi = bel_info(bel).pins[name]; 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}); 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) void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic)
{ {
@ -198,11 +199,14 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy)
refreshUiGroup(group); 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; } void Arch::setLutK(int K) { args.K = K; }
@ -212,9 +216,12 @@ void Arch::setDelayScaling(double scale, double offset)
args.delayOffset = 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) if (get_or_default(cellTiming[cell].portClasses, fromPort, TMG_IGNORE) == TMG_IGNORE)
cellTiming[cell].portClasses[fromPort] = TMG_COMB_INPUT; 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; 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; TimingClockingInfo ci;
ci.clock_port = clock; ci.clock_port = clock;
@ -234,7 +241,7 @@ void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock,
cellTiming[cell].portClasses[port] = TMG_REGISTER_INPUT; 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; TimingClockingInfo ci;
ci.clock_port = clock; 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)) if (bels.count(name))
return name; return name;
return BelId(); return BelId();
} }
IdString Arch::getBelName(BelId bel) const { return bel; } IdStringList Arch::getBelName(BelId bel) const { return bel; }
Loc Arch::getBelLocation(BelId bel) const Loc Arch::getBelLocation(BelId bel) const
{ {
@ -321,7 +328,7 @@ WireId Arch::getBelPinWire(BelId bel, IdString pin) const
{ {
const auto &bdata = bels.at(bel); const auto &bdata = bels.at(bel);
if (!bdata.pins.count(pin)) 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; 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)) if (wires.count(name))
return name; return name;
return WireId(); 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; } 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)) if (pips.count(name))
return name; return name;
return PipId(); 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; } 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 std::vector<GroupId> Arch::getGroups() const
{ {
@ -582,8 +589,7 @@ bool Arch::route()
const std::vector<GraphicElement> &Arch::getDecalGraphics(DecalId decal) const const std::vector<GraphicElement> &Arch::getDecalGraphics(DecalId decal) const
{ {
if (!decal_graphics.count(decal)) { if (!decal_graphics.count(decal)) {
std::cerr << "No decal named " << decal.str(this) << std::endl; std::cerr << "No decal named " << decal.str(getCtx()) << std::endl;
log_error("No decal named %s!\n", decal.c_str(this));
} }
return decal_graphics.at(decal); return decal_graphics.at(decal);
} }

View File

@ -36,7 +36,8 @@ struct WireInfo;
struct PipInfo struct PipInfo
{ {
IdString name, type; IdStringList name;
IdString type;
std::map<IdString, std::string> attrs; std::map<IdString, std::string> attrs;
NetInfo *bound_net; NetInfo *bound_net;
WireId srcWire, dstWire; WireId srcWire, dstWire;
@ -47,7 +48,8 @@ struct PipInfo
struct WireInfo struct WireInfo
{ {
IdString name, type; IdStringList name;
IdString type;
std::map<IdString, std::string> attrs; std::map<IdString, std::string> attrs;
NetInfo *bound_net; NetInfo *bound_net;
std::vector<PipId> downhill, uphill; std::vector<PipId> downhill, uphill;
@ -60,14 +62,15 @@ struct WireInfo
struct PinInfo struct PinInfo
{ {
IdString name; IdStringList name;
WireId wire; WireId wire;
PortType type; PortType type;
}; };
struct BelInfo struct BelInfo
{ {
IdString name, type; IdStringList name;
IdString type;
std::map<IdString, std::string> attrs; std::map<IdString, std::string> attrs;
CellInfo *bound_cell; CellInfo *bound_cell;
std::unordered_map<IdString, PinInfo> pins; std::unordered_map<IdString, PinInfo> pins;
@ -78,7 +81,7 @@ struct BelInfo
struct GroupInfo struct GroupInfo
{ {
IdString name; IdStringList name;
std::vector<BelId> bels; std::vector<BelId> bels;
std::vector<WireId> wires; std::vector<WireId> wires;
std::vector<PipId> pips; std::vector<PipId> pips;
@ -117,17 +120,17 @@ struct Arch : BaseCtx
{ {
std::string chipName; std::string chipName;
std::unordered_map<IdString, WireInfo> wires; std::unordered_map<IdStringList, WireInfo> wires;
std::unordered_map<IdString, PipInfo> pips; std::unordered_map<IdStringList, PipInfo> pips;
std::unordered_map<IdString, BelInfo> bels; std::unordered_map<IdStringList, BelInfo> bels;
std::unordered_map<GroupId, GroupInfo> groups; std::unordered_map<GroupId, GroupInfo> groups;
// These functions include useful errors if not found // These functions include useful errors if not found
WireInfo &wire_info(IdString wire); WireInfo &wire_info(IdStringList wire);
PipInfo &pip_info(IdString wire); PipInfo &pip_info(IdStringList wire);
BelInfo &bel_info(IdString 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::unordered_map<Loc, BelId> bel_by_loc;
std::vector<std::vector<std::vector<BelId>>> bels_by_tile; 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>> tileBelDimZ;
std::vector<std::vector<int>> tilePipDimZ; 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 addWire(IdStringList name, IdString type, int x, int y);
void addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay, Loc loc); 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 addBel(IdStringList name, IdString type, Loc loc, bool gb);
void addBelInput(IdString bel, IdString name, IdString wire); void addBelInput(IdStringList bel, IdString name, IdStringList wire);
void addBelOutput(IdString bel, IdString name, IdString wire); void addBelOutput(IdStringList bel, IdString name, IdStringList wire);
void addBelInout(IdString bel, IdString name, IdString wire); void addBelInout(IdStringList bel, IdString name, IdStringList wire);
void addGroupBel(IdString group, IdString bel); void addGroupBel(IdStringList group, IdStringList bel);
void addGroupWire(IdString group, IdString wire); void addGroupWire(IdStringList group, IdStringList wire);
void addGroupPip(IdString group, IdString pip); void addGroupPip(IdStringList group, IdStringList pip);
void addGroupGroup(IdString group, IdString grp); void addGroupGroup(IdStringList group, IdStringList grp);
void addDecalGraphic(DecalId decal, const GraphicElement &graphic); void addDecalGraphic(DecalId decal, const GraphicElement &graphic);
void setWireDecal(WireId wire, DecalXY decalxy); void setWireDecal(WireId wire, DecalXY decalxy);
@ -159,17 +162,17 @@ struct Arch : BaseCtx
void setBelDecal(BelId bel, DecalXY decalxy); void setBelDecal(BelId bel, DecalXY decalxy);
void setGroupDecal(GroupId group, DecalXY decalxy); void setGroupDecal(GroupId group, DecalXY decalxy);
void setWireAttr(IdString wire, IdString key, const std::string &value); void setWireAttr(IdStringList wire, IdString key, const std::string &value);
void setPipAttr(IdString pip, IdString key, const std::string &value); void setPipAttr(IdStringList pip, IdString key, const std::string &value);
void setBelAttr(IdString bel, IdString key, const std::string &value); void setBelAttr(IdStringList bel, IdString key, const std::string &value);
void setLutK(int K); void setLutK(int K);
void setDelayScaling(double scale, double offset); void setDelayScaling(double scale, double offset);
void addCellTimingClock(IdString cell, IdString port); void addCellTimingClock(IdStringList cell, IdString port);
void addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay); void addCellTimingDelay(IdStringList cell, IdString fromPort, IdString toPort, DelayInfo delay);
void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold); void addCellTimingSetupHold(IdStringList cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold);
void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq); void addCellTimingClockToOut(IdStringList cell, IdString port, IdString clock, DelayInfo clktoq);
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Common Arch API. Every arch must provide the following methods. // Common Arch API. Every arch must provide the following methods.
@ -187,9 +190,10 @@ struct Arch : BaseCtx
int getGridDimY() const { return gridDimY; } int getGridDimY() const { return gridDimY; }
int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; } int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; }
int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; } int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; }
char getNameDelimiter() const { return '/'; }
BelId getBelByName(IdString name) const; BelId getBelByName(IdStringList name) const;
IdString getBelName(BelId bel) const; IdStringList getBelName(BelId bel) const;
Loc getBelLocation(BelId bel) const; Loc getBelLocation(BelId bel) const;
BelId getBelByLocation(Loc loc) const; BelId getBelByLocation(Loc loc) const;
const std::vector<BelId> &getBelsByTile(int x, int y) 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; PortType getBelPinType(BelId bel, IdString pin) const;
std::vector<IdString> getBelPins(BelId bel) const; std::vector<IdString> getBelPins(BelId bel) const;
WireId getWireByName(IdString name) const; WireId getWireByName(IdStringList name) const;
IdString getWireName(WireId wire) const; IdStringList getWireName(WireId wire) const;
IdString getWireType(WireId wire) const; IdString getWireType(WireId wire) const;
const std::map<IdString, std::string> &getWireAttrs(WireId wire) const; const std::map<IdString, std::string> &getWireAttrs(WireId wire) const;
uint32_t getWireChecksum(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<WireId> &getWires() const;
const std::vector<BelPin> &getWireBelPins(WireId wire) const; const std::vector<BelPin> &getWireBelPins(WireId wire) const;
PipId getPipByName(IdString name) const; PipId getPipByName(IdStringList name) const;
IdString getPipName(PipId pip) const; IdStringList getPipName(PipId pip) const;
IdString getPipType(PipId pip) const; IdString getPipType(PipId pip) const;
const std::map<IdString, std::string> &getPipAttrs(PipId pip) const; const std::map<IdString, std::string> &getPipAttrs(PipId pip) const;
uint32_t getPipChecksum(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> &getPipsDownhill(WireId wire) const;
const std::vector<PipId> &getPipsUphill(WireId wire) const; const std::vector<PipId> &getPipsUphill(WireId wire) const;
GroupId getGroupByName(IdString name) const; GroupId getGroupByName(IdStringList name) const;
IdString getGroupName(GroupId group) const; IdStringList getGroupName(GroupId group) const;
std::vector<GroupId> getGroups() const; std::vector<GroupId> getGroups() const;
const std::vector<BelId> &getGroupBels(GroupId group) const; const std::vector<BelId> &getGroupBels(GroupId group) const;
const std::vector<WireId> &getGroupWires(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> getCellTypes() const
{ {
std::vector<IdString> cell_types; std::unordered_set<IdString> cell_types;
cell_types.reserve(bels.size());
for (auto bel : bels) { 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(); } std::vector<BelBucketId> getBelBuckets() const { return getCellTypes(); }

View File

@ -35,6 +35,7 @@ template <> struct string_converter<const IdString &>
std::string to_str(Context *ctx, const IdString &id) { return id.str(ctx); } std::string to_str(Context *ctx, const IdString &id) { return id.str(ctx); }
}; };
} // namespace PythonConversion } // namespace PythonConversion
void arch_wrap_python(py::module &m) 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"); pass_through<float>>::def_wrap(ctx_cls, "addClock");
// Generic arch construction API // 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", conv_from_str<IdString>, pass_through<int>, pass_through<int>>::def_wrap(ctx_cls, "addWire",
"name"_a, "type"_a, "x"_a, "name"_a, "type"_a, "x"_a,
"y"_a); "y"_a);
fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdString>, fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdStringList>,
conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, pass_through<DelayInfo>, conv_from_str<IdString>, conv_from_str<IdStringList>, conv_from_str<IdStringList>,
pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, "srcWire"_a, "dstWire"_a, pass_through<DelayInfo>, pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a,
"delay"_a, "loc"_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", conv_from_str<IdString>, pass_through<Loc>, pass_through<bool>>::def_wrap(ctx_cls, "addBel",
"name"_a, "type"_a, "name"_a, "type"_a,
"loc"_a, "gb"_a); "loc"_a, "gb"_a);
fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<IdString>, fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<IdStringList>,
conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addBelInput", "bel"_a, conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInput", "bel"_a,
"name"_a, "wire"_a); "name"_a, "wire"_a);
fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<IdString>, fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<IdStringList>,
conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a, conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a,
"name"_a, "wire"_a); "name"_a, "wire"_a);
fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<IdString>, fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<IdStringList>,
conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addBelInout", "bel"_a, conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInout", "bel"_a,
"name"_a, "wire"_a); "name"_a, "wire"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addGroupBel), &Context::addGroupBel, conv_from_str<IdString>, fn_wrapper_2a_v<Context, decltype(&Context::addGroupBel), &Context::addGroupBel, conv_from_str<IdStringList>,
conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a); 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<IdString>, fn_wrapper_2a_v<Context, decltype(&Context::addGroupWire), &Context::addGroupWire, conv_from_str<IdStringList>,
conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a); 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<IdString>, fn_wrapper_2a_v<Context, decltype(&Context::addGroupPip), &Context::addGroupPip, conv_from_str<IdStringList>,
conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a); 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<IdString>, fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupPip, conv_from_str<IdStringList>,
conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a); 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>, 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")); 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); pass_through<double>>::def_wrap(ctx_cls, "setDelayScaling", "scale"_a, "offset"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addCellTimingClock), &Context::addCellTimingClock, 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, conv_from_str<IdStringList>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addCellTimingClock",
"port"_a); "cell"_a, "port"_a);
fn_wrapper_4a_v<Context, decltype(&Context::addCellTimingDelay), &Context::addCellTimingDelay, 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, pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingDelay", "cell"_a, "fromPort"_a,
"toPort"_a, "delay"_a); "toPort"_a, "delay"_a);
fn_wrapper_5a_v<Context, decltype(&Context::addCellTimingSetupHold), &Context::addCellTimingSetupHold, 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>, conv_from_str<IdStringList>, conv_from_str<IdString>, conv_from_str<IdString>,
pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingSetupHold", "cell"_a, "port"_a, "clock"_a, pass_through<DelayInfo>, pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingSetupHold",
"setup"_a, "hold"_a); "cell"_a, "port"_a, "clock"_a,
"setup"_a, "hold"_a);
fn_wrapper_4a_v<Context, decltype(&Context::addCellTimingClockToOut), &Context::addCellTimingClockToOut, fn_wrapper_4a_v<Context, decltype(&Context::addCellTimingClockToOut), &Context::addCellTimingClockToOut,
conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>,
pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingClockToOut", "cell"_a, "port"_a, pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingClockToOut", "cell"_a, "port"_a,

View File

@ -46,11 +46,11 @@ struct DelayInfo
} }
}; };
typedef IdString BelId; typedef IdStringList BelId;
typedef IdString WireId; typedef IdStringList WireId;
typedef IdString PipId; typedef IdStringList PipId;
typedef IdString GroupId; typedef IdStringList GroupId;
typedef IdString DecalId; typedef IdStringList DecalId;
typedef IdString BelBucketId; typedef IdString BelBucketId;
struct ArchNetInfo struct ArchNetInfo

View File

@ -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)) if (bels.count(name[0]))
return name; return name[0];
return BelId(); 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 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)) if (wires.count(name[0]))
return name; return name[0];
return WireId(); 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; } 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)) if (pips.count(name[0]))
return name; return name[0];
return PipId(); 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; } 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 std::vector<GroupId> Arch::getGroups() const
{ {

View File

@ -323,9 +323,13 @@ struct Arch : BaseCtx
int getGridDimY() const { return gridDimY; } int getGridDimY() const { return gridDimY; }
int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; } int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; }
int getTilePipDimZ(int x, int y) const { return tilePipDimZ[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; BelId getBelByName(IdStringList name) const;
IdString getBelName(BelId bel) const; IdStringList getBelName(BelId bel) const;
Loc getBelLocation(BelId bel) const; Loc getBelLocation(BelId bel) const;
BelId getBelByLocation(Loc loc) const; BelId getBelByLocation(Loc loc) const;
const std::vector<BelId> &getBelsByTile(int x, int y) 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; PortType getBelPinType(BelId bel, IdString pin) const;
std::vector<IdString> getBelPins(BelId bel) const; std::vector<IdString> getBelPins(BelId bel) const;
WireId getWireByName(IdString name) const; WireId getWireByName(IdStringList name) const;
IdString getWireName(WireId wire) const; IdStringList getWireName(WireId wire) const;
IdString getWireType(WireId wire) const; IdString getWireType(WireId wire) const;
const std::map<IdString, std::string> &getWireAttrs(WireId wire) const; const std::map<IdString, std::string> &getWireAttrs(WireId wire) const;
uint32_t getWireChecksum(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<WireId> &getWires() const;
const std::vector<BelPin> &getWireBelPins(WireId wire) const; const std::vector<BelPin> &getWireBelPins(WireId wire) const;
PipId getPipByName(IdString name) const; PipId getPipByName(IdStringList name) const;
IdString getPipName(PipId pip) const; IdStringList getPipName(PipId pip) const;
IdString getPipType(PipId pip) const; IdString getPipType(PipId pip) const;
const std::map<IdString, std::string> &getPipAttrs(PipId pip) const; const std::map<IdString, std::string> &getPipAttrs(PipId pip) const;
uint32_t getPipChecksum(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> &getPipsDownhill(WireId wire) const;
const std::vector<PipId> &getPipsUphill(WireId wire) const; const std::vector<PipId> &getPipsUphill(WireId wire) const;
GroupId getGroupByName(IdString name) const; GroupId getGroupByName(IdStringList name) const;
IdString getGroupName(GroupId group) const; IdStringList getGroupName(GroupId group) const;
std::vector<GroupId> getGroups() const; std::vector<GroupId> getGroups() const;
const std::vector<BelId> &getGroupBels(GroupId group) const; const std::vector<BelId> &getGroupBels(GroupId group) const;
const std::vector<WireId> &getGroupWires(GroupId group) const; const std::vector<WireId> &getGroupWires(GroupId group) const;

View File

@ -340,11 +340,9 @@ void DesignWidget::newContext(Context *ctx)
} }
getTreeByElementType(ElementType::CELL) getTreeByElementType(ElementType::CELL)
->loadData(ctx, ->loadData(ctx, std::unique_ptr<TreeModel::IdList>(new TreeModel::IdList(ElementType::CELL)));
std::unique_ptr<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::CELL)));
getTreeByElementType(ElementType::NET) getTreeByElementType(ElementType::NET)
->loadData(ctx, ->loadData(ctx, std::unique_ptr<TreeModel::IdList>(new TreeModel::IdList(ElementType::NET)));
std::unique_ptr<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::NET)));
} }
updateTree(); updateTree();
} }
@ -357,10 +355,10 @@ void DesignWidget::updateTree()
while (i != highlightSelected.end()) { while (i != highlightSelected.end()) {
QMap<TreeModel::Item *, int>::iterator prev = i; QMap<TreeModel::Item *, int>::iterator prev = i;
++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); 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); 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_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->mutex); std::lock_guard<std::mutex> lock(ctx->mutex);
std::vector<IdString> cells; std::vector<IdStringList> cells;
for (auto &pair : ctx->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) { for (auto &pair : ctx->nets) {
nets.push_back(pair.first); nets.push_back(IdStringList(pair.first));
} }
getTreeByElementType(ElementType::CELL)->updateElements(cells); getTreeByElementType(ElementType::CELL)->updateElements(cells);
@ -603,7 +601,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
clearProperties(); clearProperties();
IdString c = clickItem->id(); IdStringList c = clickItem->id();
Q_EMIT selected(getDecals(type, c), false); Q_EMIT selected(getDecals(type, c), false);
if (type == ElementType::BEL) { if (type == ElementType::BEL) {
@ -613,7 +611,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
BelId bel = ctx->getBelByName(c); BelId bel = ctx->getBelByName(c);
QtProperty *topItem = addTopLevelProperty("Bel"); 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::String, "Type", ctx->getBelType(bel).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel));
addProperty(topItem, QVariant::String, "Bound Cell", ctx->nameOf(ctx->getBoundBelCell(bel)), ElementType::CELL); 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::String, "Name", item.c_str(ctx));
addProperty(portInfoItem, QVariant::Int, "Type", int(ctx->getBelPinType(bel, item))); addProperty(portInfoItem, QVariant::Int, "Type", int(ctx->getBelPinType(bel, item)));
WireId wire = ctx->getBelPinWire(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) { } else if (type == ElementType::WIRE) {
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex); 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); WireId wire = ctx->getWireByName(c);
QtProperty *topItem = addTopLevelProperty("Wire"); 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::String, "Type", ctx->getWireType(wire).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire)); 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, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Wire", addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->nameOfWire(ctx->getConflictingWireWire(wire)),
ctx->getWireName(ctx->getConflictingWireWire(wire)).c_str(ctx), ElementType::WIRE); ElementType::WIRE);
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)), addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)),
ElementType::NET); ElementType::NET);
@ -666,7 +664,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
for (const auto &item : ctx->getWireBelPins(wire)) { for (const auto &item : ctx->getWireBelPins(wire)) {
QString belname = ""; QString belname = "";
if (item.bel != BelId()) if (item.bel != BelId())
belname = ctx->getBelName(item.bel).c_str(ctx); belname = ctx->nameOfBel(item.bel);
QString pinname = item.pin.c_str(ctx); QString pinname = item.pin.c_str(ctx);
QtProperty *dhItem = addSubGroup(belpinsItem, belname + "-" + pinname); QtProperty *dhItem = addSubGroup(belpinsItem, belname + "-" + pinname);
@ -677,7 +675,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
int counter = 0; int counter = 0;
QtProperty *pipsDownItem = addSubGroup(topItem, "Pips Downhill"); QtProperty *pipsDownItem = addSubGroup(topItem, "Pips Downhill");
for (const auto &item : ctx->getPipsDownhill(wire)) { 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++; counter++;
if (counter == 50) { if (counter == 50) {
addProperty(pipsDownItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE); 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; counter = 0;
QtProperty *pipsUpItem = addSubGroup(topItem, "Pips Uphill"); QtProperty *pipsUpItem = addSubGroup(topItem, "Pips Uphill");
for (const auto &item : ctx->getPipsUphill(wire)) { 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++; counter++;
if (counter == 50) { if (counter == 50) {
addProperty(pipsUpItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE); 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); PipId pip = ctx->getPipByName(c);
QtProperty *topItem = addTopLevelProperty("Pip"); 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::String, "Type", ctx->getPipType(pip).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
if (ctx->getConflictingPipWire(pip) != WireId()) { if (ctx->getConflictingPipWire(pip) != WireId()) {
addProperty(topItem, QVariant::String, "Conflicting Wire", addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->nameOfWire(ctx->getConflictingPipWire(pip)),
ctx->getWireName(ctx->getConflictingPipWire(pip)).c_str(ctx), ElementType::WIRE); ElementType::WIRE);
} else { } else {
addProperty(topItem, QVariant::String, "Conflicting Wire", "", ElementType::NONE); addProperty(topItem, QVariant::String, "Conflicting Wire", "", ElementType::NONE);
} }
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)), addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)),
ElementType::NET); ElementType::NET);
addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx), addProperty(topItem, QVariant::String, "Src Wire", ctx->nameOfWire(ctx->getPipSrcWire(pip)), ElementType::WIRE);
ElementType::WIRE); addProperty(topItem, QVariant::String, "Dest Wire", ctx->nameOfWire(ctx->getPipDstWire(pip)),
addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx),
ElementType::WIRE); ElementType::WIRE);
QtProperty *attrsItem = addSubGroup(topItem, "Attributes"); 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_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->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"); QtProperty *topItem = addTopLevelProperty("Net");
@ -769,14 +766,13 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
QtProperty *wiresItem = addSubGroup(topItem, "Wires"); QtProperty *wiresItem = addSubGroup(topItem, "Wires");
for (auto &item : net->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); QtProperty *wireItem = addSubGroup(wiresItem, name);
addProperty(wireItem, QVariant::String, "Wire", name, ElementType::WIRE); addProperty(wireItem, QVariant::String, "Wire", name, ElementType::WIRE);
if (item.second.pip != PipId()) if (item.second.pip != PipId())
addProperty(wireItem, QVariant::String, "Pip", ctx->getPipName(item.second.pip).c_str(ctx), addProperty(wireItem, QVariant::String, "Pip", ctx->nameOfPip(item.second.pip), ElementType::PIP);
ElementType::PIP);
else else
addProperty(wireItem, QVariant::String, "Pip", "", ElementType::PIP); 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_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->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"); QtProperty *topItem = addTopLevelProperty("Cell");
addProperty(topItem, QVariant::String, "Name", cell->name.c_str(ctx)); addProperty(topItem, QVariant::String, "Name", cell->name.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", cell->type.c_str(ctx)); addProperty(topItem, QVariant::String, "Type", cell->type.c_str(ctx));
if (cell->bel != BelId()) 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 else
addProperty(topItem, QVariant::String, "Bel", "", ElementType::BEL); addProperty(topItem, QVariant::String, "Bel", "", ElementType::BEL);
addProperty(topItem, QVariant::Int, "Bel strength", int(cell->belStrength)); 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; std::vector<DecalXY> decals;
switch (type) { switch (type) {
@ -861,7 +857,7 @@ std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
} }
} break; } break;
case ElementType::NET: { case ElementType::NET: {
NetInfo *net = ctx->nets.at(value).get(); NetInfo *net = ctx->nets.at(value[0]).get();
for (auto &item : net->wires) { for (auto &item : net->wires) {
decals.push_back(ctx->getWireDecal(item.first)); decals.push_back(ctx->getWireDecal(item.first));
if (item.second.pip != PipId()) { if (item.second.pip != PipId()) {
@ -870,7 +866,7 @@ std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
} }
} break; } break;
case ElementType::CELL: { case ElementType::CELL: {
CellInfo *cell = ctx->cells.at(value).get(); CellInfo *cell = ctx->cells.at(value[0]).get();
if (cell->bel != BelId()) { if (cell->bel != BelId()) {
decals.push_back(ctx->getBelDecal(cell->bel)); decals.push_back(ctx->getBelDecal(cell->bel));
} }

View File

@ -71,7 +71,7 @@ class DesignWidget : public QWidget
int getElementIndex(ElementType type); int getElementIndex(ElementType type);
void updateButtons(); void updateButtons();
void addToHistory(int tab, QModelIndex item); 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 updateHighlightGroup(QList<TreeModel::Item *> item, int group);
void clearAllSelectionModels(); void clearAllSelectionModels();
Q_SIGNALS: Q_SIGNALS:

View File

@ -779,22 +779,22 @@ void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event)
rendererArgs_->x = event->x(); rendererArgs_->x = event->x();
rendererArgs_->y = event->y(); rendererArgs_->y = event->y();
if (closest.type == ElementType::BEL) { 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); CellInfo *cell = ctx_->getBoundBelCell(closest.bel);
if (cell != nullptr) if (cell != nullptr)
rendererArgs_->hintText += std::string("\nCELL\n") + ctx_->nameOf(cell); rendererArgs_->hintText += std::string("\nCELL\n") + ctx_->nameOf(cell);
} else if (closest.type == ElementType::WIRE) { } 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); NetInfo *net = ctx_->getBoundWireNet(closest.wire);
if (net != nullptr) if (net != nullptr)
rendererArgs_->hintText += std::string("\nNET\n") + ctx_->nameOf(net); rendererArgs_->hintText += std::string("\nNET\n") + ctx_->nameOf(net);
} else if (closest.type == ElementType::PIP) { } 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); NetInfo *net = ctx_->getBoundPipNet(closest.pip);
if (net != nullptr) if (net != nullptr)
rendererArgs_->hintText += std::string("\nNET\n") + ctx_->nameOf(net); rendererArgs_->hintText += std::string("\nNET\n") + ctx_->nameOf(net);
} else if (closest.type == ElementType::GROUP) { } 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 } else
rendererArgs_->hintText = ""; rendererArgs_->hintText = "";

View File

@ -26,7 +26,7 @@ NEXTPNR_NAMESPACE_BEGIN
namespace TreeModel { namespace TreeModel {
// converts 'aa123bb432' -> ['aa', '123', 'bb', '432'] // 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; std::vector<QString> res;
QString current_part; QString current_part;
@ -53,12 +53,12 @@ std::vector<QString> IdStringList::alphaNumSplit(const QString &str)
return res; return res;
} }
void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements) void IdList::updateElements(Context *ctx, std::vector<IdStringList> elements)
{ {
bool changed = false; bool changed = false;
// For any elements that are not yet in managed_, created them. // 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) { for (auto elem : elements) {
element_set.insert(elem); element_set.insert(elem);
auto existing = managed_.find(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_) { for (const auto &child : children_) {
if (limit != -1 && results.size() > limit) if (limit != -1 && results.size() > limit)
@ -157,7 +157,7 @@ void Model::loadData(Context *ctx, std::unique_ptr<Item> data)
endResetModel(); endResetModel();
} }
void Model::updateElements(std::vector<IdString> elements) void Model::updateElements(std::vector<IdStringList> elements)
{ {
if (!ctx_) if (!ctx_)
return; return;

View File

@ -95,16 +95,16 @@ class Item
int indexOf(Item *child) { return children_.indexOf(child, 0); } int indexOf(Item *child) { return children_.indexOf(child, 0); }
// Arch id and type that correspond to this element. // 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; } virtual ElementType type() const { return ElementType::NONE; }
// Lazy loading methods. // Lazy loading methods.
virtual bool canFetchMore() const { return false; } virtual bool canFetchMore() const { return false; }
virtual void fetchMore() {} 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 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() virtual ~Item()
{ {
@ -118,46 +118,46 @@ class Item
class IdStringItem : public Item class IdStringItem : public Item
{ {
private: private:
IdString id_; IdStringList id_;
ElementType type_; ElementType type_;
public: public:
IdStringItem(Context *ctx, IdString str, Item *parent, ElementType type) IdStringItem(Context *ctx, IdStringList str, Item *parent, ElementType type)
: Item(QString(str.c_str(ctx)), parent), id_(str), type_(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_; } 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 // a vector of IdStrings. It will render each IdStrings as a child, with the
// list sorted in a smart way. // list sorted in a smart way.
class IdStringList : public Item class IdList : public Item
{ {
private: private:
// Children that we manage the memory for, stored for quick lookup from // Children that we manage the memory for, stored for quick lookup from
// IdString to child. // 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. // Type of children that the list creates.
ElementType child_type_; ElementType child_type_;
public: 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. // 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 // Split a name into alpha/non-alpha parts, which is then used for sorting
// of children. // of children.
static std::vector<QString> alphaNumSplit(const QString &str); static std::vector<QString> alphaNumSplit(const QString &str);
// getById finds a child for the given IdString. // 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. // (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. // Find children that contain the given text.
virtual void search(QList<Item *> &results, QString text, int limit) override; 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. // A map from tile (X,Y) to list of ElementTs in that tile.
using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>; using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>;
// A method that converts an ElementT to an IdString. // A method that converts an ElementT to an IdString.
using ElementGetter = std::function<IdString(Context *, ElementT)>; using ElementGetter = std::function<IdStringList(Context *, ElementT)>;
private: private:
Context *ctx_; Context *ctx_;
@ -184,7 +184,7 @@ template <typename ElementT> class ElementList : public Item
ElementGetter getter_; ElementGetter getter_;
// Children that we manage the memory for, stored for quick lookup from // Children that we manage the memory for, stored for quick lookup from
// IdString to child. // 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. // Type of children that he list creates.
ElementType child_type_; ElementType child_type_;
@ -209,9 +209,10 @@ template <typename ElementT> class ElementList : public Item
size_t end = std::min(start + count, elements()->size()); size_t end = std::min(start + count, elements()->size());
for (size_t i = start; i < end; i++) { for (size_t i = start; i < end; i++) {
auto idstring = getter_(ctx_, elements()->at(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_); QString prefix = QString("X%1/Y%2/").arg(x_).arg(y_);
if (name.startsWith(prefix)) if (name.startsWith(prefix))
name.remove(0, prefix.size()); name.remove(0, prefix.size());
@ -224,7 +225,7 @@ template <typename ElementT> class ElementList : public Item
virtual void fetchMore() override { fetchMore(100); } virtual void fetchMore() override { fetchMore(100); }
// getById finds a child for the given IdString. // 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... // Search requires us to load all our elements...
while (canFetchMore()) 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. // A map from tile (X,Y) to list of ElementTs in that tile.
using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>; using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>;
// A method that converts an ElementT to an IdString. // A method that converts an ElementT to an IdString.
using ElementGetter = std::function<IdString(Context *, ElementT)>; using ElementGetter = std::function<IdStringList(Context *, ElementT)>;
private: private:
Context *ctx_; Context *ctx_;
@ -319,7 +320,7 @@ template <typename ElementT> class ElementXYRoot : public Item
} }
// getById finds a child for the given IdString. // 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. // For now, scan linearly all ElementLists.
// TODO(q3k) fix this once we have tree API from arch // TODO(q3k) fix this once we have tree API from arch
@ -353,7 +354,7 @@ class Model : public QAbstractItemModel
~Model(); ~Model();
void loadData(Context *ctx, std::unique_ptr<Item> data); 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; Item *nodeFromIndex(const QModelIndex &idx) const;
QModelIndex indexFromNode(Item *node) QModelIndex indexFromNode(Item *node)
{ {
@ -366,7 +367,7 @@ class Model : public QAbstractItemModel
QList<QModelIndex> search(QString text); 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 // Override QAbstractItemModel methods
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;

View File

@ -110,6 +110,17 @@ Arch::Arch(ArchArgs args) : args(args)
if (package_info == nullptr) if (package_info == nullptr)
log_error("Unsupported package '%s'.\n", args.package.c_str()); 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_carry.resize(chip_info->bel_data.size());
bel_to_cell.resize(chip_info->bel_data.size()); bel_to_cell.resize(chip_info->bel_data.size());
wire_to_net.resize(chip_info->wire_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; BelId ret;
if (bel_by_name.empty()) { if (bel_by_name.empty()) {
for (size_t i = 0; i < chip_info->bel_data.size(); i++) for (size_t i = 0; i < chip_info->bel_data.size(); i++) {
bel_by_name[id(chip_info->bel_data[i].name.get())] = i; BelId b;
b.index = i;
bel_by_name[getBelName(b)] = i;
}
} }
auto it = bel_by_name.find(name); 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; WireId ret;
if (wire_by_name.empty()) { if (wire_by_name.empty()) {
for (int i = 0; i < int(chip_info->wire_data.size()); i++) for (int i = 0; i < int(chip_info->wire_data.size()); i++) {
wire_by_name[id(chip_info->wire_data[i].name.get())] = i; WireId w;
w.index = i;
wire_by_name[getWireName(w)] = i;
}
} }
auto it = wire_by_name.find(name); 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; PipId ret;
@ -446,24 +463,21 @@ PipId Arch::getPipByName(IdString name) const
return ret; return ret;
} }
IdString Arch::getPipName(PipId pip) const IdStringList Arch::getPipName(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
#if 1
int x = chip_info->pip_data[pip.index].x; int x = chip_info->pip_data[pip.index].x;
int y = chip_info->pip_data[pip.index].y; 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(); auto &src_wire = chip_info->wire_data[chip_info->pip_data[pip.index].src];
std::replace(src_name.begin(), src_name.end(), '/', '.'); 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::string src_name = stringf("%d.%d.%s", int(src_wire.name_x), int(src_wire.name_y), src_wire.name.get());
std::replace(dst_name.begin(), dst_name.end(), '/', '.'); 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); std::array<IdString, 3> ids{x_ids.at(x), y_ids.at(y), id(src_name + ".->." + dst_name)};
#else return IdStringList(ids);
return id(chip_info->pip_data[pip.index].name.get());
#endif
} }
IdString Arch::getPipType(PipId pip) const { return IdString(); } 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()) for (auto g : getGroups())
if (getGroupName(g) == name) if (getGroupName(g) == name)
@ -511,7 +525,7 @@ GroupId Arch::getGroupByName(IdString name) const
return GroupId(); return GroupId();
} }
IdString Arch::getGroupName(GroupId group) const IdStringList Arch::getGroupName(GroupId group) const
{ {
std::string suffix; std::string suffix;
@ -553,7 +567,8 @@ IdString Arch::getGroupName(GroupId group) const
return IdString(); 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 std::vector<GroupId> Arch::getGroups() const

View File

@ -91,6 +91,8 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD {
}; };
RelPtr<char> name; RelPtr<char> name;
int8_t name_x, name_y;
int16_t padding;
RelSlice<int32_t> pips_uphill, pips_downhill; RelSlice<int32_t> pips_uphill, pips_downhill;
RelSlice<BelPortPOD> bel_pins; RelSlice<BelPortPOD> bel_pins;
@ -378,9 +380,9 @@ struct Arch : BaseCtx
const ChipInfoPOD *chip_info; const ChipInfoPOD *chip_info;
const PackageInfoPOD *package_info; const PackageInfoPOD *package_info;
mutable std::unordered_map<IdString, int> bel_by_name; mutable std::unordered_map<IdStringList, int> bel_by_name;
mutable std::unordered_map<IdString, int> wire_by_name; mutable std::unordered_map<IdStringList, int> wire_by_name;
mutable std::unordered_map<IdString, int> pip_by_name; mutable std::unordered_map<IdStringList, int> pip_by_name;
mutable std::unordered_map<Loc, int> bel_by_loc; mutable std::unordered_map<Loc, int> bel_by_loc;
std::vector<bool> bel_carry; std::vector<bool> bel_carry;
@ -389,6 +391,11 @@ struct Arch : BaseCtx
std::vector<NetInfo *> pip_to_net; std::vector<NetInfo *> pip_to_net;
std::vector<WireId> switches_locked; 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; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
@ -407,15 +414,18 @@ struct Arch : BaseCtx
int getGridDimY() const { return chip_info->height; } int getGridDimY() const { return chip_info->height; }
int getTileBelDimZ(int, int) const { return 8; } int getTileBelDimZ(int, int) const { return 8; }
int getTilePipDimZ(int, int) const { return 1; } 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()); 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; } 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()); 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; 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) void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{ {
@ -703,7 +715,7 @@ struct Arch : BaseCtx
return loc; return loc;
} }
IdString getPipName(PipId pip) const; IdStringList getPipName(PipId pip) const;
IdString getPipType(PipId pip) const; IdString getPipType(PipId pip) const;
std::vector<std::pair<IdString, std::string>> getPipAttrs(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; GroupId getGroupByName(IdStringList name) const;
IdString getGroupName(GroupId group) const; IdStringList getGroupName(GroupId group) const;
std::vector<GroupId> getGroups() const; std::vector<GroupId> getGroups() const;
std::vector<BelId> getGroupBels(GroupId group) const; std::vector<BelId> getGroupBels(GroupId group) const;
std::vector<WireId> getGroupWires(GroupId group) const; std::vector<WireId> getGroupWires(GroupId group) const;
@ -895,7 +907,7 @@ struct Arch : BaseCtx
int getDrivenGlobalNetwork(BelId bel) const int getDrivenGlobalNetwork(BelId bel) const
{ {
NPNR_ASSERT(getBelType(bel) == id_SB_GB); 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()); return std::stoi(std::string("") + glb_net.str(this).back());
} }

View File

@ -142,7 +142,7 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
break; break;
// Are we perhaps a PAD INPUT Bel that can be placed here? // 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; return true;
// Conflict // Conflict

View File

@ -778,7 +778,7 @@ def add_bel_output(bel, wire, port):
def add_bel_lc(x, y, z): def add_bel_lc(x, y, z):
bel = len(bel_name) 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_type.append("ICESTORM_LC")
bel_pos.append((x, y, z)) bel_pos.append((x, y, z))
bel_wires.append(list()) bel_wires.append(list())
@ -837,7 +837,7 @@ def add_bel_lc(x, y, z):
def add_bel_io(x, y, z): def add_bel_io(x, y, z):
bel = len(bel_name) 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_type.append("SB_IO")
bel_pos.append((x, y, z)) bel_pos.append((x, y, z))
bel_wires.append(list()) bel_wires.append(list())
@ -871,7 +871,7 @@ def add_bel_io(x, y, z):
def add_bel_ram(x, y): def add_bel_ram(x, y):
bel = len(bel_name) 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_type.append("ICESTORM_RAM")
bel_pos.append((x, y, 0)) bel_pos.append((x, y, 0))
bel_wires.append(list()) bel_wires.append(list())
@ -905,7 +905,7 @@ def add_bel_gb(xy, x, y, g):
return return
bel = len(bel_name) 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_type.append("SB_GB")
bel_pos.append((x, y, 2)) bel_pos.append((x, y, 2))
bel_wires.append(list()) bel_wires.append(list())
@ -942,7 +942,7 @@ def add_bel_ec(ec):
ectype, x, y, z = ec ectype, x, y, z = ec
bel = len(bel_name) bel = len(bel_name)
extra_cell_config[bel] = [] 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_type.append(ectype)
bel_pos.append((x, y, z)) bel_pos.append((x, y, z))
bel_wires.append(list()) bel_wires.append(list())
@ -1140,7 +1140,7 @@ for bel in range(len(bel_name)):
bba.l("bel_data_%s" % dev_name, "BelInfoPOD") bba.l("bel_data_%s" % dev_name, "BelInfoPOD")
for bel in range(len(bel_name)): 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.u32(constids[bel_type[bel]], "type")
bba.r_slice("bel_wires_%d" % bel, len(bel_wires[bel]), "bel_wires") bba.r_slice("bel_wires_%d" % bel, len(bel_wires[bel]), "bel_wires")
bba.u8(bel_pos[bel][0], "x") bba.u8(bel_pos[bel][0], "x")
@ -1215,7 +1215,9 @@ for wire in range(num_wires):
num_bel_pins = 0 num_bel_pins = 0
info = dict() 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["num_uphill"] = num_uphill
info["list_uphill"] = list_uphill info["list_uphill"] = list_uphill
@ -1263,7 +1265,7 @@ for package in packages:
pins_info = [] pins_info = []
for pin in pins: for pin in pins:
pinname, x, y, z = pin 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) bel_idx = bel_name.index(pin_bel)
pins_info.append((pinname, bel_idx)) pins_info.append((pinname, bel_idx))
bba.l("package_%s_pins" % safename, "PackagePinPOD") 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") bba.l("wire_data_%s" % dev_name, "WireInfoPOD")
for wire, info in enumerate(wireinfo): for wire, info in enumerate(wireinfo):
bba.s(info["name"], "name") 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_uphill"], info["num_uphill"], "pips_uphill")
bba.r_slice(info["list_downhill"], info["num_downhill"], "pips_downhill") bba.r_slice(info["list_downhill"], info["num_downhill"], "pips_downhill")
bba.r_slice(info["list_bel_pins"], info["num_bel_pins"], "bel_pins") bba.r_slice(info["list_bel_pins"], info["num_bel_pins"], "bel_pins")

View File

@ -80,7 +80,7 @@ void ice40DelayFuzzerMain(Context *ctx)
printf("%s %d %d %s %s %d %d\n", cursor == dst ? "dst" : "src", 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), 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))); int(ctx->estimateDelay(cursor, dst)));
if (cursor == src) if (cursor == src)

View File

@ -417,7 +417,7 @@ static BelId find_padin_gbuf(Context *ctx, BelId bel, IdString port_name)
auto wire = ctx->getBelPinWire(bel, port_name); auto wire = ctx->getBelPinWire(bel, port_name);
if (wire == WireId()) 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)) { for (auto src_bel : ctx->getWireBelPins(wire)) {
if (ctx->getBelType(src_bel.bel) == id_SB_GB && src_bel.pin == id_GLOBAL_BUFFER_OUTPUT) { 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 // Find the matching SB_GB BEL connected to the same global network
if (!cell->attrs.count(ctx->id("BEL"))) if (!cell->attrs.count(ctx->id("BEL")))
log_error("Unconstrained SB_GB_IO %s is not supported.\n", ctx->nameOf(cell)); 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); BelId gb_bel = find_padin_gbuf(ctx, bel, port_name);
NPNR_ASSERT(gb_bel != BelId()); NPNR_ASSERT(gb_bel != BelId());
@ -666,7 +666,7 @@ static void promote_globals(Context *ctx)
/* And possibly limits what we can promote */ /* And possibly limits what we can promote */
if (cell.second->attrs.find(ctx->id("BEL")) != cell.second->attrs.end()) { if (cell.second->attrs.find(ctx->id("BEL")) != cell.second->attrs.end()) {
/* If the SB_GB is locked, doesn't matter what it drives */ /* 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); int glb_id = ctx->getDrivenGlobalNetwork(bel);
if ((glb_id % 2) == 0) if ((glb_id % 2) == 0)
resets_available--; resets_available--;
@ -785,7 +785,7 @@ static void place_plls(Context *ctx)
// If it's constrained already, add to already used list // If it's constrained already, add to already used list
if (ci->attrs.count(ctx->id("BEL"))) { 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) if (pll_all_bels.count(bel_constrain) == 0)
log_error("PLL '%s' is constrained to invalid BEL '%s'\n", ci->name.c_str(ctx), 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()); 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), log_error("PLL '%s' PACKAGEPIN SB_IO '%s' is unconstrained\n", ci->name.c_str(ctx),
io_cell->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; BelId found_bel;
// Find the PLL BEL that would suit that connection // Find the PLL BEL that would suit that connection
@ -839,18 +839,17 @@ static void place_plls(Context *ctx)
if (conflict_cell == ci) if (conflict_cell == ci)
continue; continue;
log_error("PLL '%s' PACKAGEPIN forces it to BEL %s but BEL is already assigned to PLL '%s'\n", 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 ? // Is it user constrained ?
if (ci->attrs.count(ctx->id("BEL"))) { if (ci->attrs.count(ctx->id("BEL"))) {
// Yes. Check it actually matches ! // 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) 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 " log_error("PLL '%s' is user constrained to %s but can only be placed in %s based on its PACKAGEPIN "
"connection\n", "connection\n",
ci->name.c_str(ctx), ctx->getBelName(bel_constrain).c_str(ctx), ci->name.c_str(ctx), ctx->nameOfBel(bel_constrain), ctx->nameOfBel(found_bel));
ctx->getBelName(found_bel).c_str(ctx));
} else { } else {
// No, we can constrain it ourselves // No, we can constrain it ourselves
ci->attrs[ctx->id("BEL")] = ctx->getBelName(found_bel).str(ctx); ci->attrs[ctx->id("BEL")] = ctx->getBelName(found_bel).str(ctx);
@ -858,7 +857,7 @@ static void place_plls(Context *ctx)
} }
// Inform user // 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 // Scan all SB_IOs to check for conflict with PLL BELs
@ -876,7 +875,7 @@ static void place_plls(Context *ctx)
continue; continue;
// Check all placed PLL (either forced by user, or forced by PACKAGEPIN) // 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) { for (auto placed_pll : pll_used_bels) {
BelPin pll_io_a, pll_io_b; BelPin pll_io_a, pll_io_b;
@ -910,7 +909,7 @@ static void place_plls(Context *ctx)
continue; continue;
// Check all placed PLL (either forced by user, or forced by PACKAGEPIN) // 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) { for (auto placed_pll : pll_used_bels) {
CellInfo *ci = placed_pll.second; CellInfo *ci = placed_pll.second;
@ -969,7 +968,7 @@ static void place_plls(Context *ctx)
bool could_be_pad = false; bool could_be_pad = false;
BelId pad_bel; BelId pad_bel;
if (ni->users.size() == 1 && is_sb_io(ctx, ni->driver.cell) && ni->driver.cell->attrs.count(ctx->id("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 // Find a BEL for it
BelId found_bel; 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), 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 ?" : ""); 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) if (could_be_pad)
log_info(" (given its connections, this PLL could have been a PAD PLL)\n"); 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; continue;
if (ctx->isBelLocked(bel)) if (ctx->isBelLocked(bel))
continue; continue;
IdString bel_name = ctx->getBelName(bel); IdStringList bel_name = ctx->getBelName(bel);
ci->attrs[ctx->id("BEL")] = bel_name.str(ctx); 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; return bel;
} }
log_error("Unable to place cell '%s' of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); 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) 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), log_error("Unable to find placement for cell '%s' of type '%s'\n", ci->name.c_str(ctx),
ci->type.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); 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: constr_fail:
// PLL must have been placed already in place_plls() // 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()); NPNR_ASSERT(pll_bel != BelId());
// Deal with PAD PLL peculiarities // Deal with PAD PLL peculiarities

View File

@ -32,20 +32,6 @@
NEXTPNR_NAMESPACE_BEGIN 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) 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; 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(); init_cell_pin_data();
// Validate and set up package // Validate and set up package
package_idx = -1; 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; if (name.size() != 3)
std::string belname; return BelId();
std::tie(x, y, belname) = split_identifier_name(name.str(this)); 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(x >= 0 && x < chip_info->width);
NPNR_ASSERT(y >= 0 && y < chip_info->height); NPNR_ASSERT(y >= 0 && y < chip_info->height);
auto &tile = db->loctypes[chip_info->grid[y * chip_info->width + x].loc_type]; 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++) { 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; BelId ret;
ret.tile = y * chip_info->width + x; ret.tile = y * chip_info->width + x;
ret.index = i; 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; if (name.size() != 3)
std::string wirename; return WireId();
std::tie(x, y, wirename) = split_identifier_name(name.str(this)); 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(x >= 0 && x < chip_info->width);
NPNR_ASSERT(y >= 0 && y < chip_info->height); NPNR_ASSERT(y >= 0 && y < chip_info->height);
auto &tile = db->loctypes[chip_info->grid[y * chip_info->width + x].loc_type]; 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++) { 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; WireId ret;
ret.tile = y * chip_info->width + x; ret.tile = y * chip_info->width + x;
ret.index = i; 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; if (name.size() != 5)
std::string pipname; return PipId();
std::tie(x, y, pipname) = split_identifier_name(name.str(this)); 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(x >= 0 && x < chip_info->width);
NPNR_ASSERT(y >= 0 && y < chip_info->height); NPNR_ASSERT(y >= 0 && y < chip_info->height);
PipId ret; PipId ret;
ret.tile = y * chip_info->width + x; ret.tile = y * chip_info->width + x;
auto sep_pos = pipname.find(':'); ret.index = std::stoi(name[2].str(this));
ret.index = std::stoi(pipname.substr(0, sep_pos));
return ret; return ret;
} }
IdString Arch::getPipName(PipId pip) const IdStringList Arch::getPipName(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); 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, std::array<IdString, 5> ids{x_ids.at(pip.tile % chip_info->width), y_ids.at(pip.tile / chip_info->width),
nameOf(loc_data(pip).wires[pip_data(pip).from_wire].name), id(stringf("%d", pip.index)), IdString(loc_data(pip).wires[pip_data(pip).to_wire].name),
nameOf(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(); } IdString Arch::getPipType(PipId pip) const { return IdString(); }

View File

@ -897,6 +897,11 @@ struct Arch : BaseCtx
std::unordered_map<WireId, NetInfo *> wire_to_net; std::unordered_map<WireId, NetInfo *> wire_to_net;
std::unordered_map<PipId, NetInfo *> pip_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; std::string getChipName() const;
@ -909,20 +914,18 @@ struct Arch : BaseCtx
int getGridDimY() const { return chip_info->height; } int getGridDimY() const { return chip_info->height; }
int getTileBelDimZ(int, int) const { return 256; } int getTileBelDimZ(int, int) const { return 256; }
int getTilePipDimZ(int, int) const { return 1; } 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"; NPNR_ASSERT(bel != BelId());
name += std::to_string(bel.tile % chip_info->width); std::array<IdString, 3> ids{x_ids.at(bel.tile % chip_info->width), y_ids.at(bel.tile / chip_info->width),
name += "/Y"; IdString(bel_data(bel).name)};
name += std::to_string(bel.tile / chip_info->width); return IdStringList(ids);
name += "/";
name += nameOf(IdString(bel_data(bel).name));
return id(name);
} }
uint32_t getBelChecksum(BelId bel) const { return (bel.tile << 16) ^ bel.index; } uint32_t getBelChecksum(BelId bel) const { return (bel.tile << 16) ^ bel.index; }
@ -1023,16 +1026,13 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
WireId getWireByName(IdString name) const; WireId getWireByName(IdStringList name) const;
IdString getWireName(WireId wire) const IdStringList getWireName(WireId wire) const
{ {
std::string name = "X"; NPNR_ASSERT(wire != WireId());
name += std::to_string(wire.tile % chip_info->width); std::array<IdString, 3> ids{x_ids.at(wire.tile % chip_info->width), y_ids.at(wire.tile / chip_info->width),
name += "/Y"; IdString(wire_data(wire).name)};
name += std::to_string(wire.tile / chip_info->width); return IdStringList(ids);
name += "/";
name += nameOf(IdString(wire_data(wire).name));
return id(name);
} }
IdString getWireType(WireId wire) const; IdString getWireType(WireId wire) const;
@ -1136,8 +1136,8 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
PipId getPipByName(IdString name) const; PipId getPipByName(IdStringList name) const;
IdString getPipName(PipId pip) const; IdStringList getPipName(PipId pip) const;
void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{ {
@ -1289,8 +1289,8 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
GroupId getGroupByName(IdString name) const { return GroupId(); } GroupId getGroupByName(IdStringList name) const { return GroupId(); }
IdString getGroupName(GroupId group) const { return IdString(); } IdStringList getGroupName(GroupId group) const { return IdStringList(); }
std::vector<GroupId> getGroups() const { return {}; } std::vector<GroupId> getGroups() const { return {}; }
std::vector<BelId> getGroupBels(GroupId group) const { return {}; } std::vector<BelId> getGroupBels(GroupId group) const { return {}; }
std::vector<WireId> getGroupWires(GroupId group) const { return {}; } std::vector<WireId> getGroupWires(GroupId group) const { return {}; }

View File

@ -544,7 +544,7 @@ struct NexusPacker
{ {
if (!ci->attrs.count(id_BEL)) if (!ci->attrs.count(id_BEL))
return BelId(); 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() void pack_io()