Merge pull request #561 from YosysHQ/dave/idstringlist
Use IdStringList for bel/wire/pip/group names
This commit is contained in:
commit
9a79163eab
@ -10,6 +10,9 @@ readonly_wrapper<Context, decltype(&Context::hierarchy), &Context::hierarchy, wr
|
||||
readwrite_wrapper<Context, decltype(&Context::top_module), &Context::top_module, conv_to_str<IdString>,
|
||||
conv_from_str<IdString>>::def_wrap(ctx_cls, "top_module");
|
||||
|
||||
fn_wrapper_0a<Context, decltype(&Context::getNameDelimiter), &Context::getNameDelimiter, pass_through<char>>::def_wrap(
|
||||
ctx_cls, "getNameDelimiter");
|
||||
|
||||
fn_wrapper_1a<Context, decltype(&Context::getNetByAlias), &Context::getNetByAlias, deref_and_wrap<NetInfo>,
|
||||
conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias");
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>,
|
||||
|
@ -36,19 +36,19 @@ void archcheck_names(const Context *ctx)
|
||||
|
||||
log_info("Checking bel names..\n");
|
||||
for (BelId bel : ctx->getBels()) {
|
||||
IdString name = ctx->getBelName(bel);
|
||||
IdStringList name = ctx->getBelName(bel);
|
||||
BelId bel2 = ctx->getBelByName(name);
|
||||
if (bel != bel2) {
|
||||
log_error("bel != bel2, name = %s\n", name.c_str(ctx));
|
||||
log_error("bel != bel2, name = %s\n", ctx->nameOfBel(bel));
|
||||
}
|
||||
}
|
||||
|
||||
log_info("Checking wire names..\n");
|
||||
for (WireId wire : ctx->getWires()) {
|
||||
IdString name = ctx->getWireName(wire);
|
||||
IdStringList name = ctx->getWireName(wire);
|
||||
WireId wire2 = ctx->getWireByName(name);
|
||||
if (wire != wire2) {
|
||||
log_error("wire != wire2, name = %s\n", name.c_str(ctx));
|
||||
log_error("wire != wire2, name = %s\n", ctx->nameOfWire(wire));
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,10 +64,10 @@ void archcheck_names(const Context *ctx)
|
||||
#ifndef ARCH_ECP5
|
||||
log_info("Checking pip names..\n");
|
||||
for (PipId pip : ctx->getPips()) {
|
||||
IdString name = ctx->getPipName(pip);
|
||||
IdStringList name = ctx->getPipName(pip);
|
||||
PipId pip2 = ctx->getPipByName(name);
|
||||
if (pip != pip2) {
|
||||
log_error("pip != pip2, name = %s\n", name.c_str(ctx));
|
||||
log_error("pip != pip2, name = %s\n", ctx->nameOfPip(pip));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -109,7 +109,7 @@ void archcheck_locs(const Context *ctx)
|
||||
if (bel == BelId())
|
||||
continue;
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
dbg(" + %d %s\n", z, ctx->getBelName(bel).c_str(ctx));
|
||||
dbg(" + %d %s\n", z, ctx->nameOfBel(bel));
|
||||
log_assert(x == loc.x);
|
||||
log_assert(y == loc.y);
|
||||
log_assert(z == loc.z);
|
||||
@ -118,7 +118,7 @@ void archcheck_locs(const Context *ctx)
|
||||
|
||||
for (BelId bel : ctx->getBelsByTile(x, y)) {
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
dbg(" - %d %s\n", loc.z, ctx->getBelName(bel).c_str(ctx));
|
||||
dbg(" - %d %s\n", loc.z, ctx->nameOfBel(bel));
|
||||
log_assert(x == loc.x);
|
||||
log_assert(y == loc.y);
|
||||
log_assert(usedz.count(loc.z));
|
||||
|
@ -69,6 +69,41 @@ void IdString::initialize_add(const BaseCtx *ctx, const char *s, int idx)
|
||||
ctx->idstring_idx_to_str->push_back(&insert_rc.first->first);
|
||||
}
|
||||
|
||||
IdStringList IdStringList::parse(Context *ctx, const std::string &str)
|
||||
{
|
||||
char delim = ctx->getNameDelimiter();
|
||||
size_t id_count = std::count(str.begin(), str.end(), delim) + 1;
|
||||
IdStringList list(id_count);
|
||||
size_t start = 0;
|
||||
for (size_t i = 0; i < id_count; i++) {
|
||||
size_t end = str.find(delim, start);
|
||||
NPNR_ASSERT((i == (id_count - 1)) || (end != std::string::npos));
|
||||
list.ids[i] = ctx->id(str.substr(start, end - start));
|
||||
start = end + 1;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void IdStringList::build_str(const Context *ctx, std::string &str) const
|
||||
{
|
||||
char delim = ctx->getNameDelimiter();
|
||||
bool first = true;
|
||||
str.clear();
|
||||
for (auto entry : ids) {
|
||||
if (!first)
|
||||
str += delim;
|
||||
str += entry.str(ctx);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string IdStringList::str(const Context *ctx) const
|
||||
{
|
||||
std::string s;
|
||||
build_str(ctx, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
TimingConstrObjectId BaseCtx::timingWildcardObject()
|
||||
{
|
||||
TimingConstrObjectId id;
|
||||
@ -76,6 +111,14 @@ TimingConstrObjectId BaseCtx::timingWildcardObject()
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string &StrRingBuffer::next()
|
||||
{
|
||||
std::string &s = buffer.at(index++);
|
||||
if (index >= N)
|
||||
index = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
TimingConstrObjectId BaseCtx::timingClockDomainObject(NetInfo *clockDomain)
|
||||
{
|
||||
NPNR_ASSERT(clockDomain->clkconstr != nullptr);
|
||||
@ -248,25 +291,57 @@ void BaseCtx::removeConstraint(IdString constrName)
|
||||
const char *BaseCtx::nameOfBel(BelId bel) const
|
||||
{
|
||||
const Context *ctx = getCtx();
|
||||
return ctx->getBelName(bel).c_str(ctx);
|
||||
std::string &s = ctx->log_strs.next();
|
||||
ctx->getBelName(bel).build_str(ctx, s);
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
const char *BaseCtx::nameOfWire(WireId wire) const
|
||||
{
|
||||
const Context *ctx = getCtx();
|
||||
return ctx->getWireName(wire).c_str(ctx);
|
||||
std::string &s = ctx->log_strs.next();
|
||||
ctx->getWireName(wire).build_str(ctx, s);
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
const char *BaseCtx::nameOfPip(PipId pip) const
|
||||
{
|
||||
const Context *ctx = getCtx();
|
||||
return ctx->getPipName(pip).c_str(ctx);
|
||||
std::string &s = ctx->log_strs.next();
|
||||
ctx->getPipName(pip).build_str(ctx, s);
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
const char *BaseCtx::nameOfGroup(GroupId group) const
|
||||
{
|
||||
const Context *ctx = getCtx();
|
||||
return ctx->getGroupName(group).c_str(ctx);
|
||||
std::string &s = ctx->log_strs.next();
|
||||
ctx->getGroupName(group).build_str(ctx, s);
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
BelId BaseCtx::getBelByNameStr(const std::string &str)
|
||||
{
|
||||
Context *ctx = getCtx();
|
||||
return ctx->getBelByName(IdStringList::parse(ctx, str));
|
||||
}
|
||||
|
||||
WireId BaseCtx::getWireByNameStr(const std::string &str)
|
||||
{
|
||||
Context *ctx = getCtx();
|
||||
return ctx->getWireByName(IdStringList::parse(ctx, str));
|
||||
}
|
||||
|
||||
PipId BaseCtx::getPipByNameStr(const std::string &str)
|
||||
{
|
||||
Context *ctx = getCtx();
|
||||
return ctx->getPipByName(IdStringList::parse(ctx, str));
|
||||
}
|
||||
|
||||
GroupId BaseCtx::getGroupByNameStr(const std::string &str)
|
||||
{
|
||||
Context *ctx = getCtx();
|
||||
return ctx->getGroupByName(IdStringList::parse(ctx, str));
|
||||
}
|
||||
|
||||
WireId Context::getNetinfoSourceWire(const NetInfo *net_info) const
|
||||
@ -620,7 +695,7 @@ void BaseCtx::archInfoToAttributes()
|
||||
if (ci->attrs.find(id("BEL")) != ci->attrs.end()) {
|
||||
ci->attrs.erase(ci->attrs.find(id("BEL")));
|
||||
}
|
||||
ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).str(this);
|
||||
ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).str(getCtx());
|
||||
ci->attrs[id("BEL_STRENGTH")] = (int)ci->belStrength;
|
||||
}
|
||||
if (ci->constr_x != ci->UNCONSTR)
|
||||
@ -650,10 +725,10 @@ void BaseCtx::archInfoToAttributes()
|
||||
for (auto &item : ni->wires) {
|
||||
if (!first)
|
||||
routing += ";";
|
||||
routing += getCtx()->getWireName(item.first).c_str(this);
|
||||
routing += getCtx()->getWireName(item.first).str(getCtx());
|
||||
routing += ";";
|
||||
if (item.second.pip != PipId())
|
||||
routing += getCtx()->getPipName(item.second.pip).c_str(this);
|
||||
routing += getCtx()->getPipName(item.second.pip).str(getCtx());
|
||||
routing += ";" + std::to_string(item.second.strength);
|
||||
first = false;
|
||||
}
|
||||
@ -672,7 +747,7 @@ void BaseCtx::attributesToArchInfo()
|
||||
if (str != ci->attrs.end())
|
||||
strength = (PlaceStrength)str->second.as_int64();
|
||||
|
||||
BelId b = getCtx()->getBelByName(id(val->second.as_string()));
|
||||
BelId b = getCtx()->getBelByNameStr(val->second.as_string());
|
||||
getCtx()->bindBel(b, ci, strength);
|
||||
}
|
||||
|
||||
|
155
common/nextpnr.h
155
common/nextpnr.h
@ -145,6 +145,152 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX IdString>
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
// An small size optimised array that is statically allocated when the size is N or less; heap allocated otherwise
|
||||
template <typename T, size_t N> class SSOArray
|
||||
{
|
||||
private:
|
||||
union
|
||||
{
|
||||
T data_static[N];
|
||||
T *data_heap;
|
||||
};
|
||||
size_t m_size;
|
||||
inline bool is_heap() const { return (m_size > N); }
|
||||
void alloc()
|
||||
{
|
||||
if (is_heap()) {
|
||||
data_heap = new T[m_size];
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
T *data() { return is_heap() ? data_heap : data_static; }
|
||||
const T *data() const { return is_heap() ? data_heap : data_static; }
|
||||
size_t size() const { return m_size; }
|
||||
|
||||
T *begin() { return data(); }
|
||||
T *end() { return data() + m_size; }
|
||||
const T *begin() const { return data(); }
|
||||
const T *end() const { return data() + m_size; }
|
||||
|
||||
SSOArray() : m_size(0){};
|
||||
|
||||
SSOArray(size_t size, const T &init = T()) : m_size(size)
|
||||
{
|
||||
alloc();
|
||||
std::fill(begin(), end(), init);
|
||||
}
|
||||
|
||||
SSOArray(const SSOArray &other) : m_size(other.size())
|
||||
{
|
||||
alloc();
|
||||
std::copy(other.begin(), other.end(), begin());
|
||||
}
|
||||
|
||||
template <typename Tother> SSOArray(const Tother &other) : m_size(other.size())
|
||||
{
|
||||
alloc();
|
||||
std::copy(other.begin(), other.end(), begin());
|
||||
}
|
||||
|
||||
~SSOArray()
|
||||
{
|
||||
if (is_heap()) {
|
||||
delete[] data_heap;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const SSOArray &other) const
|
||||
{
|
||||
if (size() != other.size())
|
||||
return false;
|
||||
return std::equal(begin(), end(), other.begin());
|
||||
}
|
||||
bool operator!=(const SSOArray &other) const
|
||||
{
|
||||
if (size() != other.size())
|
||||
return true;
|
||||
return !std::equal(begin(), end(), other.begin());
|
||||
}
|
||||
T &operator[](size_t idx)
|
||||
{
|
||||
NPNR_ASSERT(idx < m_size);
|
||||
return data()[idx];
|
||||
}
|
||||
const T &operator[](size_t idx) const
|
||||
{
|
||||
NPNR_ASSERT(idx < m_size);
|
||||
return data()[idx];
|
||||
}
|
||||
};
|
||||
|
||||
struct IdStringList
|
||||
{
|
||||
SSOArray<IdString, 4> ids;
|
||||
|
||||
IdStringList(){};
|
||||
IdStringList(size_t n) : ids(n, IdString()){};
|
||||
IdStringList(IdString id) : ids(1, id){};
|
||||
template <typename Tlist> IdStringList(const Tlist &list) : ids(list){};
|
||||
|
||||
static IdStringList parse(Context *ctx, const std::string &str);
|
||||
void build_str(const Context *ctx, std::string &str) const;
|
||||
std::string str(const Context *ctx) const;
|
||||
|
||||
size_t size() const { return ids.size(); }
|
||||
const IdString *begin() const { return ids.begin(); }
|
||||
const IdString *end() const { return ids.end(); }
|
||||
const IdString &operator[](size_t idx) const { return ids[idx]; }
|
||||
bool operator==(const IdStringList &other) const { return ids == other.ids; }
|
||||
bool operator!=(const IdStringList &other) const { return ids != other.ids; }
|
||||
bool operator<(const IdStringList &other) const
|
||||
{
|
||||
if (size() > other.size())
|
||||
return false;
|
||||
if (size() < other.size())
|
||||
return true;
|
||||
for (size_t i = 0; i < size(); i++) {
|
||||
IdString a = ids[i], b = other[i];
|
||||
if (a.index < b.index)
|
||||
return true;
|
||||
if (a.index > b.index)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
namespace std {
|
||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX IdStringList>
|
||||
{
|
||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX IdStringList &obj) const noexcept
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, hash<size_t>()(obj.size()));
|
||||
for (auto &id : obj)
|
||||
boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(id));
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
// A ring buffer of strings, so we can return a simple const char * pointer for %s formatting - inspired by how logging
|
||||
// in Yosys works Let's just hope noone tries to log more than 100 things in one call....
|
||||
class StrRingBuffer
|
||||
{
|
||||
private:
|
||||
static const size_t N = 100;
|
||||
std::array<std::string, N> buffer;
|
||||
size_t index = 0;
|
||||
|
||||
public:
|
||||
std::string &next();
|
||||
};
|
||||
|
||||
struct GraphicElement
|
||||
{
|
||||
enum type_t
|
||||
@ -667,6 +813,9 @@ struct BaseCtx
|
||||
mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
|
||||
mutable std::vector<const std::string *> *idstring_idx_to_str;
|
||||
|
||||
// Temporary string backing store for logging
|
||||
mutable StrRingBuffer log_strs;
|
||||
|
||||
// Project settings and config switches
|
||||
std::unordered_map<IdString, Property> settings;
|
||||
|
||||
@ -782,6 +931,12 @@ struct BaseCtx
|
||||
const char *nameOfPip(PipId pip) const;
|
||||
const char *nameOfGroup(GroupId group) const;
|
||||
|
||||
// Wrappers of arch functions that take a string and handle IdStringList parsing
|
||||
BelId getBelByNameStr(const std::string &str);
|
||||
WireId getWireByNameStr(const std::string &str);
|
||||
PipId getPipByNameStr(const std::string &str);
|
||||
GroupId getGroupByNameStr(const std::string &str);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
|
||||
bool allUiReload = true;
|
||||
|
@ -158,8 +158,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
|
||||
all_placed = true;
|
||||
}
|
||||
if (ctx->verbose)
|
||||
log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx),
|
||||
ctx->getBelName(best_bel).c_str(ctx));
|
||||
log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx), ctx->nameOfBel(best_bel));
|
||||
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
|
||||
|
||||
cell = ripup_target;
|
||||
@ -375,7 +374,7 @@ class ConstraintLegaliseWorker
|
||||
if (confl_cell != nullptr) {
|
||||
if (ctx->verbose)
|
||||
log_info(" '%s' already placed at '%s'\n", ctx->nameOf(confl_cell),
|
||||
ctx->getBelName(confl_cell->bel).c_str(ctx));
|
||||
ctx->nameOfBel(confl_cell->bel));
|
||||
NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG);
|
||||
ctx->unbindBel(target);
|
||||
rippedCells.insert(confl_cell->name);
|
||||
@ -489,7 +488,7 @@ class ConstraintLegaliseWorker
|
||||
for (auto cell : sorted(ctx->cells))
|
||||
if (get_constraints_distance(ctx, cell.second) != 0)
|
||||
log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx),
|
||||
ctx->getBelName(cell.second->bel).c_str(ctx));
|
||||
ctx->nameOfBel(cell.second->bel));
|
||||
return score;
|
||||
}
|
||||
};
|
||||
|
@ -154,7 +154,7 @@ class SAPlacer
|
||||
auto loc = cell->attrs.find(ctx->id("BEL"));
|
||||
if (loc != cell->attrs.end()) {
|
||||
std::string loc_name = loc->second.as_string();
|
||||
BelId bel = ctx->getBelByName(ctx->id(loc_name));
|
||||
BelId bel = ctx->getBelByNameStr(loc_name);
|
||||
if (bel == BelId()) {
|
||||
log_error("No Bel named \'%s\' located for "
|
||||
"this chip (processing BEL attribute on \'%s\')\n",
|
||||
@ -409,18 +409,18 @@ class SAPlacer
|
||||
if (ctx->force) {
|
||||
log_warning("post-placement validity check failed for Bel '%s' "
|
||||
"(%s)\n",
|
||||
ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
|
||||
ctx->nameOfBel(bel), cell_text.c_str());
|
||||
} else {
|
||||
log_error("post-placement validity check failed for Bel '%s' "
|
||||
"(%s)\n",
|
||||
ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
|
||||
ctx->nameOfBel(bel), cell_text.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells))
|
||||
if (get_constraints_distance(ctx, cell.second) != 0)
|
||||
log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx),
|
||||
ctx->getBelName(cell.second->bel).c_str(ctx));
|
||||
ctx->nameOfBel(cell.second->bel));
|
||||
timing_analysis(ctx);
|
||||
ctx->unlock();
|
||||
return true;
|
||||
@ -563,9 +563,9 @@ class SAPlacer
|
||||
}
|
||||
commit_cost_changes(moveChange);
|
||||
#if 0
|
||||
log_info("swap %s -> %s\n", cell->name.c_str(ctx), ctx->getBelName(newBel).c_str(ctx));
|
||||
log_info("swap %s -> %s\n", cell->name.c_str(ctx), ctx->nameOfBel(newBel));
|
||||
if (other_cell != nullptr)
|
||||
log_info("swap %s -> %s\n", other_cell->name.c_str(ctx), ctx->getBelName(oldBel).c_str(ctx));
|
||||
log_info("swap %s -> %s\n", other_cell->name.c_str(ctx), ctx->nameOfBel(oldBel));
|
||||
#endif
|
||||
return true;
|
||||
swap_fail:
|
||||
@ -590,7 +590,7 @@ class SAPlacer
|
||||
{
|
||||
BelId oldBel = cell->bel;
|
||||
#if 0
|
||||
log_info("%s old: %s new: %s\n", cell->name.c_str(ctx), ctx->getBelName(cell->bel).c_str(ctx), ctx->getBelName(newBel).c_str(ctx));
|
||||
log_info("%s old: %s new: %s\n", cell->name.c_str(ctx), ctx->nameOfBel(cell->bel), ctx->nameOfBel(newBel));
|
||||
#endif
|
||||
CellInfo *bound = ctx->getBoundBelCell(newBel);
|
||||
if (bound != nullptr)
|
||||
|
@ -305,7 +305,7 @@ class HeAPPlacer
|
||||
if (ctx->getBoundBelCell(cell.second->bel) != cell.second)
|
||||
log_error("Found cell %s with mismatched binding\n", cell.first.c_str(ctx));
|
||||
if (ctx->debug)
|
||||
log_info("AP soln: %s -> %s\n", cell.first.c_str(ctx), ctx->getBelName(cell.second->bel).c_str(ctx));
|
||||
log_info("AP soln: %s -> %s\n", cell.first.c_str(ctx), ctx->nameOfBel(cell.second->bel));
|
||||
}
|
||||
|
||||
ctx->unlock();
|
||||
@ -379,7 +379,7 @@ class HeAPPlacer
|
||||
auto loc = cell->attrs.find(ctx->id("BEL"));
|
||||
if (loc != cell->attrs.end()) {
|
||||
std::string loc_name = loc->second.as_string();
|
||||
BelId bel = ctx->getBelByName(ctx->id(loc_name));
|
||||
BelId bel = ctx->getBelByNameStr(loc_name);
|
||||
if (bel == BelId()) {
|
||||
log_error("No Bel named \'%s\' located for "
|
||||
"this chip (processing BEL attribute on \'%s\')\n",
|
||||
|
@ -74,6 +74,18 @@ template <> struct string_converter<const IdString>
|
||||
inline std::string to_str(Context *ctx, IdString id) { return id.str(ctx); }
|
||||
};
|
||||
|
||||
template <> struct string_converter<IdStringList>
|
||||
{
|
||||
IdStringList from_str(Context *ctx, std::string name) { return IdStringList::parse(ctx, name); }
|
||||
std::string to_str(Context *ctx, const IdStringList &id) { return id.str(ctx); }
|
||||
};
|
||||
|
||||
template <> struct string_converter<const IdStringList>
|
||||
{
|
||||
IdStringList from_str(Context *ctx, std::string name) { return IdStringList::parse(ctx, name); }
|
||||
std::string to_str(Context *ctx, const IdStringList &id) { return id.str(ctx); }
|
||||
};
|
||||
|
||||
} // namespace PythonConversion
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -885,8 +885,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
|
||||
auto pip = it->second.pip;
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
delay = ctx->getPipDelay(pip).maxDelay();
|
||||
log_info(" %1.3f %s\n", ctx->getDelayNS(delay),
|
||||
ctx->getPipName(pip).c_str(ctx));
|
||||
log_info(" %1.3f %s\n", ctx->getDelayNS(delay), ctx->nameOfPip(pip));
|
||||
cursor = ctx->getPipSrcWire(pip);
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ template <> struct hash<std::pair<int, NEXTPNR_NAMESPACE_PREFIX BelId>>
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
#if !defined(ARCH_GENERIC) && !defined(ARCH_GOWIN)
|
||||
#if !defined(ARCH_GOWIN)
|
||||
template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX BelId>>
|
||||
{
|
||||
std::size_t
|
||||
@ -427,7 +427,7 @@ class TimingOptimiser
|
||||
if (pn->users.at(i).cell == port->cell && pn->users.at(i).port == port->port)
|
||||
crit = net_crit.at(pn->name).criticality.at(i);
|
||||
log_info(" %s.%s at %s crit %0.02f\n", port->cell->name.c_str(ctx), port->port.c_str(ctx),
|
||||
ctx->getBelName(port->cell->bel).c_str(ctx), crit);
|
||||
ctx->nameOfBel(port->cell->bel), crit);
|
||||
}
|
||||
if (std::find(path_cells.begin(), path_cells.end(), port->cell->name) != path_cells.end())
|
||||
continue;
|
||||
@ -472,10 +472,9 @@ class TimingOptimiser
|
||||
|
||||
if (ctx->debug) {
|
||||
for (auto cell : path_cells) {
|
||||
log_info("Candidate neighbours for %s (%s):\n", cell.c_str(ctx),
|
||||
ctx->getBelName(ctx->cells[cell]->bel).c_str(ctx));
|
||||
log_info("Candidate neighbours for %s (%s):\n", cell.c_str(ctx), ctx->nameOfBel(ctx->cells[cell]->bel));
|
||||
for (auto neigh : cell_neighbour_bels.at(cell)) {
|
||||
log_info(" %s\n", ctx->getBelName(neigh).c_str(ctx));
|
||||
log_info(" %s\n", ctx->nameOfBel(neigh));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -597,7 +596,7 @@ class TimingOptimiser
|
||||
CellInfo *cell = ctx->cells.at(rt_entry.first).get();
|
||||
cell_swap_bel(cell, rt_entry.second);
|
||||
if (ctx->debug)
|
||||
log_info(" %s at %s\n", rt_entry.first.c_str(ctx), ctx->getBelName(rt_entry.second).c_str(ctx));
|
||||
log_info(" %s at %s\n", rt_entry.first.c_str(ctx), ctx->nameOfBel(rt_entry.second));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -92,6 +92,10 @@ Get Z dimension for the specified tile for bels. All bels with at specified X an
|
||||
|
||||
Get Z dimension for the specified tile for pips. All pips with at specified X and Y coordinates must have a Z coordinate in the range `0 .. getTileDimZ(X,Y)-1` (inclusive).
|
||||
|
||||
### char getNameDelimiter() const
|
||||
|
||||
Returns a delimiter that can be used to build up bel, wire and pip names out of hierarchical components (such as tiles and sites) to avoid the high memory usage of storing full names for every object.
|
||||
|
||||
Cell Methods
|
||||
-----------
|
||||
|
||||
@ -99,15 +103,14 @@ Cell Methods
|
||||
|
||||
Get list of cell types that this architecture accepts.
|
||||
|
||||
|
||||
Bel Methods
|
||||
-----------
|
||||
|
||||
### BelId getBelByName(IdString name) const
|
||||
### BelId getBelByName(IdStringList name) const
|
||||
|
||||
Lookup a bel by its name.
|
||||
Lookup a bel by its name, which is a list of IdStrings joined by `getNameDelimiter()`.
|
||||
|
||||
### IdString getBelName(BelId bel) const
|
||||
### IdStringList getBelName(BelId bel) const
|
||||
|
||||
Get the name for a bel. (Bel names must be unique.)
|
||||
|
||||
@ -183,11 +186,11 @@ Return a list of all pins on that bel.
|
||||
Wire Methods
|
||||
------------
|
||||
|
||||
### WireId getWireByName(IdString name) const
|
||||
### WireId getWireByName(IdStringList name) const
|
||||
|
||||
Lookup a wire by its name.
|
||||
Lookup a wire by its name, which is a list of IdStrings joined by `getNameDelimiter()`.
|
||||
|
||||
### IdString getWireName(WireId wire) const
|
||||
### IdStringList getWireName(WireId wire) const
|
||||
|
||||
Get the name for a wire. (Wire names must be unique.)
|
||||
|
||||
@ -259,11 +262,11 @@ of the bounds is almost always better than an under-estimate.
|
||||
Pip Methods
|
||||
-----------
|
||||
|
||||
### PipId getPipByName(IdString name) const
|
||||
### PipId getPipByName(IdStringList name) const
|
||||
|
||||
Lookup a pip by its name.
|
||||
Lookup a pip by its name, which is a list of IdStrings joined by `getNameDelimiter()`.
|
||||
|
||||
### IdString getPipName(PipId pip) const
|
||||
### IdStringList getPipName(PipId pip) const
|
||||
|
||||
Get the name for a pip. (Pip names must be unique.)
|
||||
|
||||
@ -350,11 +353,11 @@ Get all pips uphill of a wire, i.e. pips that use this wire as destination wire.
|
||||
Group Methods
|
||||
-------------
|
||||
|
||||
### GroupId getGroupByName(IdString name) const
|
||||
### GroupId getGroupByName(IdStringList name) const
|
||||
|
||||
Lookup a group by its name.
|
||||
Lookup a group by its name, which is a list of IdStrings joined by `getNameDelimiter()`.
|
||||
|
||||
### IdString getGroupName(GroupId group) const
|
||||
### IdStringList getGroupName(GroupId group) const
|
||||
|
||||
Get the name for a group. (Group names must be unique.)
|
||||
|
||||
|
111
ecp5/arch.cc
111
ecp5/arch.cc
@ -37,17 +37,6 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
static std::tuple<int, int, std::string> split_identifier_name(const std::string &name)
|
||||
{
|
||||
size_t first_slash = name.find('/');
|
||||
NPNR_ASSERT(first_slash != std::string::npos);
|
||||
size_t second_slash = name.find('/', first_slash + 1);
|
||||
NPNR_ASSERT(second_slash != std::string::npos);
|
||||
return std::make_tuple(std::stoi(name.substr(1, first_slash)),
|
||||
std::stoi(name.substr(first_slash + 2, second_slash - first_slash)),
|
||||
name.substr(second_slash + 1));
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void IdString::initialize_arch(const BaseCtx *ctx)
|
||||
@ -128,6 +117,22 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
bucket.name = bel_type;
|
||||
buckets.push_back(bucket);
|
||||
}
|
||||
|
||||
for (int i = 0; i < chip_info->width; i++)
|
||||
x_ids.push_back(id(stringf("X%d", i)));
|
||||
for (int i = 0; i < chip_info->height; i++)
|
||||
y_ids.push_back(id(stringf("Y%d", i)));
|
||||
|
||||
for (int i = 0; i < chip_info->width; i++) {
|
||||
IdString x_id = id(stringf("X%d", i));
|
||||
x_ids.push_back(x_id);
|
||||
id_to_x[x_id] = i;
|
||||
}
|
||||
for (int i = 0; i < chip_info->height; i++) {
|
||||
IdString y_id = id(stringf("Y%d", i));
|
||||
y_ids.push_back(y_id);
|
||||
id_to_y[y_id] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -208,28 +213,24 @@ IdString Arch::archArgsToId(ArchArgs args) const
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
BelId Arch::getBelByName(IdString name) const
|
||||
BelId Arch::getBelByName(IdStringList name) const
|
||||
{
|
||||
if (name.size() != 3)
|
||||
return BelId();
|
||||
BelId ret;
|
||||
auto it = bel_by_name.find(name);
|
||||
if (it != bel_by_name.end())
|
||||
return it->second;
|
||||
|
||||
Location loc;
|
||||
std::string basename;
|
||||
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
|
||||
loc.x = id_to_x.at(name[0]);
|
||||
loc.y = id_to_y.at(name[1]);
|
||||
ret.location = loc;
|
||||
const LocationTypePOD *loci = locInfo(ret);
|
||||
for (int i = 0; i < int(loci->bel_data.size()); i++) {
|
||||
if (std::strcmp(loci->bel_data[i].name.get(), basename.c_str()) == 0) {
|
||||
if (std::strcmp(loci->bel_data[i].name.get(), name[2].c_str(this)) == 0) {
|
||||
ret.index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret.index >= 0)
|
||||
bel_by_name[name] = ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return BelId();
|
||||
}
|
||||
|
||||
BelRange Arch::getBelsByTile(int x, int y) const
|
||||
{
|
||||
@ -277,36 +278,31 @@ PortType Arch::getBelPinType(BelId bel, IdString pin) const
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
WireId Arch::getWireByName(IdString name) const
|
||||
WireId Arch::getWireByName(IdStringList name) const
|
||||
{
|
||||
if (name.size() != 3)
|
||||
return WireId();
|
||||
WireId ret;
|
||||
auto it = wire_by_name.find(name);
|
||||
if (it != wire_by_name.end())
|
||||
return it->second;
|
||||
|
||||
Location loc;
|
||||
std::string basename;
|
||||
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
|
||||
loc.x = id_to_x.at(name[0]);
|
||||
loc.y = id_to_y.at(name[1]);
|
||||
ret.location = loc;
|
||||
const LocationTypePOD *loci = locInfo(ret);
|
||||
for (int i = 0; i < int(loci->wire_data.size()); i++) {
|
||||
if (std::strcmp(loci->wire_data[i].name.get(), basename.c_str()) == 0) {
|
||||
if (std::strcmp(loci->wire_data[i].name.get(), name[2].c_str(this)) == 0) {
|
||||
ret.index = i;
|
||||
ret.location = loc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret.index >= 0)
|
||||
wire_by_name[name] = ret;
|
||||
else
|
||||
ret.location = Location();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return WireId();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
PipId Arch::getPipByName(IdString name) const
|
||||
PipId Arch::getPipByName(IdStringList name) const
|
||||
{
|
||||
if (name.size() != 3)
|
||||
return PipId();
|
||||
auto it = pip_by_name.find(name);
|
||||
if (it != pip_by_name.end())
|
||||
return it->second;
|
||||
@ -314,7 +310,8 @@ PipId Arch::getPipByName(IdString name) const
|
||||
PipId ret;
|
||||
Location loc;
|
||||
std::string basename;
|
||||
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
|
||||
loc.x = id_to_x.at(name[0]);
|
||||
loc.y = id_to_y.at(name[1]);
|
||||
ret.location = loc;
|
||||
const LocationTypePOD *loci = locInfo(ret);
|
||||
for (int i = 0; i < int(loci->pip_data.size()); i++) {
|
||||
@ -324,24 +321,23 @@ PipId Arch::getPipByName(IdString name) const
|
||||
pip_by_name[getPipName(curr)] = curr;
|
||||
}
|
||||
if (pip_by_name.find(name) == pip_by_name.end())
|
||||
NPNR_ASSERT_FALSE_STR("no pip named " + name.str(this));
|
||||
NPNR_ASSERT_FALSE_STR("no pip named " + name.str(getCtx()));
|
||||
return pip_by_name[name];
|
||||
}
|
||||
|
||||
IdString Arch::getPipName(PipId pip) const
|
||||
IdStringList Arch::getPipName(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
|
||||
int x = pip.location.x;
|
||||
int y = pip.location.y;
|
||||
// TODO: can we improve how pip names are stored/built?
|
||||
auto &pip_data = locInfo(pip)->pip_data[pip.index];
|
||||
WireId src = getPipSrcWire(pip), dst = getPipDstWire(pip);
|
||||
std::string pip_name = stringf("%d_%d_%s->%d_%d_%s", pip_data.rel_src_loc.x, pip_data.rel_src_loc.y,
|
||||
getWireBasename(src).c_str(this), pip_data.rel_dst_loc.x, pip_data.rel_dst_loc.y,
|
||||
getWireBasename(dst).c_str(this));
|
||||
|
||||
std::string src_name = getWireName(getPipSrcWire(pip)).str(this);
|
||||
std::replace(src_name.begin(), src_name.end(), '/', '.');
|
||||
|
||||
std::string dst_name = getWireName(getPipDstWire(pip)).str(this);
|
||||
std::replace(dst_name.begin(), dst_name.end(), '/', '.');
|
||||
|
||||
return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name);
|
||||
std::array<IdString, 3> ids{x_ids.at(pip.location.x), y_ids.at(pip.location.y), id(pip_name)};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -1206,7 +1202,7 @@ const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
GroupId Arch::getGroupByName(IdString name) const
|
||||
GroupId Arch::getGroupByName(IdStringList name) const
|
||||
{
|
||||
for (auto g : getGroups())
|
||||
if (getGroupName(g) == name)
|
||||
@ -1214,7 +1210,7 @@ GroupId Arch::getGroupByName(IdString name) const
|
||||
return GroupId();
|
||||
}
|
||||
|
||||
IdString Arch::getGroupName(GroupId group) const
|
||||
IdStringList Arch::getGroupName(GroupId group) const
|
||||
{
|
||||
std::string suffix;
|
||||
|
||||
@ -1223,10 +1219,11 @@ IdString Arch::getGroupName(GroupId group) const
|
||||
suffix = "switchbox";
|
||||
break;
|
||||
default:
|
||||
return IdString();
|
||||
return IdStringList();
|
||||
}
|
||||
|
||||
return id("X" + std::to_string(group.location.x) + "/Y" + std::to_string(group.location.y) + "/" + suffix);
|
||||
std::array<IdString, 3> ids{x_ids.at(group.location.x), y_ids.at(group.location.y), id(suffix)};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
std::vector<GroupId> Arch::getGroups() const
|
||||
|
40
ecp5/arch.h
40
ecp5/arch.h
@ -441,15 +441,18 @@ struct Arch : BaseCtx
|
||||
const PackageInfoPOD *package_info;
|
||||
const SpeedGradePOD *speed_grade;
|
||||
|
||||
mutable std::unordered_map<IdString, BelId> bel_by_name;
|
||||
mutable std::unordered_map<IdString, WireId> wire_by_name;
|
||||
mutable std::unordered_map<IdString, PipId> pip_by_name;
|
||||
mutable std::unordered_map<IdStringList, PipId> pip_by_name;
|
||||
|
||||
std::vector<CellInfo *> bel_to_cell;
|
||||
std::unordered_map<WireId, NetInfo *> wire_to_net;
|
||||
std::unordered_map<PipId, NetInfo *> pip_to_net;
|
||||
std::unordered_map<WireId, int> wire_fanout;
|
||||
|
||||
// fast access to X and Y IdStrings for building object names
|
||||
std::vector<IdString> x_ids, y_ids;
|
||||
// inverse of the above for name->object mapping
|
||||
std::unordered_map<IdString, int> id_to_x, id_to_y;
|
||||
|
||||
ArchArgs args;
|
||||
Arch(ArchArgs args);
|
||||
|
||||
@ -471,22 +474,23 @@ struct Arch : BaseCtx
|
||||
int getGridDimY() const { return chip_info->height; };
|
||||
int getTileBelDimZ(int, int) const { return max_loc_bels; };
|
||||
int getTilePipDimZ(int, int) const { return 1; };
|
||||
char getNameDelimiter() const { return '/'; }
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
BelId getBelByName(IdString name) const;
|
||||
BelId getBelByName(IdStringList name) const;
|
||||
|
||||
template <typename Id> const LocationTypePOD *locInfo(Id &id) const
|
||||
{
|
||||
return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
|
||||
}
|
||||
|
||||
IdString getBelName(BelId bel) const
|
||||
IdStringList getBelName(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
std::stringstream name;
|
||||
name << "X" << bel.location.x << "/Y" << bel.location.y << "/" << locInfo(bel)->bel_data[bel.index].name.get();
|
||||
return id(name.str());
|
||||
std::array<IdString, 3> ids{x_ids.at(bel.location.x), y_ids.at(bel.location.y),
|
||||
id(locInfo(bel)->bel_data[bel.index].name.get())};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
|
||||
@ -594,16 +598,14 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
WireId getWireByName(IdString name) const;
|
||||
WireId getWireByName(IdStringList name) const;
|
||||
|
||||
IdString getWireName(WireId wire) const
|
||||
IdStringList getWireName(WireId wire) const
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
|
||||
std::stringstream name;
|
||||
name << "X" << wire.location.x << "/Y" << wire.location.y << "/"
|
||||
<< locInfo(wire)->wire_data[wire.index].name.get();
|
||||
return id(name.str());
|
||||
std::array<IdString, 3> ids{x_ids.at(wire.location.x), y_ids.at(wire.location.y),
|
||||
id(locInfo(wire)->wire_data[wire.index].name.get())};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
IdString getWireType(WireId wire) const
|
||||
@ -712,8 +714,8 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
PipId getPipByName(IdString name) const;
|
||||
IdString getPipName(PipId pip) const;
|
||||
PipId getPipByName(IdStringList name) const;
|
||||
IdStringList getPipName(PipId pip) const;
|
||||
|
||||
IdString getPipType(PipId pip) const { return IdString(); }
|
||||
|
||||
@ -891,8 +893,8 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
GroupId getGroupByName(IdString name) const;
|
||||
IdString getGroupName(GroupId group) const;
|
||||
GroupId getGroupByName(IdStringList name) const;
|
||||
IdStringList getGroupName(GroupId group) const;
|
||||
std::vector<GroupId> getGroups() const;
|
||||
std::vector<BelId> getGroupBels(GroupId group) const;
|
||||
std::vector<WireId> getGroupWires(GroupId group) const;
|
||||
|
@ -30,7 +30,7 @@ namespace PythonConversion {
|
||||
|
||||
template <> struct string_converter<BelId>
|
||||
{
|
||||
BelId from_str(Context *ctx, std::string name) { return ctx->getBelByName(ctx->id(name)); }
|
||||
BelId from_str(Context *ctx, std::string name) { return ctx->getBelByNameStr(name); }
|
||||
|
||||
std::string to_str(Context *ctx, BelId id)
|
||||
{
|
||||
@ -42,7 +42,7 @@ template <> struct string_converter<BelId>
|
||||
|
||||
template <> struct string_converter<WireId>
|
||||
{
|
||||
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); }
|
||||
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); }
|
||||
|
||||
std::string to_str(Context *ctx, WireId id)
|
||||
{
|
||||
@ -54,7 +54,7 @@ template <> struct string_converter<WireId>
|
||||
|
||||
template <> struct string_converter<const WireId>
|
||||
{
|
||||
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); }
|
||||
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); }
|
||||
|
||||
std::string to_str(Context *ctx, WireId id)
|
||||
{
|
||||
@ -66,7 +66,7 @@ template <> struct string_converter<const WireId>
|
||||
|
||||
template <> struct string_converter<PipId>
|
||||
{
|
||||
PipId from_str(Context *ctx, std::string name) { return ctx->getPipByName(ctx->id(name)); }
|
||||
PipId from_str(Context *ctx, std::string name) { return ctx->getPipByNameStr(name); }
|
||||
|
||||
std::string to_str(Context *ctx, PipId id)
|
||||
{
|
||||
|
@ -811,14 +811,12 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
NetInfo *lsrnet = nullptr;
|
||||
if (ci->ports.find(ctx->id("LSR")) != ci->ports.end() && ci->ports.at(ctx->id("LSR")).net != nullptr)
|
||||
lsrnet = ci->ports.at(ctx->id("LSR")).net;
|
||||
if (ctx->getBoundWireNet(ctx->getWireByName(
|
||||
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR0")))) == lsrnet) {
|
||||
if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR0")) == lsrnet) {
|
||||
cc.tiles[tname].add_enum("LSR0.SRMODE",
|
||||
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
|
||||
}
|
||||
if (ctx->getBoundWireNet(ctx->getWireByName(
|
||||
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR1")))) == lsrnet) {
|
||||
if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR1")) == lsrnet) {
|
||||
cc.tiles[tname].add_enum("LSR1.SRMODE",
|
||||
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum("LSR1.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
|
||||
@ -827,12 +825,10 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
NetInfo *clknet = nullptr;
|
||||
if (ci->ports.find(ctx->id("CLK")) != ci->ports.end() && ci->ports.at(ctx->id("CLK")).net != nullptr)
|
||||
clknet = ci->ports.at(ctx->id("CLK")).net;
|
||||
if (ctx->getBoundWireNet(ctx->getWireByName(
|
||||
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK0")))) == clknet) {
|
||||
if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK0")) == clknet) {
|
||||
cc.tiles[tname].add_enum("CLK0.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK"));
|
||||
}
|
||||
if (ctx->getBoundWireNet(ctx->getWireByName(
|
||||
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK1")))) == clknet) {
|
||||
if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK1")) == clknet) {
|
||||
cc.tiles[tname].add_enum("CLK1.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK"));
|
||||
}
|
||||
}
|
||||
@ -907,8 +903,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
(ci->ports.find(ctx->id("IOLTO")) == ci->ports.end() ||
|
||||
ci->ports.at(ctx->id("IOLTO")).net == nullptr)) {
|
||||
// Tie tristate low if unconnected for outputs or bidir
|
||||
std::string jpt = fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/JPADDT" << pio.back());
|
||||
WireId jpt_wire = ctx->getWireByName(ctx->id(jpt));
|
||||
WireId jpt_wire = ctx->getWireByLocAndBasename(bel.location, fmt_str("JPADDT" << pio.back()));
|
||||
PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin();
|
||||
WireId cib_wire = ctx->getPipSrcWire(jpt_pip);
|
||||
std::string cib_tile =
|
||||
|
@ -176,8 +176,8 @@ class Ecp5GlobalRouter
|
||||
}
|
||||
}
|
||||
if (upstream.size() > 30000) {
|
||||
log_error("failed to route HPBX%02d00 to %s.%s\n", global_index,
|
||||
ctx->getBelName(user.cell->bel).c_str(ctx), user.port.c_str(ctx));
|
||||
log_error("failed to route HPBX%02d00 to %s.%s\n", global_index, ctx->nameOfBel(user.cell->bel),
|
||||
user.port.c_str(ctx));
|
||||
}
|
||||
}
|
||||
// Set all the pips we found along the way
|
||||
@ -238,8 +238,7 @@ class Ecp5GlobalRouter
|
||||
if (visit.empty() || visit.size() > 50000) {
|
||||
if (allow_fail)
|
||||
return false;
|
||||
log_error("cannot route global from %s to %s.\n", ctx->getWireName(src).c_str(ctx),
|
||||
ctx->getWireName(dst).c_str(ctx));
|
||||
log_error("cannot route global from %s to %s.\n", ctx->nameOfWire(src), ctx->nameOfWire(dst));
|
||||
}
|
||||
cursor = visit.front();
|
||||
visit.pop();
|
||||
@ -300,7 +299,7 @@ class Ecp5GlobalRouter
|
||||
if (drv.cell == nullptr) {
|
||||
return 0;
|
||||
} else if (drv.cell->attrs.count(ctx->id("BEL"))) {
|
||||
drv_bel = ctx->getBelByName(ctx->id(drv.cell->attrs.at(ctx->id("BEL")).as_string()));
|
||||
drv_bel = ctx->getBelByNameStr(drv.cell->attrs.at(ctx->id("BEL")).as_string());
|
||||
} else {
|
||||
// Check if driver is a singleton
|
||||
BelId last_bel;
|
||||
@ -325,8 +324,8 @@ class Ecp5GlobalRouter
|
||||
} else {
|
||||
// Check for dedicated routing
|
||||
if (has_short_route(ctx->getBelPinWire(drv_bel, drv.port), ctx->getBelPinWire(dcc->bel, id_CLKI))) {
|
||||
// log_info("dedicated route %s -> %s\n", ctx->getWireName(ctx->getBelPinWire(drv_bel,
|
||||
// drv.port)).c_str(ctx), ctx->getBelName(dcc->bel).c_str(ctx));
|
||||
// log_info("dedicated route %s -> %s\n", ctx->nameOfWire(ctx->getBelPinWire(drv_bel,
|
||||
// drv.port)), ctx->nameOfWire(dcc->bel));
|
||||
dedicated_routing = true;
|
||||
return 0;
|
||||
}
|
||||
@ -347,8 +346,8 @@ class Ecp5GlobalRouter
|
||||
while (true) {
|
||||
|
||||
if (visit.empty() || visit.size() > 10000) {
|
||||
// log_info ("dist %s -> %s = inf\n", ctx->getWireName(src).c_str(ctx),
|
||||
// ctx->getWireName(dst).c_str(ctx));
|
||||
// log_info ("dist %s -> %s = inf\n", ctx->nameOfWire(src),
|
||||
// ctx->nameOfWire(dst));
|
||||
return false;
|
||||
}
|
||||
cursor = visit.front();
|
||||
@ -372,7 +371,7 @@ class Ecp5GlobalRouter
|
||||
cursor = ctx->getPipSrcWire(fnd->second);
|
||||
length++;
|
||||
}
|
||||
// log_info ("dist %s -> %s = %d\n", ctx->getWireName(src).c_str(ctx), ctx->getWireName(dst).c_str(ctx),
|
||||
// log_info ("dist %s -> %s = %d\n", ctx->nameOfWire(src), ctx->nameOfWire(dst),
|
||||
// length);
|
||||
return length < thresh;
|
||||
}
|
||||
|
48
ecp5/pack.cc
48
ecp5/pack.cc
@ -522,7 +522,7 @@ class Ecp5Packer
|
||||
trio->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str());
|
||||
} else {
|
||||
log_info("pin '%s' constrained to Bel '%s'.\n", trio->name.c_str(ctx),
|
||||
ctx->getBelName(pinBel).c_str(ctx));
|
||||
ctx->nameOfBel(pinBel));
|
||||
}
|
||||
trio->attrs[ctx->id("BEL")] = ctx->getBelName(pinBel).str(ctx);
|
||||
}
|
||||
@ -1657,7 +1657,7 @@ class Ecp5Packer
|
||||
CellInfo *dcu = clki->driver.cell;
|
||||
if (!dcu->attrs.count(ctx->id("BEL")))
|
||||
log_error("DCU must be constrained to a Bel!\n");
|
||||
BelId bel = ctx->getBelByName(ctx->id(dcu->attrs.at(ctx->id("BEL")).as_string()));
|
||||
BelId bel = ctx->getBelByNameStr(dcu->attrs.at(ctx->id("BEL")).as_string());
|
||||
if (bel == BelId())
|
||||
log_error("Invalid DCU bel '%s'\n", dcu->attrs.at(ctx->id("BEL")).c_str());
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
@ -1704,7 +1704,7 @@ class Ecp5Packer
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL")))
|
||||
available_plls.erase(ctx->getBelByName(ctx->id(ci->attrs.at(ctx->id("BEL")).as_string())));
|
||||
available_plls.erase(ctx->getBelByNameStr(ci->attrs.at(ctx->id("BEL")).as_string()));
|
||||
}
|
||||
// Place PLL connected to fixed drivers such as IO close to their source
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
@ -1716,7 +1716,7 @@ class Ecp5Packer
|
||||
const CellInfo *drivercell = drivernet->driver.cell;
|
||||
if (!drivercell->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
BelId drvbel = ctx->getBelByName(ctx->id(drivercell->attrs.at(ctx->id("BEL")).as_string()));
|
||||
BelId drvbel = ctx->getBelByNameStr(drivercell->attrs.at(ctx->id("BEL")).as_string());
|
||||
Loc drvloc = ctx->getBelLocation(drvbel);
|
||||
BelId closest_pll;
|
||||
int closest_distance = std::numeric_limits<int>::max();
|
||||
@ -1848,12 +1848,12 @@ class Ecp5Packer
|
||||
WireId next;
|
||||
while (true) {
|
||||
if (upstream.empty() || upstream.size() > 30000)
|
||||
log_error("failed to route bank %d ECLK%d to %s.%s\n", bank, found_eclk,
|
||||
ctx->getBelName(usr_bel).c_str(ctx), usr_port.name.c_str(ctx));
|
||||
log_error("failed to route bank %d ECLK%d to %s.%s\n", bank, found_eclk, ctx->nameOfBel(usr_bel),
|
||||
usr_port.name.c_str(ctx));
|
||||
next = upstream.front();
|
||||
upstream.pop();
|
||||
if (ctx->debug)
|
||||
log_info(" visited %s\n", ctx->getWireName(next).c_str(ctx));
|
||||
log_info(" visited %s\n", ctx->nameOfWire(next));
|
||||
IdString basename = ctx->getWireBasename(next);
|
||||
if (basename == bnke_name || basename == global_name) {
|
||||
break;
|
||||
@ -1913,17 +1913,17 @@ class Ecp5Packer
|
||||
log_error("DQSBUFM can only be used with a pin-constrained PIO connected to its DQSI input"
|
||||
"(while processing '%s').\n",
|
||||
ci->name.c_str(ctx));
|
||||
BelId pio_bel = ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string()));
|
||||
BelId pio_bel = ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string());
|
||||
NPNR_ASSERT(pio_bel != BelId());
|
||||
Loc pio_loc = ctx->getBelLocation(pio_bel);
|
||||
if (pio_loc.z != 0)
|
||||
log_error("PIO '%s' does not appear to be a DQS site (expecting an 'A' pin).\n",
|
||||
ctx->getBelName(pio_bel).c_str(ctx));
|
||||
ctx->nameOfBel(pio_bel));
|
||||
pio_loc.z = 8;
|
||||
BelId dqsbuf = ctx->getBelByLocation(pio_loc);
|
||||
if (dqsbuf == BelId() || ctx->getBelType(dqsbuf) != id_DQSBUFM)
|
||||
log_error("PIO '%s' does not appear to be a DQS site (didn't find a DQSBUFM).\n",
|
||||
ctx->getBelName(pio_bel).c_str(ctx));
|
||||
ctx->nameOfBel(pio_bel));
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(dqsbuf).str(ctx);
|
||||
bool got_dqsg = ctx->getPIODQSGroup(pio_bel, dqsbuf_dqsg[ci->name].first, dqsbuf_dqsg[ci->name].second);
|
||||
NPNR_ASSERT(got_dqsg);
|
||||
@ -2078,15 +2078,14 @@ class Ecp5Packer
|
||||
log_error("IOLOGIC functionality (DDR, DELAY, DQS, etc) can only be used with pin-constrained PIO "
|
||||
"(while processing '%s').\n",
|
||||
curr->name.c_str(ctx));
|
||||
BelId bel = ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string()));
|
||||
BelId bel = ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string());
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return bel;
|
||||
};
|
||||
|
||||
auto create_pio_iologic = [&](CellInfo *pio, CellInfo *curr) {
|
||||
BelId bel = get_pio_bel(pio, curr);
|
||||
log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx),
|
||||
ctx->getBelName(bel).c_str(ctx));
|
||||
log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx), ctx->nameOfBel(bel));
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
bool s = false;
|
||||
if (loc.y == 0 || loc.y == (ctx->chip_info->height - 1))
|
||||
@ -2292,8 +2291,7 @@ class Ecp5Packer
|
||||
replace_port(ci, ctx->id("D2"), iol, id_TXDATA2);
|
||||
replace_port(ci, ctx->id("D3"), iol, id_TXDATA3);
|
||||
if (ci->type == ctx->id("ODDR71B")) {
|
||||
Loc loc =
|
||||
ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
|
||||
Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
|
||||
if (loc.z % 2 == 1)
|
||||
log_error("ODDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
|
||||
replace_port(ci, ctx->id("D4"), iol, id_TXDATA4);
|
||||
@ -2326,8 +2324,7 @@ class Ecp5Packer
|
||||
replace_port(ci, ctx->id("Q2"), iol, id_RXDATA2);
|
||||
replace_port(ci, ctx->id("Q3"), iol, id_RXDATA3);
|
||||
if (ci->type == ctx->id("IDDR71B")) {
|
||||
Loc loc =
|
||||
ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
|
||||
Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
|
||||
if (loc.z % 2 == 1)
|
||||
log_error("IDDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
|
||||
replace_port(ci, ctx->id("Q4"), iol, id_RXDATA4);
|
||||
@ -2579,7 +2576,7 @@ class Ecp5Packer
|
||||
if (!user.cell->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
Loc user_loc = ctx->getBelLocation(
|
||||
ctx->getBelByName(ctx->id(user.cell->attrs.at(ctx->id("BEL")).as_string())));
|
||||
ctx->getBelByNameStr(user.cell->attrs.at(ctx->id("BEL")).as_string()));
|
||||
for (auto bel : ctx->getBels()) {
|
||||
if (ctx->getBelType(bel) != id_ECLKBRIDGECS)
|
||||
continue;
|
||||
@ -2594,8 +2591,8 @@ class Ecp5Packer
|
||||
CellInfo *drv = input->driver.cell;
|
||||
if (!drv->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
Loc drv_loc = ctx->getBelLocation(
|
||||
ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string())));
|
||||
Loc drv_loc =
|
||||
ctx->getBelLocation(ctx->getBelByNameStr(drv->attrs.at(ctx->id("BEL")).as_string()));
|
||||
BelId closest;
|
||||
int closest_x = -1; // aim for same side of chip
|
||||
for (auto bel : ctx->getBels()) {
|
||||
@ -2639,7 +2636,7 @@ class Ecp5Packer
|
||||
if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) {
|
||||
if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr)
|
||||
continue;
|
||||
BelId bel = ctx->getBelByName(ctx->id(str_or_default(ci->attrs, ctx->id("BEL"))));
|
||||
BelId bel = ctx->getBelByNameStr(str_or_default(ci->attrs, ctx->id("BEL")));
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
Loc pioLoc = ctx->getBelLocation(bel);
|
||||
if (ci->type == id_DQSBUFM)
|
||||
@ -2683,8 +2680,7 @@ class Ecp5Packer
|
||||
const NetInfo *eclko = net_or_nullptr(ci, id_ECLKO);
|
||||
if (eclki != nullptr && eclki->driver.cell != nullptr) {
|
||||
if (eclki->driver.cell->type == id_ECLKBRIDGECS) {
|
||||
BelId bel =
|
||||
ctx->getBelByName(ctx->id(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string()));
|
||||
BelId bel = ctx->getBelByNameStr(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string());
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
ci->attrs[ctx->id("BEL")] =
|
||||
ctx->getBelName(ctx->getBelByLocation(Loc(loc.x, loc.y, 15))).str(ctx);
|
||||
@ -2697,7 +2693,7 @@ class Ecp5Packer
|
||||
for (auto user : eclko->users) {
|
||||
if (user.cell->type == id_TRELLIS_ECLKBUF) {
|
||||
Loc eckbuf_loc = ctx->getBelLocation(
|
||||
ctx->getBelByName(ctx->id(user.cell->attrs.at(ctx->id("BEL")).as_string())));
|
||||
ctx->getBelByNameStr(user.cell->attrs.at(ctx->id("BEL")).as_string()));
|
||||
for (auto bel : ctx->getBels()) {
|
||||
if (ctx->getBelType(bel) != id_ECLKSYNCB)
|
||||
continue;
|
||||
@ -2726,7 +2722,7 @@ class Ecp5Packer
|
||||
const CellInfo *uc = usr.cell;
|
||||
if (uc->type != id_DQSBUFM || !uc->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
BelId dqsb_bel = ctx->getBelByName(ctx->id(uc->attrs.at(ctx->id("BEL")).as_string()));
|
||||
BelId dqsb_bel = ctx->getBelByNameStr(uc->attrs.at(ctx->id("BEL")).as_string());
|
||||
Loc dqsb_loc = ctx->getBelLocation(dqsb_bel);
|
||||
if (dqsb_loc.x > 15)
|
||||
right_bank_users = true;
|
||||
@ -2809,7 +2805,7 @@ class Ecp5Packer
|
||||
CellInfo *drv = clki->driver.cell;
|
||||
if (drv->type != id_ECLKSYNCB || !drv->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
BelId bel = ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string()));
|
||||
BelId bel = ctx->getBelByNameStr(drv->attrs.at(ctx->id("BEL")).as_string());
|
||||
// Find a CLKDIVF that is routeable from the ECLKSYNC
|
||||
std::queue<WireId> visit;
|
||||
visit.push(ctx->getBelPinWire(bel, id_ECLKO));
|
||||
|
@ -28,31 +28,31 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
WireInfo &Arch::wire_info(IdString wire)
|
||||
WireInfo &Arch::wire_info(IdStringList wire)
|
||||
{
|
||||
auto w = wires.find(wire);
|
||||
if (w == wires.end())
|
||||
NPNR_ASSERT_FALSE_STR("no wire named " + wire.str(this));
|
||||
NPNR_ASSERT_FALSE_STR("no wire named " + wire.str(getCtx()));
|
||||
return w->second;
|
||||
}
|
||||
|
||||
PipInfo &Arch::pip_info(IdString pip)
|
||||
PipInfo &Arch::pip_info(IdStringList pip)
|
||||
{
|
||||
auto p = pips.find(pip);
|
||||
if (p == pips.end())
|
||||
NPNR_ASSERT_FALSE_STR("no pip named " + pip.str(this));
|
||||
NPNR_ASSERT_FALSE_STR("no pip named " + pip.str(getCtx()));
|
||||
return p->second;
|
||||
}
|
||||
|
||||
BelInfo &Arch::bel_info(IdString bel)
|
||||
BelInfo &Arch::bel_info(IdStringList bel)
|
||||
{
|
||||
auto b = bels.find(bel);
|
||||
if (b == bels.end())
|
||||
NPNR_ASSERT_FALSE_STR("no bel named " + bel.str(this));
|
||||
NPNR_ASSERT_FALSE_STR("no bel named " + bel.str(getCtx()));
|
||||
return b->second;
|
||||
}
|
||||
|
||||
void Arch::addWire(IdString name, IdString type, int x, int y)
|
||||
void Arch::addWire(IdStringList name, IdString type, int x, int y)
|
||||
{
|
||||
NPNR_ASSERT(wires.count(name) == 0);
|
||||
WireInfo &wi = wires[name];
|
||||
@ -64,7 +64,8 @@ void Arch::addWire(IdString name, IdString type, int x, int y)
|
||||
wire_ids.push_back(name);
|
||||
}
|
||||
|
||||
void Arch::addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay, Loc loc)
|
||||
void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, DelayInfo delay,
|
||||
Loc loc)
|
||||
{
|
||||
NPNR_ASSERT(pips.count(name) == 0);
|
||||
PipInfo &pi = pips[name];
|
||||
@ -90,7 +91,7 @@ void Arch::addPip(IdString name, IdString type, IdString srcWire, IdString dstWi
|
||||
tilePipDimZ[loc.x][loc.y] = std::max(tilePipDimZ[loc.x][loc.y], loc.z + 1);
|
||||
}
|
||||
|
||||
void Arch::addBel(IdString name, IdString type, Loc loc, bool gb)
|
||||
void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb)
|
||||
{
|
||||
NPNR_ASSERT(bels.count(name) == 0);
|
||||
NPNR_ASSERT(bel_by_loc.count(loc) == 0);
|
||||
@ -124,7 +125,7 @@ void Arch::addBel(IdString name, IdString type, Loc loc, bool gb)
|
||||
tileBelDimZ[loc.x][loc.y] = std::max(tileBelDimZ[loc.x][loc.y], loc.z + 1);
|
||||
}
|
||||
|
||||
void Arch::addBelInput(IdString bel, IdString name, IdString wire)
|
||||
void Arch::addBelInput(IdStringList bel, IdString name, IdStringList wire)
|
||||
{
|
||||
NPNR_ASSERT(bel_info(bel).pins.count(name) == 0);
|
||||
PinInfo &pi = bel_info(bel).pins[name];
|
||||
@ -136,7 +137,7 @@ void Arch::addBelInput(IdString bel, IdString name, IdString wire)
|
||||
wire_info(wire).bel_pins.push_back(BelPin{bel, name});
|
||||
}
|
||||
|
||||
void Arch::addBelOutput(IdString bel, IdString name, IdString wire)
|
||||
void Arch::addBelOutput(IdStringList bel, IdString name, IdStringList wire)
|
||||
{
|
||||
NPNR_ASSERT(bel_info(bel).pins.count(name) == 0);
|
||||
PinInfo &pi = bel_info(bel).pins[name];
|
||||
@ -148,7 +149,7 @@ void Arch::addBelOutput(IdString bel, IdString name, IdString wire)
|
||||
wire_info(wire).bel_pins.push_back(BelPin{bel, name});
|
||||
}
|
||||
|
||||
void Arch::addBelInout(IdString bel, IdString name, IdString wire)
|
||||
void Arch::addBelInout(IdStringList bel, IdString name, IdStringList wire)
|
||||
{
|
||||
NPNR_ASSERT(bel_info(bel).pins.count(name) == 0);
|
||||
PinInfo &pi = bel_info(bel).pins[name];
|
||||
@ -160,13 +161,13 @@ void Arch::addBelInout(IdString bel, IdString name, IdString wire)
|
||||
wire_info(wire).bel_pins.push_back(BelPin{bel, name});
|
||||
}
|
||||
|
||||
void Arch::addGroupBel(IdString group, IdString bel) { groups[group].bels.push_back(bel); }
|
||||
void Arch::addGroupBel(IdStringList group, IdStringList bel) { groups[group].bels.push_back(bel); }
|
||||
|
||||
void Arch::addGroupWire(IdString group, IdString wire) { groups[group].wires.push_back(wire); }
|
||||
void Arch::addGroupWire(IdStringList group, IdStringList wire) { groups[group].wires.push_back(wire); }
|
||||
|
||||
void Arch::addGroupPip(IdString group, IdString pip) { groups[group].pips.push_back(pip); }
|
||||
void Arch::addGroupPip(IdStringList group, IdStringList pip) { groups[group].pips.push_back(pip); }
|
||||
|
||||
void Arch::addGroupGroup(IdString group, IdString grp) { groups[group].groups.push_back(grp); }
|
||||
void Arch::addGroupGroup(IdStringList group, IdStringList grp) { groups[group].groups.push_back(grp); }
|
||||
|
||||
void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic)
|
||||
{
|
||||
@ -198,11 +199,14 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy)
|
||||
refreshUiGroup(group);
|
||||
}
|
||||
|
||||
void Arch::setWireAttr(IdString wire, IdString key, const std::string &value) { wire_info(wire).attrs[key] = value; }
|
||||
void Arch::setWireAttr(IdStringList wire, IdString key, const std::string &value)
|
||||
{
|
||||
wire_info(wire).attrs[key] = value;
|
||||
}
|
||||
|
||||
void Arch::setPipAttr(IdString pip, IdString key, const std::string &value) { pip_info(pip).attrs[key] = value; }
|
||||
void Arch::setPipAttr(IdStringList pip, IdString key, const std::string &value) { pip_info(pip).attrs[key] = value; }
|
||||
|
||||
void Arch::setBelAttr(IdString bel, IdString key, const std::string &value) { bel_info(bel).attrs[key] = value; }
|
||||
void Arch::setBelAttr(IdStringList bel, IdString key, const std::string &value) { bel_info(bel).attrs[key] = value; }
|
||||
|
||||
void Arch::setLutK(int K) { args.K = K; }
|
||||
|
||||
@ -212,9 +216,12 @@ void Arch::setDelayScaling(double scale, double offset)
|
||||
args.delayOffset = offset;
|
||||
}
|
||||
|
||||
void Arch::addCellTimingClock(IdString cell, IdString port) { cellTiming[cell].portClasses[port] = TMG_CLOCK_INPUT; }
|
||||
void Arch::addCellTimingClock(IdStringList cell, IdString port)
|
||||
{
|
||||
cellTiming[cell].portClasses[port] = TMG_CLOCK_INPUT;
|
||||
}
|
||||
|
||||
void Arch::addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay)
|
||||
void Arch::addCellTimingDelay(IdStringList cell, IdString fromPort, IdString toPort, DelayInfo delay)
|
||||
{
|
||||
if (get_or_default(cellTiming[cell].portClasses, fromPort, TMG_IGNORE) == TMG_IGNORE)
|
||||
cellTiming[cell].portClasses[fromPort] = TMG_COMB_INPUT;
|
||||
@ -223,7 +230,7 @@ void Arch::addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort,
|
||||
cellTiming[cell].combDelays[CellDelayKey{fromPort, toPort}] = delay;
|
||||
}
|
||||
|
||||
void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold)
|
||||
void Arch::addCellTimingSetupHold(IdStringList cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold)
|
||||
{
|
||||
TimingClockingInfo ci;
|
||||
ci.clock_port = clock;
|
||||
@ -234,7 +241,7 @@ void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock,
|
||||
cellTiming[cell].portClasses[port] = TMG_REGISTER_INPUT;
|
||||
}
|
||||
|
||||
void Arch::addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq)
|
||||
void Arch::addCellTimingClockToOut(IdStringList cell, IdString port, IdString clock, DelayInfo clktoq)
|
||||
{
|
||||
TimingClockingInfo ci;
|
||||
ci.clock_port = clock;
|
||||
@ -256,14 +263,14 @@ void IdString::initialize_arch(const BaseCtx *ctx) {}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
BelId Arch::getBelByName(IdString name) const
|
||||
BelId Arch::getBelByName(IdStringList name) const
|
||||
{
|
||||
if (bels.count(name))
|
||||
return name;
|
||||
return BelId();
|
||||
}
|
||||
|
||||
IdString Arch::getBelName(BelId bel) const { return bel; }
|
||||
IdStringList Arch::getBelName(BelId bel) const { return bel; }
|
||||
|
||||
Loc Arch::getBelLocation(BelId bel) const
|
||||
{
|
||||
@ -321,7 +328,7 @@ WireId Arch::getBelPinWire(BelId bel, IdString pin) const
|
||||
{
|
||||
const auto &bdata = bels.at(bel);
|
||||
if (!bdata.pins.count(pin))
|
||||
log_error("bel '%s' has no pin '%s'\n", bel.c_str(this), pin.c_str(this));
|
||||
log_error("bel '%s' has no pin '%s'\n", getCtx()->nameOfBel(bel), pin.c_str(this));
|
||||
return bdata.pins.at(pin).wire;
|
||||
}
|
||||
|
||||
@ -337,14 +344,14 @@ std::vector<IdString> Arch::getBelPins(BelId bel) const
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
WireId Arch::getWireByName(IdString name) const
|
||||
WireId Arch::getWireByName(IdStringList name) const
|
||||
{
|
||||
if (wires.count(name))
|
||||
return name;
|
||||
return WireId();
|
||||
}
|
||||
|
||||
IdString Arch::getWireName(WireId wire) const { return wire; }
|
||||
IdStringList Arch::getWireName(WireId wire) const { return wire; }
|
||||
|
||||
IdString Arch::getWireType(WireId wire) const { return wires.at(wire).type; }
|
||||
|
||||
@ -391,14 +398,14 @@ const std::vector<WireId> &Arch::getWires() const { return wire_ids; }
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
PipId Arch::getPipByName(IdString name) const
|
||||
PipId Arch::getPipByName(IdStringList name) const
|
||||
{
|
||||
if (pips.count(name))
|
||||
return name;
|
||||
return PipId();
|
||||
}
|
||||
|
||||
IdString Arch::getPipName(PipId pip) const { return pip; }
|
||||
IdStringList Arch::getPipName(PipId pip) const { return pip; }
|
||||
|
||||
IdString Arch::getPipType(PipId pip) const { return pips.at(pip).type; }
|
||||
|
||||
@ -455,9 +462,9 @@ const std::vector<PipId> &Arch::getPipsUphill(WireId wire) const { return wires.
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
GroupId Arch::getGroupByName(IdString name) const { return name; }
|
||||
GroupId Arch::getGroupByName(IdStringList name) const { return name; }
|
||||
|
||||
IdString Arch::getGroupName(GroupId group) const { return group; }
|
||||
IdStringList Arch::getGroupName(GroupId group) const { return group; }
|
||||
|
||||
std::vector<GroupId> Arch::getGroups() const
|
||||
{
|
||||
@ -582,8 +589,7 @@ bool Arch::route()
|
||||
const std::vector<GraphicElement> &Arch::getDecalGraphics(DecalId decal) const
|
||||
{
|
||||
if (!decal_graphics.count(decal)) {
|
||||
std::cerr << "No decal named " << decal.str(this) << std::endl;
|
||||
log_error("No decal named %s!\n", decal.c_str(this));
|
||||
std::cerr << "No decal named " << decal.str(getCtx()) << std::endl;
|
||||
}
|
||||
return decal_graphics.at(decal);
|
||||
}
|
||||
|
@ -36,7 +36,8 @@ struct WireInfo;
|
||||
|
||||
struct PipInfo
|
||||
{
|
||||
IdString name, type;
|
||||
IdStringList name;
|
||||
IdString type;
|
||||
std::map<IdString, std::string> attrs;
|
||||
NetInfo *bound_net;
|
||||
WireId srcWire, dstWire;
|
||||
@ -47,7 +48,8 @@ struct PipInfo
|
||||
|
||||
struct WireInfo
|
||||
{
|
||||
IdString name, type;
|
||||
IdStringList name;
|
||||
IdString type;
|
||||
std::map<IdString, std::string> attrs;
|
||||
NetInfo *bound_net;
|
||||
std::vector<PipId> downhill, uphill;
|
||||
@ -60,14 +62,15 @@ struct WireInfo
|
||||
|
||||
struct PinInfo
|
||||
{
|
||||
IdString name;
|
||||
IdStringList name;
|
||||
WireId wire;
|
||||
PortType type;
|
||||
};
|
||||
|
||||
struct BelInfo
|
||||
{
|
||||
IdString name, type;
|
||||
IdStringList name;
|
||||
IdString type;
|
||||
std::map<IdString, std::string> attrs;
|
||||
CellInfo *bound_cell;
|
||||
std::unordered_map<IdString, PinInfo> pins;
|
||||
@ -78,7 +81,7 @@ struct BelInfo
|
||||
|
||||
struct GroupInfo
|
||||
{
|
||||
IdString name;
|
||||
IdStringList name;
|
||||
std::vector<BelId> bels;
|
||||
std::vector<WireId> wires;
|
||||
std::vector<PipId> pips;
|
||||
@ -117,17 +120,17 @@ struct Arch : BaseCtx
|
||||
{
|
||||
std::string chipName;
|
||||
|
||||
std::unordered_map<IdString, WireInfo> wires;
|
||||
std::unordered_map<IdString, PipInfo> pips;
|
||||
std::unordered_map<IdString, BelInfo> bels;
|
||||
std::unordered_map<IdStringList, WireInfo> wires;
|
||||
std::unordered_map<IdStringList, PipInfo> pips;
|
||||
std::unordered_map<IdStringList, BelInfo> bels;
|
||||
std::unordered_map<GroupId, GroupInfo> groups;
|
||||
|
||||
// These functions include useful errors if not found
|
||||
WireInfo &wire_info(IdString wire);
|
||||
PipInfo &pip_info(IdString wire);
|
||||
BelInfo &bel_info(IdString wire);
|
||||
WireInfo &wire_info(IdStringList wire);
|
||||
PipInfo &pip_info(IdStringList wire);
|
||||
BelInfo &bel_info(IdStringList wire);
|
||||
|
||||
std::vector<IdString> bel_ids, wire_ids, pip_ids;
|
||||
std::vector<IdStringList> bel_ids, wire_ids, pip_ids;
|
||||
|
||||
std::unordered_map<Loc, BelId> bel_by_loc;
|
||||
std::vector<std::vector<std::vector<BelId>>> bels_by_tile;
|
||||
@ -138,20 +141,20 @@ struct Arch : BaseCtx
|
||||
std::vector<std::vector<int>> tileBelDimZ;
|
||||
std::vector<std::vector<int>> tilePipDimZ;
|
||||
|
||||
std::unordered_map<IdString, CellTiming> cellTiming;
|
||||
std::unordered_map<IdStringList, CellTiming> cellTiming;
|
||||
|
||||
void addWire(IdString name, IdString type, int x, int y);
|
||||
void addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay, Loc loc);
|
||||
void addWire(IdStringList name, IdString type, int x, int y);
|
||||
void addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, DelayInfo delay, Loc loc);
|
||||
|
||||
void addBel(IdString name, IdString type, Loc loc, bool gb);
|
||||
void addBelInput(IdString bel, IdString name, IdString wire);
|
||||
void addBelOutput(IdString bel, IdString name, IdString wire);
|
||||
void addBelInout(IdString bel, IdString name, IdString wire);
|
||||
void addBel(IdStringList name, IdString type, Loc loc, bool gb);
|
||||
void addBelInput(IdStringList bel, IdString name, IdStringList wire);
|
||||
void addBelOutput(IdStringList bel, IdString name, IdStringList wire);
|
||||
void addBelInout(IdStringList bel, IdString name, IdStringList wire);
|
||||
|
||||
void addGroupBel(IdString group, IdString bel);
|
||||
void addGroupWire(IdString group, IdString wire);
|
||||
void addGroupPip(IdString group, IdString pip);
|
||||
void addGroupGroup(IdString group, IdString grp);
|
||||
void addGroupBel(IdStringList group, IdStringList bel);
|
||||
void addGroupWire(IdStringList group, IdStringList wire);
|
||||
void addGroupPip(IdStringList group, IdStringList pip);
|
||||
void addGroupGroup(IdStringList group, IdStringList grp);
|
||||
|
||||
void addDecalGraphic(DecalId decal, const GraphicElement &graphic);
|
||||
void setWireDecal(WireId wire, DecalXY decalxy);
|
||||
@ -159,17 +162,17 @@ struct Arch : BaseCtx
|
||||
void setBelDecal(BelId bel, DecalXY decalxy);
|
||||
void setGroupDecal(GroupId group, DecalXY decalxy);
|
||||
|
||||
void setWireAttr(IdString wire, IdString key, const std::string &value);
|
||||
void setPipAttr(IdString pip, IdString key, const std::string &value);
|
||||
void setBelAttr(IdString bel, IdString key, const std::string &value);
|
||||
void setWireAttr(IdStringList wire, IdString key, const std::string &value);
|
||||
void setPipAttr(IdStringList pip, IdString key, const std::string &value);
|
||||
void setBelAttr(IdStringList bel, IdString key, const std::string &value);
|
||||
|
||||
void setLutK(int K);
|
||||
void setDelayScaling(double scale, double offset);
|
||||
|
||||
void addCellTimingClock(IdString cell, IdString port);
|
||||
void addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay);
|
||||
void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold);
|
||||
void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq);
|
||||
void addCellTimingClock(IdStringList cell, IdString port);
|
||||
void addCellTimingDelay(IdStringList cell, IdString fromPort, IdString toPort, DelayInfo delay);
|
||||
void addCellTimingSetupHold(IdStringList cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold);
|
||||
void addCellTimingClockToOut(IdStringList cell, IdString port, IdString clock, DelayInfo clktoq);
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Common Arch API. Every arch must provide the following methods.
|
||||
@ -187,9 +190,10 @@ struct Arch : BaseCtx
|
||||
int getGridDimY() const { return gridDimY; }
|
||||
int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; }
|
||||
int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; }
|
||||
char getNameDelimiter() const { return '/'; }
|
||||
|
||||
BelId getBelByName(IdString name) const;
|
||||
IdString getBelName(BelId bel) const;
|
||||
BelId getBelByName(IdStringList name) const;
|
||||
IdStringList getBelName(BelId bel) const;
|
||||
Loc getBelLocation(BelId bel) const;
|
||||
BelId getBelByLocation(Loc loc) const;
|
||||
const std::vector<BelId> &getBelsByTile(int x, int y) const;
|
||||
@ -207,8 +211,8 @@ struct Arch : BaseCtx
|
||||
PortType getBelPinType(BelId bel, IdString pin) const;
|
||||
std::vector<IdString> getBelPins(BelId bel) const;
|
||||
|
||||
WireId getWireByName(IdString name) const;
|
||||
IdString getWireName(WireId wire) const;
|
||||
WireId getWireByName(IdStringList name) const;
|
||||
IdStringList getWireName(WireId wire) const;
|
||||
IdString getWireType(WireId wire) const;
|
||||
const std::map<IdString, std::string> &getWireAttrs(WireId wire) const;
|
||||
uint32_t getWireChecksum(WireId wire) const;
|
||||
@ -222,8 +226,8 @@ struct Arch : BaseCtx
|
||||
const std::vector<WireId> &getWires() const;
|
||||
const std::vector<BelPin> &getWireBelPins(WireId wire) const;
|
||||
|
||||
PipId getPipByName(IdString name) const;
|
||||
IdString getPipName(PipId pip) const;
|
||||
PipId getPipByName(IdStringList name) const;
|
||||
IdStringList getPipName(PipId pip) const;
|
||||
IdString getPipType(PipId pip) const;
|
||||
const std::map<IdString, std::string> &getPipAttrs(PipId pip) const;
|
||||
uint32_t getPipChecksum(PipId pip) const;
|
||||
@ -241,8 +245,8 @@ struct Arch : BaseCtx
|
||||
const std::vector<PipId> &getPipsDownhill(WireId wire) const;
|
||||
const std::vector<PipId> &getPipsUphill(WireId wire) const;
|
||||
|
||||
GroupId getGroupByName(IdString name) const;
|
||||
IdString getGroupName(GroupId group) const;
|
||||
GroupId getGroupByName(IdStringList name) const;
|
||||
IdStringList getGroupName(GroupId group) const;
|
||||
std::vector<GroupId> getGroups() const;
|
||||
const std::vector<BelId> &getGroupBels(GroupId group) const;
|
||||
const std::vector<WireId> &getGroupWires(GroupId group) const;
|
||||
@ -273,13 +277,12 @@ struct Arch : BaseCtx
|
||||
|
||||
std::vector<IdString> getCellTypes() const
|
||||
{
|
||||
std::vector<IdString> cell_types;
|
||||
cell_types.reserve(bels.size());
|
||||
std::unordered_set<IdString> cell_types;
|
||||
for (auto bel : bels) {
|
||||
cell_types.push_back(bel.first);
|
||||
cell_types.insert(bel.second.type);
|
||||
}
|
||||
|
||||
return cell_types;
|
||||
return std::vector<IdString>{cell_types.begin(), cell_types.end()};
|
||||
}
|
||||
|
||||
std::vector<BelBucketId> getBelBuckets() const { return getCellTypes(); }
|
||||
|
@ -35,6 +35,7 @@ template <> struct string_converter<const IdString &>
|
||||
|
||||
std::string to_str(Context *ctx, const IdString &id) { return id.str(ctx); }
|
||||
};
|
||||
|
||||
} // namespace PythonConversion
|
||||
|
||||
void arch_wrap_python(py::module &m)
|
||||
@ -152,37 +153,37 @@ void arch_wrap_python(py::module &m)
|
||||
pass_through<float>>::def_wrap(ctx_cls, "addClock");
|
||||
|
||||
// Generic arch construction API
|
||||
fn_wrapper_4a_v<Context, decltype(&Context::addWire), &Context::addWire, conv_from_str<IdString>,
|
||||
fn_wrapper_4a_v<Context, decltype(&Context::addWire), &Context::addWire, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdString>, pass_through<int>, pass_through<int>>::def_wrap(ctx_cls, "addWire",
|
||||
"name"_a, "type"_a, "x"_a,
|
||||
"y"_a);
|
||||
fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdString>,
|
||||
conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, pass_through<DelayInfo>,
|
||||
pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, "srcWire"_a, "dstWire"_a,
|
||||
"delay"_a, "loc"_a);
|
||||
fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdString>, conv_from_str<IdStringList>, conv_from_str<IdStringList>,
|
||||
pass_through<DelayInfo>, pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a,
|
||||
"srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a);
|
||||
|
||||
fn_wrapper_4a_v<Context, decltype(&Context::addBel), &Context::addBel, conv_from_str<IdString>,
|
||||
fn_wrapper_4a_v<Context, decltype(&Context::addBel), &Context::addBel, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdString>, pass_through<Loc>, pass_through<bool>>::def_wrap(ctx_cls, "addBel",
|
||||
"name"_a, "type"_a,
|
||||
"loc"_a, "gb"_a);
|
||||
fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<IdString>,
|
||||
conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addBelInput", "bel"_a,
|
||||
fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInput", "bel"_a,
|
||||
"name"_a, "wire"_a);
|
||||
fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<IdString>,
|
||||
conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a,
|
||||
fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a,
|
||||
"name"_a, "wire"_a);
|
||||
fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<IdString>,
|
||||
conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addBelInout", "bel"_a,
|
||||
fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInout", "bel"_a,
|
||||
"name"_a, "wire"_a);
|
||||
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addGroupBel), &Context::addGroupBel, conv_from_str<IdString>,
|
||||
conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a);
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addGroupWire), &Context::addGroupWire, conv_from_str<IdString>,
|
||||
conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a);
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addGroupPip), &Context::addGroupPip, conv_from_str<IdString>,
|
||||
conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a);
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupPip, conv_from_str<IdString>,
|
||||
conv_from_str<IdString>>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a);
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addGroupBel), &Context::addGroupBel, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a);
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addGroupWire), &Context::addGroupWire, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a);
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addGroupPip), &Context::addGroupPip, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a);
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupPip, conv_from_str<IdStringList>,
|
||||
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a);
|
||||
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addDecalGraphic), &Context::addDecalGraphic, conv_from_str<DecalId>,
|
||||
pass_through<GraphicElement>>::def_wrap(ctx_cls, "addDecalGraphic", (py::arg("decal"), "graphic"));
|
||||
@ -211,15 +212,16 @@ void arch_wrap_python(py::module &m)
|
||||
pass_through<double>>::def_wrap(ctx_cls, "setDelayScaling", "scale"_a, "offset"_a);
|
||||
|
||||
fn_wrapper_2a_v<Context, decltype(&Context::addCellTimingClock), &Context::addCellTimingClock,
|
||||
conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addCellTimingClock", "cell"_a,
|
||||
"port"_a);
|
||||
conv_from_str<IdStringList>, conv_from_str<IdString>>::def_wrap(ctx_cls, "addCellTimingClock",
|
||||
"cell"_a, "port"_a);
|
||||
fn_wrapper_4a_v<Context, decltype(&Context::addCellTimingDelay), &Context::addCellTimingDelay,
|
||||
conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>,
|
||||
conv_from_str<IdStringList>, conv_from_str<IdString>, conv_from_str<IdString>,
|
||||
pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingDelay", "cell"_a, "fromPort"_a,
|
||||
"toPort"_a, "delay"_a);
|
||||
fn_wrapper_5a_v<Context, decltype(&Context::addCellTimingSetupHold), &Context::addCellTimingSetupHold,
|
||||
conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, pass_through<DelayInfo>,
|
||||
pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingSetupHold", "cell"_a, "port"_a, "clock"_a,
|
||||
conv_from_str<IdStringList>, conv_from_str<IdString>, conv_from_str<IdString>,
|
||||
pass_through<DelayInfo>, pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingSetupHold",
|
||||
"cell"_a, "port"_a, "clock"_a,
|
||||
"setup"_a, "hold"_a);
|
||||
fn_wrapper_4a_v<Context, decltype(&Context::addCellTimingClockToOut), &Context::addCellTimingClockToOut,
|
||||
conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>,
|
||||
|
@ -46,11 +46,11 @@ struct DelayInfo
|
||||
}
|
||||
};
|
||||
|
||||
typedef IdString BelId;
|
||||
typedef IdString WireId;
|
||||
typedef IdString PipId;
|
||||
typedef IdString GroupId;
|
||||
typedef IdString DecalId;
|
||||
typedef IdStringList BelId;
|
||||
typedef IdStringList WireId;
|
||||
typedef IdStringList PipId;
|
||||
typedef IdStringList GroupId;
|
||||
typedef IdStringList DecalId;
|
||||
typedef IdString BelBucketId;
|
||||
|
||||
struct ArchNetInfo
|
||||
|
@ -759,14 +759,14 @@ void IdString::initialize_arch(const BaseCtx *ctx)
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
BelId Arch::getBelByName(IdString name) const
|
||||
BelId Arch::getBelByName(IdStringList name) const
|
||||
{
|
||||
if (bels.count(name))
|
||||
return name;
|
||||
if (bels.count(name[0]))
|
||||
return name[0];
|
||||
return BelId();
|
||||
}
|
||||
|
||||
IdString Arch::getBelName(BelId bel) const { return bel; }
|
||||
IdStringList Arch::getBelName(BelId bel) const { return IdStringList(bel); }
|
||||
|
||||
Loc Arch::getBelLocation(BelId bel) const
|
||||
{
|
||||
@ -836,14 +836,14 @@ std::vector<IdString> Arch::getBelPins(BelId bel) const
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
WireId Arch::getWireByName(IdString name) const
|
||||
WireId Arch::getWireByName(IdStringList name) const
|
||||
{
|
||||
if (wires.count(name))
|
||||
return name;
|
||||
if (wires.count(name[0]))
|
||||
return name[0];
|
||||
return WireId();
|
||||
}
|
||||
|
||||
IdString Arch::getWireName(WireId wire) const { return wire; }
|
||||
IdStringList Arch::getWireName(WireId wire) const { return IdStringList(wire); }
|
||||
|
||||
IdString Arch::getWireType(WireId wire) const { return wires.at(wire).type; }
|
||||
|
||||
@ -890,14 +890,14 @@ const std::vector<WireId> &Arch::getWires() const { return wire_ids; }
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
PipId Arch::getPipByName(IdString name) const
|
||||
PipId Arch::getPipByName(IdStringList name) const
|
||||
{
|
||||
if (pips.count(name))
|
||||
return name;
|
||||
if (pips.count(name[0]))
|
||||
return name[0];
|
||||
return PipId();
|
||||
}
|
||||
|
||||
IdString Arch::getPipName(PipId pip) const { return pip; }
|
||||
IdStringList Arch::getPipName(PipId pip) const { return IdStringList(pip); }
|
||||
|
||||
IdString Arch::getPipType(PipId pip) const { return pips.at(pip).type; }
|
||||
|
||||
@ -950,9 +950,9 @@ const std::vector<PipId> &Arch::getPipsUphill(WireId wire) const { return wires.
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
GroupId Arch::getGroupByName(IdString name) const { return name; }
|
||||
GroupId Arch::getGroupByName(IdStringList name) const { return name[0]; }
|
||||
|
||||
IdString Arch::getGroupName(GroupId group) const { return group; }
|
||||
IdStringList Arch::getGroupName(GroupId group) const { return IdStringList(group); }
|
||||
|
||||
std::vector<GroupId> Arch::getGroups() const
|
||||
{
|
||||
|
20
gowin/arch.h
20
gowin/arch.h
@ -323,9 +323,13 @@ struct Arch : BaseCtx
|
||||
int getGridDimY() const { return gridDimY; }
|
||||
int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; }
|
||||
int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; }
|
||||
char getNameDelimiter() const
|
||||
{
|
||||
return ' '; /* use a non-existent delimiter as we aren't using IdStringLists yet */
|
||||
}
|
||||
|
||||
BelId getBelByName(IdString name) const;
|
||||
IdString getBelName(BelId bel) const;
|
||||
BelId getBelByName(IdStringList name) const;
|
||||
IdStringList getBelName(BelId bel) const;
|
||||
Loc getBelLocation(BelId bel) const;
|
||||
BelId getBelByLocation(Loc loc) const;
|
||||
const std::vector<BelId> &getBelsByTile(int x, int y) const;
|
||||
@ -343,8 +347,8 @@ struct Arch : BaseCtx
|
||||
PortType getBelPinType(BelId bel, IdString pin) const;
|
||||
std::vector<IdString> getBelPins(BelId bel) const;
|
||||
|
||||
WireId getWireByName(IdString name) const;
|
||||
IdString getWireName(WireId wire) const;
|
||||
WireId getWireByName(IdStringList name) const;
|
||||
IdStringList getWireName(WireId wire) const;
|
||||
IdString getWireType(WireId wire) const;
|
||||
const std::map<IdString, std::string> &getWireAttrs(WireId wire) const;
|
||||
uint32_t getWireChecksum(WireId wire) const;
|
||||
@ -358,8 +362,8 @@ struct Arch : BaseCtx
|
||||
const std::vector<WireId> &getWires() const;
|
||||
const std::vector<BelPin> &getWireBelPins(WireId wire) const;
|
||||
|
||||
PipId getPipByName(IdString name) const;
|
||||
IdString getPipName(PipId pip) const;
|
||||
PipId getPipByName(IdStringList name) const;
|
||||
IdStringList getPipName(PipId pip) const;
|
||||
IdString getPipType(PipId pip) const;
|
||||
const std::map<IdString, std::string> &getPipAttrs(PipId pip) const;
|
||||
uint32_t getPipChecksum(PipId pip) const;
|
||||
@ -377,8 +381,8 @@ struct Arch : BaseCtx
|
||||
const std::vector<PipId> &getPipsDownhill(WireId wire) const;
|
||||
const std::vector<PipId> &getPipsUphill(WireId wire) const;
|
||||
|
||||
GroupId getGroupByName(IdString name) const;
|
||||
IdString getGroupName(GroupId group) const;
|
||||
GroupId getGroupByName(IdStringList name) const;
|
||||
IdStringList getGroupName(GroupId group) const;
|
||||
std::vector<GroupId> getGroups() const;
|
||||
const std::vector<BelId> &getGroupBels(GroupId group) const;
|
||||
const std::vector<WireId> &getGroupWires(GroupId group) const;
|
||||
|
@ -340,11 +340,9 @@ void DesignWidget::newContext(Context *ctx)
|
||||
}
|
||||
|
||||
getTreeByElementType(ElementType::CELL)
|
||||
->loadData(ctx,
|
||||
std::unique_ptr<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::CELL)));
|
||||
->loadData(ctx, std::unique_ptr<TreeModel::IdList>(new TreeModel::IdList(ElementType::CELL)));
|
||||
getTreeByElementType(ElementType::NET)
|
||||
->loadData(ctx,
|
||||
std::unique_ptr<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::NET)));
|
||||
->loadData(ctx, std::unique_ptr<TreeModel::IdList>(new TreeModel::IdList(ElementType::NET)));
|
||||
}
|
||||
updateTree();
|
||||
}
|
||||
@ -357,10 +355,10 @@ void DesignWidget::updateTree()
|
||||
while (i != highlightSelected.end()) {
|
||||
QMap<TreeModel::Item *, int>::iterator prev = i;
|
||||
++i;
|
||||
if (prev.key()->type() == ElementType::NET && ctx->nets.find(prev.key()->id()) == ctx->nets.end()) {
|
||||
if (prev.key()->type() == ElementType::NET && ctx->nets.find(prev.key()->id()[0]) == ctx->nets.end()) {
|
||||
highlightSelected.erase(prev);
|
||||
}
|
||||
if (prev.key()->type() == ElementType::CELL && ctx->cells.find(prev.key()->id()) == ctx->cells.end()) {
|
||||
if (prev.key()->type() == ElementType::CELL && ctx->cells.find(prev.key()->id()[0]) == ctx->cells.end()) {
|
||||
highlightSelected.erase(prev);
|
||||
}
|
||||
}
|
||||
@ -369,13 +367,13 @@ void DesignWidget::updateTree()
|
||||
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
|
||||
std::lock_guard<std::mutex> lock(ctx->mutex);
|
||||
|
||||
std::vector<IdString> cells;
|
||||
std::vector<IdStringList> cells;
|
||||
for (auto &pair : ctx->cells) {
|
||||
cells.push_back(pair.first);
|
||||
cells.push_back(IdStringList(pair.first));
|
||||
}
|
||||
std::vector<IdString> nets;
|
||||
std::vector<IdStringList> nets;
|
||||
for (auto &pair : ctx->nets) {
|
||||
nets.push_back(pair.first);
|
||||
nets.push_back(IdStringList(pair.first));
|
||||
}
|
||||
|
||||
getTreeByElementType(ElementType::CELL)->updateElements(cells);
|
||||
@ -603,7 +601,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
|
||||
clearProperties();
|
||||
|
||||
IdString c = clickItem->id();
|
||||
IdStringList c = clickItem->id();
|
||||
Q_EMIT selected(getDecals(type, c), false);
|
||||
|
||||
if (type == ElementType::BEL) {
|
||||
@ -613,7 +611,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
BelId bel = ctx->getBelByName(c);
|
||||
QtProperty *topItem = addTopLevelProperty("Bel");
|
||||
|
||||
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
||||
addProperty(topItem, QVariant::String, "Name", ctx->nameOfBel(bel));
|
||||
addProperty(topItem, QVariant::String, "Type", ctx->getBelType(bel).c_str(ctx));
|
||||
addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel));
|
||||
addProperty(topItem, QVariant::String, "Bound Cell", ctx->nameOf(ctx->getBoundBelCell(bel)), ElementType::CELL);
|
||||
@ -631,7 +629,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
addProperty(portInfoItem, QVariant::String, "Name", item.c_str(ctx));
|
||||
addProperty(portInfoItem, QVariant::Int, "Type", int(ctx->getBelPinType(bel, item)));
|
||||
WireId wire = ctx->getBelPinWire(bel, item);
|
||||
addProperty(portInfoItem, QVariant::String, "Wire", ctx->getWireName(wire).c_str(ctx), ElementType::WIRE);
|
||||
addProperty(portInfoItem, QVariant::String, "Wire", ctx->nameOfWire(wire), ElementType::WIRE);
|
||||
}
|
||||
} else if (type == ElementType::WIRE) {
|
||||
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
|
||||
@ -640,12 +638,12 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
WireId wire = ctx->getWireByName(c);
|
||||
QtProperty *topItem = addTopLevelProperty("Wire");
|
||||
|
||||
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
||||
addProperty(topItem, QVariant::String, "Name", ctx->nameOfWire(wire));
|
||||
addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx));
|
||||
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire));
|
||||
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET);
|
||||
addProperty(topItem, QVariant::String, "Conflicting Wire",
|
||||
ctx->getWireName(ctx->getConflictingWireWire(wire)).c_str(ctx), ElementType::WIRE);
|
||||
addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->nameOfWire(ctx->getConflictingWireWire(wire)),
|
||||
ElementType::WIRE);
|
||||
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)),
|
||||
ElementType::NET);
|
||||
|
||||
@ -666,7 +664,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
for (const auto &item : ctx->getWireBelPins(wire)) {
|
||||
QString belname = "";
|
||||
if (item.bel != BelId())
|
||||
belname = ctx->getBelName(item.bel).c_str(ctx);
|
||||
belname = ctx->nameOfBel(item.bel);
|
||||
QString pinname = item.pin.c_str(ctx);
|
||||
|
||||
QtProperty *dhItem = addSubGroup(belpinsItem, belname + "-" + pinname);
|
||||
@ -677,7 +675,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
int counter = 0;
|
||||
QtProperty *pipsDownItem = addSubGroup(topItem, "Pips Downhill");
|
||||
for (const auto &item : ctx->getPipsDownhill(wire)) {
|
||||
addProperty(pipsDownItem, QVariant::String, "", ctx->getPipName(item).c_str(ctx), ElementType::PIP);
|
||||
addProperty(pipsDownItem, QVariant::String, "", ctx->nameOfPip(item), ElementType::PIP);
|
||||
counter++;
|
||||
if (counter == 50) {
|
||||
addProperty(pipsDownItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE);
|
||||
@ -688,7 +686,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
counter = 0;
|
||||
QtProperty *pipsUpItem = addSubGroup(topItem, "Pips Uphill");
|
||||
for (const auto &item : ctx->getPipsUphill(wire)) {
|
||||
addProperty(pipsUpItem, QVariant::String, "", ctx->getPipName(item).c_str(ctx), ElementType::PIP);
|
||||
addProperty(pipsUpItem, QVariant::String, "", ctx->nameOfPip(item), ElementType::PIP);
|
||||
counter++;
|
||||
if (counter == 50) {
|
||||
addProperty(pipsUpItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE);
|
||||
@ -702,21 +700,20 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
PipId pip = ctx->getPipByName(c);
|
||||
QtProperty *topItem = addTopLevelProperty("Pip");
|
||||
|
||||
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
|
||||
addProperty(topItem, QVariant::String, "Name", ctx->nameOfPip(pip));
|
||||
addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx));
|
||||
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
|
||||
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
|
||||
if (ctx->getConflictingPipWire(pip) != WireId()) {
|
||||
addProperty(topItem, QVariant::String, "Conflicting Wire",
|
||||
ctx->getWireName(ctx->getConflictingPipWire(pip)).c_str(ctx), ElementType::WIRE);
|
||||
addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->nameOfWire(ctx->getConflictingPipWire(pip)),
|
||||
ElementType::WIRE);
|
||||
} else {
|
||||
addProperty(topItem, QVariant::String, "Conflicting Wire", "", ElementType::NONE);
|
||||
}
|
||||
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)),
|
||||
ElementType::NET);
|
||||
addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx),
|
||||
ElementType::WIRE);
|
||||
addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx),
|
||||
addProperty(topItem, QVariant::String, "Src Wire", ctx->nameOfWire(ctx->getPipSrcWire(pip)), ElementType::WIRE);
|
||||
addProperty(topItem, QVariant::String, "Dest Wire", ctx->nameOfWire(ctx->getPipDstWire(pip)),
|
||||
ElementType::WIRE);
|
||||
|
||||
QtProperty *attrsItem = addSubGroup(topItem, "Attributes");
|
||||
@ -735,7 +732,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
|
||||
std::lock_guard<std::mutex> lock(ctx->mutex);
|
||||
|
||||
NetInfo *net = ctx->nets.at(c).get();
|
||||
NetInfo *net = ctx->nets.at(c[0]).get();
|
||||
|
||||
QtProperty *topItem = addTopLevelProperty("Net");
|
||||
|
||||
@ -769,14 +766,13 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
|
||||
QtProperty *wiresItem = addSubGroup(topItem, "Wires");
|
||||
for (auto &item : net->wires) {
|
||||
auto name = ctx->getWireName(item.first).c_str(ctx);
|
||||
auto name = ctx->nameOfWire(item.first);
|
||||
|
||||
QtProperty *wireItem = addSubGroup(wiresItem, name);
|
||||
addProperty(wireItem, QVariant::String, "Wire", name, ElementType::WIRE);
|
||||
|
||||
if (item.second.pip != PipId())
|
||||
addProperty(wireItem, QVariant::String, "Pip", ctx->getPipName(item.second.pip).c_str(ctx),
|
||||
ElementType::PIP);
|
||||
addProperty(wireItem, QVariant::String, "Pip", ctx->nameOfPip(item.second.pip), ElementType::PIP);
|
||||
else
|
||||
addProperty(wireItem, QVariant::String, "Pip", "", ElementType::PIP);
|
||||
|
||||
@ -787,14 +783,14 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
|
||||
std::lock_guard<std::mutex> lock(ctx->mutex);
|
||||
|
||||
CellInfo *cell = ctx->cells.at(c).get();
|
||||
CellInfo *cell = ctx->cells.at(c[0]).get();
|
||||
|
||||
QtProperty *topItem = addTopLevelProperty("Cell");
|
||||
|
||||
addProperty(topItem, QVariant::String, "Name", cell->name.c_str(ctx));
|
||||
addProperty(topItem, QVariant::String, "Type", cell->type.c_str(ctx));
|
||||
if (cell->bel != BelId())
|
||||
addProperty(topItem, QVariant::String, "Bel", ctx->getBelName(cell->bel).c_str(ctx), ElementType::BEL);
|
||||
addProperty(topItem, QVariant::String, "Bel", ctx->nameOfBel(cell->bel), ElementType::BEL);
|
||||
else
|
||||
addProperty(topItem, QVariant::String, "Bel", "", ElementType::BEL);
|
||||
addProperty(topItem, QVariant::Int, "Bel strength", int(cell->belStrength));
|
||||
@ -838,7 +834,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
|
||||
std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdStringList value)
|
||||
{
|
||||
std::vector<DecalXY> decals;
|
||||
switch (type) {
|
||||
@ -861,7 +857,7 @@ std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
|
||||
}
|
||||
} break;
|
||||
case ElementType::NET: {
|
||||
NetInfo *net = ctx->nets.at(value).get();
|
||||
NetInfo *net = ctx->nets.at(value[0]).get();
|
||||
for (auto &item : net->wires) {
|
||||
decals.push_back(ctx->getWireDecal(item.first));
|
||||
if (item.second.pip != PipId()) {
|
||||
@ -870,7 +866,7 @@ std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
|
||||
}
|
||||
} break;
|
||||
case ElementType::CELL: {
|
||||
CellInfo *cell = ctx->cells.at(value).get();
|
||||
CellInfo *cell = ctx->cells.at(value[0]).get();
|
||||
if (cell->bel != BelId()) {
|
||||
decals.push_back(ctx->getBelDecal(cell->bel));
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ class DesignWidget : public QWidget
|
||||
int getElementIndex(ElementType type);
|
||||
void updateButtons();
|
||||
void addToHistory(int tab, QModelIndex item);
|
||||
std::vector<DecalXY> getDecals(ElementType type, IdString value);
|
||||
std::vector<DecalXY> getDecals(ElementType type, IdStringList value);
|
||||
void updateHighlightGroup(QList<TreeModel::Item *> item, int group);
|
||||
void clearAllSelectionModels();
|
||||
Q_SIGNALS:
|
||||
|
@ -779,22 +779,22 @@ void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
rendererArgs_->x = event->x();
|
||||
rendererArgs_->y = event->y();
|
||||
if (closest.type == ElementType::BEL) {
|
||||
rendererArgs_->hintText = std::string("BEL\n") + ctx_->getBelName(closest.bel).c_str(ctx_);
|
||||
rendererArgs_->hintText = std::string("BEL\n") + ctx_->getBelName(closest.bel).str(ctx_);
|
||||
CellInfo *cell = ctx_->getBoundBelCell(closest.bel);
|
||||
if (cell != nullptr)
|
||||
rendererArgs_->hintText += std::string("\nCELL\n") + ctx_->nameOf(cell);
|
||||
} else if (closest.type == ElementType::WIRE) {
|
||||
rendererArgs_->hintText = std::string("WIRE\n") + ctx_->getWireName(closest.wire).c_str(ctx_);
|
||||
rendererArgs_->hintText = std::string("WIRE\n") + ctx_->getWireName(closest.wire).str(ctx_);
|
||||
NetInfo *net = ctx_->getBoundWireNet(closest.wire);
|
||||
if (net != nullptr)
|
||||
rendererArgs_->hintText += std::string("\nNET\n") + ctx_->nameOf(net);
|
||||
} else if (closest.type == ElementType::PIP) {
|
||||
rendererArgs_->hintText = std::string("PIP\n") + ctx_->getPipName(closest.pip).c_str(ctx_);
|
||||
rendererArgs_->hintText = std::string("PIP\n") + ctx_->getPipName(closest.pip).str(ctx_);
|
||||
NetInfo *net = ctx_->getBoundPipNet(closest.pip);
|
||||
if (net != nullptr)
|
||||
rendererArgs_->hintText += std::string("\nNET\n") + ctx_->nameOf(net);
|
||||
} else if (closest.type == ElementType::GROUP) {
|
||||
rendererArgs_->hintText = std::string("GROUP\n") + ctx_->getGroupName(closest.group).c_str(ctx_);
|
||||
rendererArgs_->hintText = std::string("GROUP\n") + ctx_->getGroupName(closest.group).str(ctx_);
|
||||
} else
|
||||
rendererArgs_->hintText = "";
|
||||
|
||||
|
@ -26,7 +26,7 @@ NEXTPNR_NAMESPACE_BEGIN
|
||||
namespace TreeModel {
|
||||
|
||||
// converts 'aa123bb432' -> ['aa', '123', 'bb', '432']
|
||||
std::vector<QString> IdStringList::alphaNumSplit(const QString &str)
|
||||
std::vector<QString> IdList::alphaNumSplit(const QString &str)
|
||||
{
|
||||
std::vector<QString> res;
|
||||
QString current_part;
|
||||
@ -53,12 +53,12 @@ std::vector<QString> IdStringList::alphaNumSplit(const QString &str)
|
||||
return res;
|
||||
}
|
||||
|
||||
void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements)
|
||||
void IdList::updateElements(Context *ctx, std::vector<IdStringList> elements)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
// For any elements that are not yet in managed_, created them.
|
||||
std::unordered_set<IdString> element_set;
|
||||
std::unordered_set<IdStringList> element_set;
|
||||
for (auto elem : elements) {
|
||||
element_set.insert(elem);
|
||||
auto existing = managed_.find(elem);
|
||||
@ -134,7 +134,7 @@ void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements)
|
||||
});
|
||||
}
|
||||
|
||||
void IdStringList::search(QList<Item *> &results, QString text, int limit)
|
||||
void IdList::search(QList<Item *> &results, QString text, int limit)
|
||||
{
|
||||
for (const auto &child : children_) {
|
||||
if (limit != -1 && results.size() > limit)
|
||||
@ -157,7 +157,7 @@ void Model::loadData(Context *ctx, std::unique_ptr<Item> data)
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void Model::updateElements(std::vector<IdString> elements)
|
||||
void Model::updateElements(std::vector<IdStringList> elements)
|
||||
{
|
||||
if (!ctx_)
|
||||
return;
|
||||
|
@ -95,16 +95,16 @@ class Item
|
||||
int indexOf(Item *child) { return children_.indexOf(child, 0); }
|
||||
|
||||
// Arch id and type that correspond to this element.
|
||||
virtual IdString id() const { return IdString(); }
|
||||
virtual IdStringList id() const { return IdStringList(); }
|
||||
virtual ElementType type() const { return ElementType::NONE; }
|
||||
|
||||
// Lazy loading methods.
|
||||
virtual bool canFetchMore() const { return false; }
|
||||
virtual void fetchMore() {}
|
||||
|
||||
virtual boost::optional<Item *> getById(IdString id) { return boost::none; }
|
||||
virtual boost::optional<Item *> getById(IdStringList id) { return boost::none; }
|
||||
virtual void search(QList<Item *> &results, QString text, int limit) {}
|
||||
virtual void updateElements(Context *ctx, std::vector<IdString> elements) {}
|
||||
virtual void updateElements(Context *ctx, std::vector<IdStringList> elements) {}
|
||||
|
||||
virtual ~Item()
|
||||
{
|
||||
@ -118,46 +118,46 @@ class Item
|
||||
class IdStringItem : public Item
|
||||
{
|
||||
private:
|
||||
IdString id_;
|
||||
IdStringList id_;
|
||||
ElementType type_;
|
||||
|
||||
public:
|
||||
IdStringItem(Context *ctx, IdString str, Item *parent, ElementType type)
|
||||
: Item(QString(str.c_str(ctx)), parent), id_(str), type_(type)
|
||||
IdStringItem(Context *ctx, IdStringList str, Item *parent, ElementType type)
|
||||
: Item(QString(str.str(ctx).c_str()), parent), id_(str), type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
virtual IdString id() const override { return id_; }
|
||||
virtual IdStringList id() const override { return id_; }
|
||||
|
||||
virtual ElementType type() const override { return type_; }
|
||||
};
|
||||
|
||||
// IdString list is a static list of IdStrings which can be set/updates from
|
||||
// IdList is a static list of IdStringLists which can be set/updates from
|
||||
// a vector of IdStrings. It will render each IdStrings as a child, with the
|
||||
// list sorted in a smart way.
|
||||
class IdStringList : public Item
|
||||
class IdList : public Item
|
||||
{
|
||||
private:
|
||||
// Children that we manage the memory for, stored for quick lookup from
|
||||
// IdString to child.
|
||||
std::unordered_map<IdString, std::unique_ptr<IdStringItem>> managed_;
|
||||
std::unordered_map<IdStringList, std::unique_ptr<IdStringItem>> managed_;
|
||||
// Type of children that the list creates.
|
||||
ElementType child_type_;
|
||||
|
||||
public:
|
||||
// Create an IdStringList at given parent that will contain elements of
|
||||
// Create an IdList at given parent that will contain elements of
|
||||
// the given type.
|
||||
IdStringList(ElementType type) : Item("root", nullptr), child_type_(type) {}
|
||||
IdList(ElementType type) : Item("root", nullptr), child_type_(type) {}
|
||||
|
||||
// Split a name into alpha/non-alpha parts, which is then used for sorting
|
||||
// of children.
|
||||
static std::vector<QString> alphaNumSplit(const QString &str);
|
||||
|
||||
// getById finds a child for the given IdString.
|
||||
virtual boost::optional<Item *> getById(IdString id) override { return managed_.at(id).get(); }
|
||||
virtual boost::optional<Item *> getById(IdStringList id) override { return managed_.at(id).get(); }
|
||||
|
||||
// (Re-)create children from a list of IdStrings.
|
||||
virtual void updateElements(Context *ctx, std::vector<IdString> elements) override;
|
||||
virtual void updateElements(Context *ctx, std::vector<IdStringList> elements) override;
|
||||
|
||||
// Find children that contain the given text.
|
||||
virtual void search(QList<Item *> &results, QString text, int limit) override;
|
||||
@ -173,7 +173,7 @@ template <typename ElementT> class ElementList : public Item
|
||||
// A map from tile (X,Y) to list of ElementTs in that tile.
|
||||
using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>;
|
||||
// A method that converts an ElementT to an IdString.
|
||||
using ElementGetter = std::function<IdString(Context *, ElementT)>;
|
||||
using ElementGetter = std::function<IdStringList(Context *, ElementT)>;
|
||||
|
||||
private:
|
||||
Context *ctx_;
|
||||
@ -184,7 +184,7 @@ template <typename ElementT> class ElementList : public Item
|
||||
ElementGetter getter_;
|
||||
// Children that we manage the memory for, stored for quick lookup from
|
||||
// IdString to child.
|
||||
std::unordered_map<IdString, std::unique_ptr<Item>> managed_;
|
||||
std::unordered_map<IdStringList, std::unique_ptr<Item>> managed_;
|
||||
// Type of children that he list creates.
|
||||
ElementType child_type_;
|
||||
|
||||
@ -209,9 +209,10 @@ template <typename ElementT> class ElementList : public Item
|
||||
size_t end = std::min(start + count, elements()->size());
|
||||
for (size_t i = start; i < end; i++) {
|
||||
auto idstring = getter_(ctx_, elements()->at(i));
|
||||
QString name(idstring.c_str(ctx_));
|
||||
std::string name_str = idstring.str(ctx_);
|
||||
QString name(name_str.c_str());
|
||||
|
||||
// Remove X.../Y.../ prefix
|
||||
// Remove X.../Y.../ prefix - TODO: find a way to use IdStringList splitting here
|
||||
QString prefix = QString("X%1/Y%2/").arg(x_).arg(y_);
|
||||
if (name.startsWith(prefix))
|
||||
name.remove(0, prefix.size());
|
||||
@ -224,7 +225,7 @@ template <typename ElementT> class ElementList : public Item
|
||||
virtual void fetchMore() override { fetchMore(100); }
|
||||
|
||||
// getById finds a child for the given IdString.
|
||||
virtual boost::optional<Item *> getById(IdString id) override
|
||||
virtual boost::optional<Item *> getById(IdStringList id) override
|
||||
{
|
||||
// Search requires us to load all our elements...
|
||||
while (canFetchMore())
|
||||
@ -267,7 +268,7 @@ template <typename ElementT> class ElementXYRoot : public Item
|
||||
// A map from tile (X,Y) to list of ElementTs in that tile.
|
||||
using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>;
|
||||
// A method that converts an ElementT to an IdString.
|
||||
using ElementGetter = std::function<IdString(Context *, ElementT)>;
|
||||
using ElementGetter = std::function<IdStringList(Context *, ElementT)>;
|
||||
|
||||
private:
|
||||
Context *ctx_;
|
||||
@ -319,7 +320,7 @@ template <typename ElementT> class ElementXYRoot : public Item
|
||||
}
|
||||
|
||||
// getById finds a child for the given IdString.
|
||||
virtual boost::optional<Item *> getById(IdString id) override
|
||||
virtual boost::optional<Item *> getById(IdStringList id) override
|
||||
{
|
||||
// For now, scan linearly all ElementLists.
|
||||
// TODO(q3k) fix this once we have tree API from arch
|
||||
@ -353,7 +354,7 @@ class Model : public QAbstractItemModel
|
||||
~Model();
|
||||
|
||||
void loadData(Context *ctx, std::unique_ptr<Item> data);
|
||||
void updateElements(std::vector<IdString> elements);
|
||||
void updateElements(std::vector<IdStringList> elements);
|
||||
Item *nodeFromIndex(const QModelIndex &idx) const;
|
||||
QModelIndex indexFromNode(Item *node)
|
||||
{
|
||||
@ -366,7 +367,7 @@ class Model : public QAbstractItemModel
|
||||
|
||||
QList<QModelIndex> search(QString text);
|
||||
|
||||
boost::optional<Item *> nodeForId(IdString id) const { return root_->getById(id); }
|
||||
boost::optional<Item *> nodeForId(IdStringList id) const { return root_->getById(id); }
|
||||
|
||||
// Override QAbstractItemModel methods
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
|
@ -110,6 +110,17 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
if (package_info == nullptr)
|
||||
log_error("Unsupported package '%s'.\n", args.package.c_str());
|
||||
|
||||
for (int i = 0; i < chip_info->width; i++) {
|
||||
IdString x_id = id(stringf("X%d", i));
|
||||
x_ids.push_back(x_id);
|
||||
id_to_x[x_id] = i;
|
||||
}
|
||||
for (int i = 0; i < chip_info->height; i++) {
|
||||
IdString y_id = id(stringf("Y%d", i));
|
||||
y_ids.push_back(y_id);
|
||||
id_to_y[y_id] = i;
|
||||
}
|
||||
|
||||
bel_carry.resize(chip_info->bel_data.size());
|
||||
bel_to_cell.resize(chip_info->bel_data.size());
|
||||
wire_to_net.resize(chip_info->wire_data.size());
|
||||
@ -196,13 +207,16 @@ IdString Arch::archArgsToId(ArchArgs args) const
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
BelId Arch::getBelByName(IdString name) const
|
||||
BelId Arch::getBelByName(IdStringList name) const
|
||||
{
|
||||
BelId ret;
|
||||
|
||||
if (bel_by_name.empty()) {
|
||||
for (size_t i = 0; i < chip_info->bel_data.size(); i++)
|
||||
bel_by_name[id(chip_info->bel_data[i].name.get())] = i;
|
||||
for (size_t i = 0; i < chip_info->bel_data.size(); i++) {
|
||||
BelId b;
|
||||
b.index = i;
|
||||
bel_by_name[getBelName(b)] = i;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = bel_by_name.find(name);
|
||||
@ -357,13 +371,16 @@ bool Arch::isBelLocked(BelId bel) const
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
WireId Arch::getWireByName(IdString name) const
|
||||
WireId Arch::getWireByName(IdStringList name) const
|
||||
{
|
||||
WireId ret;
|
||||
|
||||
if (wire_by_name.empty()) {
|
||||
for (int i = 0; i < int(chip_info->wire_data.size()); i++)
|
||||
wire_by_name[id(chip_info->wire_data[i].name.get())] = i;
|
||||
for (int i = 0; i < int(chip_info->wire_data.size()); i++) {
|
||||
WireId w;
|
||||
w.index = i;
|
||||
wire_by_name[getWireName(w)] = i;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = wire_by_name.find(name);
|
||||
@ -427,7 +444,7 @@ std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) co
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
PipId Arch::getPipByName(IdString name) const
|
||||
PipId Arch::getPipByName(IdStringList name) const
|
||||
{
|
||||
PipId ret;
|
||||
|
||||
@ -446,24 +463,21 @@ PipId Arch::getPipByName(IdString name) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
IdString Arch::getPipName(PipId pip) const
|
||||
IdStringList Arch::getPipName(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
|
||||
#if 1
|
||||
int x = chip_info->pip_data[pip.index].x;
|
||||
int y = chip_info->pip_data[pip.index].y;
|
||||
|
||||
std::string src_name = chip_info->wire_data[chip_info->pip_data[pip.index].src].name.get();
|
||||
std::replace(src_name.begin(), src_name.end(), '/', '.');
|
||||
auto &src_wire = chip_info->wire_data[chip_info->pip_data[pip.index].src];
|
||||
auto &dst_wire = chip_info->wire_data[chip_info->pip_data[pip.index].dst];
|
||||
|
||||
std::string dst_name = chip_info->wire_data[chip_info->pip_data[pip.index].dst].name.get();
|
||||
std::replace(dst_name.begin(), dst_name.end(), '/', '.');
|
||||
std::string src_name = stringf("%d.%d.%s", int(src_wire.name_x), int(src_wire.name_y), src_wire.name.get());
|
||||
std::string dst_name = stringf("%d.%d.%s", int(dst_wire.name_x), int(dst_wire.name_y), dst_wire.name.get());
|
||||
|
||||
return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name);
|
||||
#else
|
||||
return id(chip_info->pip_data[pip.index].name.get());
|
||||
#endif
|
||||
std::array<IdString, 3> ids{x_ids.at(x), y_ids.at(y), id(src_name + ".->." + dst_name)};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
IdString Arch::getPipType(PipId pip) const { return IdString(); }
|
||||
@ -503,7 +517,7 @@ std::string Arch::getBelPackagePin(BelId bel) const
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
GroupId Arch::getGroupByName(IdString name) const
|
||||
GroupId Arch::getGroupByName(IdStringList name) const
|
||||
{
|
||||
for (auto g : getGroups())
|
||||
if (getGroupName(g) == name)
|
||||
@ -511,7 +525,7 @@ GroupId Arch::getGroupByName(IdString name) const
|
||||
return GroupId();
|
||||
}
|
||||
|
||||
IdString Arch::getGroupName(GroupId group) const
|
||||
IdStringList Arch::getGroupName(GroupId group) const
|
||||
{
|
||||
std::string suffix;
|
||||
|
||||
@ -553,7 +567,8 @@ IdString Arch::getGroupName(GroupId group) const
|
||||
return IdString();
|
||||
}
|
||||
|
||||
return id("X" + std::to_string(group.x) + "/Y" + std::to_string(group.y) + "/" + suffix);
|
||||
std::array<IdString, 3> ids{x_ids.at(group.x), y_ids.at(group.y), id(suffix)};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
std::vector<GroupId> Arch::getGroups() const
|
||||
|
40
ice40/arch.h
40
ice40/arch.h
@ -91,6 +91,8 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD {
|
||||
};
|
||||
|
||||
RelPtr<char> name;
|
||||
int8_t name_x, name_y;
|
||||
int16_t padding;
|
||||
RelSlice<int32_t> pips_uphill, pips_downhill;
|
||||
|
||||
RelSlice<BelPortPOD> bel_pins;
|
||||
@ -378,9 +380,9 @@ struct Arch : BaseCtx
|
||||
const ChipInfoPOD *chip_info;
|
||||
const PackageInfoPOD *package_info;
|
||||
|
||||
mutable std::unordered_map<IdString, int> bel_by_name;
|
||||
mutable std::unordered_map<IdString, int> wire_by_name;
|
||||
mutable std::unordered_map<IdString, int> pip_by_name;
|
||||
mutable std::unordered_map<IdStringList, int> bel_by_name;
|
||||
mutable std::unordered_map<IdStringList, int> wire_by_name;
|
||||
mutable std::unordered_map<IdStringList, int> pip_by_name;
|
||||
mutable std::unordered_map<Loc, int> bel_by_loc;
|
||||
|
||||
std::vector<bool> bel_carry;
|
||||
@ -389,6 +391,11 @@ struct Arch : BaseCtx
|
||||
std::vector<NetInfo *> pip_to_net;
|
||||
std::vector<WireId> switches_locked;
|
||||
|
||||
// fast access to X and Y IdStrings for building object names
|
||||
std::vector<IdString> x_ids, y_ids;
|
||||
// inverse of the above for name->object mapping
|
||||
std::unordered_map<IdString, int> id_to_x, id_to_y;
|
||||
|
||||
ArchArgs args;
|
||||
Arch(ArchArgs args);
|
||||
|
||||
@ -407,15 +414,18 @@ struct Arch : BaseCtx
|
||||
int getGridDimY() const { return chip_info->height; }
|
||||
int getTileBelDimZ(int, int) const { return 8; }
|
||||
int getTilePipDimZ(int, int) const { return 1; }
|
||||
char getNameDelimiter() const { return '/'; }
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
BelId getBelByName(IdString name) const;
|
||||
BelId getBelByName(IdStringList name) const;
|
||||
|
||||
IdString getBelName(BelId bel) const
|
||||
IdStringList getBelName(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return id(chip_info->bel_data[bel.index].name.get());
|
||||
auto &data = chip_info->bel_data[bel.index];
|
||||
std::array<IdString, 3> ids{x_ids.at(data.x), y_ids.at(data.y), id(data.name.get())};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
|
||||
@ -500,12 +510,14 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
WireId getWireByName(IdString name) const;
|
||||
WireId getWireByName(IdStringList name) const;
|
||||
|
||||
IdString getWireName(WireId wire) const
|
||||
IdStringList getWireName(WireId wire) const
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
return id(chip_info->wire_data[wire.index].name.get());
|
||||
auto &data = chip_info->wire_data[wire.index];
|
||||
std::array<IdString, 3> ids{x_ids.at(data.name_x), y_ids.at(data.name_y), id(data.name.get())};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
IdString getWireType(WireId wire) const;
|
||||
@ -593,7 +605,7 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
PipId getPipByName(IdString name) const;
|
||||
PipId getPipByName(IdStringList name) const;
|
||||
|
||||
void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
|
||||
{
|
||||
@ -703,7 +715,7 @@ struct Arch : BaseCtx
|
||||
return loc;
|
||||
}
|
||||
|
||||
IdString getPipName(PipId pip) const;
|
||||
IdStringList getPipName(PipId pip) const;
|
||||
|
||||
IdString getPipType(PipId pip) const;
|
||||
std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const;
|
||||
@ -760,8 +772,8 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
GroupId getGroupByName(IdString name) const;
|
||||
IdString getGroupName(GroupId group) const;
|
||||
GroupId getGroupByName(IdStringList name) const;
|
||||
IdStringList getGroupName(GroupId group) const;
|
||||
std::vector<GroupId> getGroups() const;
|
||||
std::vector<BelId> getGroupBels(GroupId group) const;
|
||||
std::vector<WireId> getGroupWires(GroupId group) const;
|
||||
@ -895,7 +907,7 @@ struct Arch : BaseCtx
|
||||
int getDrivenGlobalNetwork(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(getBelType(bel) == id_SB_GB);
|
||||
IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT));
|
||||
IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT))[2];
|
||||
return std::stoi(std::string("") + glb_net.str(this).back());
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
|
||||
break;
|
||||
|
||||
// Are we perhaps a PAD INPUT Bel that can be placed here?
|
||||
if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this))
|
||||
if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(getCtx()))
|
||||
return true;
|
||||
|
||||
// Conflict
|
||||
|
@ -778,7 +778,7 @@ def add_bel_output(bel, wire, port):
|
||||
|
||||
def add_bel_lc(x, y, z):
|
||||
bel = len(bel_name)
|
||||
bel_name.append("X%d/Y%d/lc%d" % (x, y, z))
|
||||
bel_name.append((x, y, "lc%d" % z))
|
||||
bel_type.append("ICESTORM_LC")
|
||||
bel_pos.append((x, y, z))
|
||||
bel_wires.append(list())
|
||||
@ -837,7 +837,7 @@ def add_bel_lc(x, y, z):
|
||||
|
||||
def add_bel_io(x, y, z):
|
||||
bel = len(bel_name)
|
||||
bel_name.append("X%d/Y%d/io%d" % (x, y, z))
|
||||
bel_name.append((x, y, "io%d" % z))
|
||||
bel_type.append("SB_IO")
|
||||
bel_pos.append((x, y, z))
|
||||
bel_wires.append(list())
|
||||
@ -871,7 +871,7 @@ def add_bel_io(x, y, z):
|
||||
|
||||
def add_bel_ram(x, y):
|
||||
bel = len(bel_name)
|
||||
bel_name.append("X%d/Y%d/ram" % (x, y))
|
||||
bel_name.append((x, y, "ram"))
|
||||
bel_type.append("ICESTORM_RAM")
|
||||
bel_pos.append((x, y, 0))
|
||||
bel_wires.append(list())
|
||||
@ -905,7 +905,7 @@ def add_bel_gb(xy, x, y, g):
|
||||
return
|
||||
|
||||
bel = len(bel_name)
|
||||
bel_name.append("X%d/Y%d/gb" % (x, y))
|
||||
bel_name.append((x, y, "gb"))
|
||||
bel_type.append("SB_GB")
|
||||
bel_pos.append((x, y, 2))
|
||||
bel_wires.append(list())
|
||||
@ -942,7 +942,7 @@ def add_bel_ec(ec):
|
||||
ectype, x, y, z = ec
|
||||
bel = len(bel_name)
|
||||
extra_cell_config[bel] = []
|
||||
bel_name.append("X%d/Y%d/%s_%d" % (x, y, ectype.lower(), z))
|
||||
bel_name.append((x, y, "%s_%d" % (ectype.lower(), z)))
|
||||
bel_type.append(ectype)
|
||||
bel_pos.append((x, y, z))
|
||||
bel_wires.append(list())
|
||||
@ -1140,7 +1140,7 @@ for bel in range(len(bel_name)):
|
||||
|
||||
bba.l("bel_data_%s" % dev_name, "BelInfoPOD")
|
||||
for bel in range(len(bel_name)):
|
||||
bba.s(bel_name[bel], "name")
|
||||
bba.s(bel_name[bel][-1], "name")
|
||||
bba.u32(constids[bel_type[bel]], "type")
|
||||
bba.r_slice("bel_wires_%d" % bel, len(bel_wires[bel]), "bel_wires")
|
||||
bba.u8(bel_pos[bel][0], "x")
|
||||
@ -1215,7 +1215,9 @@ for wire in range(num_wires):
|
||||
num_bel_pins = 0
|
||||
|
||||
info = dict()
|
||||
info["name"] = "X%d/Y%d/%s" % wire_names_r[wire]
|
||||
info["name"] = wire_names_r[wire][2]
|
||||
info["name_x"] = wire_names_r[wire][0]
|
||||
info["name_y"] = wire_names_r[wire][1]
|
||||
|
||||
info["num_uphill"] = num_uphill
|
||||
info["list_uphill"] = list_uphill
|
||||
@ -1263,7 +1265,7 @@ for package in packages:
|
||||
pins_info = []
|
||||
for pin in pins:
|
||||
pinname, x, y, z = pin
|
||||
pin_bel = "X%d/Y%d/io%d" % (x, y, z)
|
||||
pin_bel = (x, y, "io%d" % z)
|
||||
bel_idx = bel_name.index(pin_bel)
|
||||
pins_info.append((pinname, bel_idx))
|
||||
bba.l("package_%s_pins" % safename, "PackagePinPOD")
|
||||
@ -1311,6 +1313,9 @@ for t in range(num_tile_types):
|
||||
bba.l("wire_data_%s" % dev_name, "WireInfoPOD")
|
||||
for wire, info in enumerate(wireinfo):
|
||||
bba.s(info["name"], "name")
|
||||
bba.u8(info["name_x"], "name_x")
|
||||
bba.u8(info["name_y"], "name_y")
|
||||
bba.u16(0, "padding")
|
||||
bba.r_slice(info["list_uphill"], info["num_uphill"], "pips_uphill")
|
||||
bba.r_slice(info["list_downhill"], info["num_downhill"], "pips_downhill")
|
||||
bba.r_slice(info["list_bel_pins"], info["num_bel_pins"], "bel_pins")
|
||||
|
@ -80,7 +80,7 @@ void ice40DelayFuzzerMain(Context *ctx)
|
||||
|
||||
printf("%s %d %d %s %s %d %d\n", cursor == dst ? "dst" : "src",
|
||||
int(ctx->chip_info->wire_data[cursor.index].x), int(ctx->chip_info->wire_data[cursor.index].y),
|
||||
ctx->getWireType(cursor).c_str(ctx), ctx->getWireName(cursor).c_str(ctx), int(delay),
|
||||
ctx->getWireType(cursor).c_str(ctx), ctx->nameOfWire(cursor), int(delay),
|
||||
int(ctx->estimateDelay(cursor, dst)));
|
||||
|
||||
if (cursor == src)
|
||||
|
@ -417,7 +417,7 @@ static BelId find_padin_gbuf(Context *ctx, BelId bel, IdString port_name)
|
||||
auto wire = ctx->getBelPinWire(bel, port_name);
|
||||
|
||||
if (wire == WireId())
|
||||
log_error("BEL '%s' has no global buffer connection available\n", ctx->getBelName(bel).c_str(ctx));
|
||||
log_error("BEL '%s' has no global buffer connection available\n", ctx->nameOfBel(bel));
|
||||
|
||||
for (auto src_bel : ctx->getWireBelPins(wire)) {
|
||||
if (ctx->getBelType(src_bel.bel) == id_SB_GB && src_bel.pin == id_GLOBAL_BUFFER_OUTPUT) {
|
||||
@ -435,7 +435,7 @@ static std::unique_ptr<CellInfo> create_padin_gbuf(Context *ctx, CellInfo *cell,
|
||||
// Find the matching SB_GB BEL connected to the same global network
|
||||
if (!cell->attrs.count(ctx->id("BEL")))
|
||||
log_error("Unconstrained SB_GB_IO %s is not supported.\n", ctx->nameOf(cell));
|
||||
BelId bel = ctx->getBelByName(ctx->id(cell->attrs[ctx->id("BEL")].as_string()));
|
||||
BelId bel = ctx->getBelByNameStr(cell->attrs[ctx->id("BEL")].as_string());
|
||||
BelId gb_bel = find_padin_gbuf(ctx, bel, port_name);
|
||||
NPNR_ASSERT(gb_bel != BelId());
|
||||
|
||||
@ -666,7 +666,7 @@ static void promote_globals(Context *ctx)
|
||||
/* And possibly limits what we can promote */
|
||||
if (cell.second->attrs.find(ctx->id("BEL")) != cell.second->attrs.end()) {
|
||||
/* If the SB_GB is locked, doesn't matter what it drives */
|
||||
BelId bel = ctx->getBelByName(ctx->id(cell.second->attrs[ctx->id("BEL")].as_string()));
|
||||
BelId bel = ctx->getBelByNameStr(cell.second->attrs[ctx->id("BEL")].as_string());
|
||||
int glb_id = ctx->getDrivenGlobalNetwork(bel);
|
||||
if ((glb_id % 2) == 0)
|
||||
resets_available--;
|
||||
@ -785,7 +785,7 @@ static void place_plls(Context *ctx)
|
||||
|
||||
// If it's constrained already, add to already used list
|
||||
if (ci->attrs.count(ctx->id("BEL"))) {
|
||||
BelId bel_constrain = ctx->getBelByName(ctx->id(ci->attrs[ctx->id("BEL")].as_string()));
|
||||
BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[ctx->id("BEL")].as_string());
|
||||
if (pll_all_bels.count(bel_constrain) == 0)
|
||||
log_error("PLL '%s' is constrained to invalid BEL '%s'\n", ci->name.c_str(ctx),
|
||||
ci->attrs[ctx->id("BEL")].as_string().c_str());
|
||||
@ -820,7 +820,7 @@ static void place_plls(Context *ctx)
|
||||
log_error("PLL '%s' PACKAGEPIN SB_IO '%s' is unconstrained\n", ci->name.c_str(ctx),
|
||||
io_cell->name.c_str(ctx));
|
||||
|
||||
BelId io_bel = ctx->getBelByName(ctx->id(io_cell->attrs.at(ctx->id("BEL")).as_string()));
|
||||
BelId io_bel = ctx->getBelByNameStr(io_cell->attrs.at(ctx->id("BEL")).as_string());
|
||||
BelId found_bel;
|
||||
|
||||
// Find the PLL BEL that would suit that connection
|
||||
@ -839,18 +839,17 @@ static void place_plls(Context *ctx)
|
||||
if (conflict_cell == ci)
|
||||
continue;
|
||||
log_error("PLL '%s' PACKAGEPIN forces it to BEL %s but BEL is already assigned to PLL '%s'\n",
|
||||
ci->name.c_str(ctx), ctx->getBelName(found_bel).c_str(ctx), conflict_cell->name.c_str(ctx));
|
||||
ci->name.c_str(ctx), ctx->nameOfBel(found_bel), conflict_cell->name.c_str(ctx));
|
||||
}
|
||||
|
||||
// Is it user constrained ?
|
||||
if (ci->attrs.count(ctx->id("BEL"))) {
|
||||
// Yes. Check it actually matches !
|
||||
BelId bel_constrain = ctx->getBelByName(ctx->id(ci->attrs[ctx->id("BEL")].as_string()));
|
||||
BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[ctx->id("BEL")].as_string());
|
||||
if (bel_constrain != found_bel)
|
||||
log_error("PLL '%s' is user constrained to %s but can only be placed in %s based on its PACKAGEPIN "
|
||||
"connection\n",
|
||||
ci->name.c_str(ctx), ctx->getBelName(bel_constrain).c_str(ctx),
|
||||
ctx->getBelName(found_bel).c_str(ctx));
|
||||
ci->name.c_str(ctx), ctx->nameOfBel(bel_constrain), ctx->nameOfBel(found_bel));
|
||||
} else {
|
||||
// No, we can constrain it ourselves
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(found_bel).str(ctx);
|
||||
@ -858,7 +857,7 @@ static void place_plls(Context *ctx)
|
||||
}
|
||||
|
||||
// Inform user
|
||||
log_info(" constrained PLL '%s' to %s\n", ci->name.c_str(ctx), ctx->getBelName(found_bel).c_str(ctx));
|
||||
log_info(" constrained PLL '%s' to %s\n", ci->name.c_str(ctx), ctx->nameOfBel(found_bel));
|
||||
}
|
||||
|
||||
// Scan all SB_IOs to check for conflict with PLL BELs
|
||||
@ -876,7 +875,7 @@ static void place_plls(Context *ctx)
|
||||
continue;
|
||||
|
||||
// Check all placed PLL (either forced by user, or forced by PACKAGEPIN)
|
||||
BelId io_bel = ctx->getBelByName(ctx->id(io_ci->attrs[ctx->id("BEL")].as_string()));
|
||||
BelId io_bel = ctx->getBelByNameStr(io_ci->attrs[ctx->id("BEL")].as_string());
|
||||
|
||||
for (auto placed_pll : pll_used_bels) {
|
||||
BelPin pll_io_a, pll_io_b;
|
||||
@ -910,7 +909,7 @@ static void place_plls(Context *ctx)
|
||||
continue;
|
||||
|
||||
// Check all placed PLL (either forced by user, or forced by PACKAGEPIN)
|
||||
BelId gb_bel = ctx->getBelByName(ctx->id(gb_ci->attrs[ctx->id("BEL")].as_string()));
|
||||
BelId gb_bel = ctx->getBelByNameStr(gb_ci->attrs[ctx->id("BEL")].as_string());
|
||||
|
||||
for (auto placed_pll : pll_used_bels) {
|
||||
CellInfo *ci = placed_pll.second;
|
||||
@ -969,7 +968,7 @@ static void place_plls(Context *ctx)
|
||||
bool could_be_pad = false;
|
||||
BelId pad_bel;
|
||||
if (ni->users.size() == 1 && is_sb_io(ctx, ni->driver.cell) && ni->driver.cell->attrs.count(ctx->id("BEL")))
|
||||
pad_bel = ctx->getBelByName(ctx->id(ni->driver.cell->attrs[ctx->id("BEL")].as_string()));
|
||||
pad_bel = ctx->getBelByNameStr(ni->driver.cell->attrs[ctx->id("BEL")].as_string());
|
||||
|
||||
// Find a BEL for it
|
||||
BelId found_bel;
|
||||
@ -999,7 +998,7 @@ static void place_plls(Context *ctx)
|
||||
log_error("PLL '%s' couldn't be placed anywhere, no suitable BEL found.%s\n", ci->name.c_str(ctx),
|
||||
could_be_pad ? " Did you mean to use a PAD PLL ?" : "");
|
||||
|
||||
log_info(" constrained PLL '%s' to %s\n", ci->name.c_str(ctx), ctx->getBelName(found_bel).c_str(ctx));
|
||||
log_info(" constrained PLL '%s' to %s\n", ci->name.c_str(ctx), ctx->nameOfBel(found_bel));
|
||||
if (could_be_pad)
|
||||
log_info(" (given its connections, this PLL could have been a PAD PLL)\n");
|
||||
|
||||
@ -1067,9 +1066,9 @@ static BelId cell_place_unique(Context *ctx, CellInfo *ci)
|
||||
continue;
|
||||
if (ctx->isBelLocked(bel))
|
||||
continue;
|
||||
IdString bel_name = ctx->getBelName(bel);
|
||||
IdStringList bel_name = ctx->getBelName(bel);
|
||||
ci->attrs[ctx->id("BEL")] = bel_name.str(ctx);
|
||||
log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), bel_name.c_str(ctx));
|
||||
log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), ctx->nameOfBel(bel));
|
||||
return bel;
|
||||
}
|
||||
log_error("Unable to place cell '%s' of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
|
||||
@ -1279,9 +1278,9 @@ static void pack_special(Context *ctx)
|
||||
if (bel == BelId() || ctx->getBelType(bel) != ci->type)
|
||||
log_error("Unable to find placement for cell '%s' of type '%s'\n", ci->name.c_str(ctx),
|
||||
ci->type.c_str(ctx));
|
||||
IdString bel_name = ctx->getBelName(bel);
|
||||
IdStringList bel_name = ctx->getBelName(bel);
|
||||
ci->attrs[ctx->id("BEL")] = bel_name.str(ctx);
|
||||
log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), bel_name.c_str(ctx));
|
||||
log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), ctx->nameOfBel(bel));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1498,7 +1497,7 @@ void pack_plls(Context *ctx)
|
||||
}
|
||||
constr_fail:
|
||||
// PLL must have been placed already in place_plls()
|
||||
BelId pll_bel = ctx->getBelByName(ctx->id(packed->attrs[ctx->id("BEL")].as_string()));
|
||||
BelId pll_bel = ctx->getBelByNameStr(packed->attrs[ctx->id("BEL")].as_string());
|
||||
NPNR_ASSERT(pll_bel != BelId());
|
||||
|
||||
// Deal with PAD PLL peculiarities
|
||||
|
@ -32,20 +32,6 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
namespace {
|
||||
static std::tuple<int, int, std::string> split_identifier_name(const std::string &name)
|
||||
{
|
||||
size_t first_slash = name.find('/');
|
||||
NPNR_ASSERT(first_slash != std::string::npos);
|
||||
size_t second_slash = name.find('/', first_slash + 1);
|
||||
NPNR_ASSERT(second_slash != std::string::npos);
|
||||
return std::make_tuple(std::stoi(name.substr(1, first_slash)),
|
||||
std::stoi(name.substr(first_slash + 2, second_slash - first_slash)),
|
||||
name.substr(second_slash + 1));
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void IdString::initialize_arch(const BaseCtx *ctx)
|
||||
@ -134,6 +120,17 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
ts.bels_by_z[bel.z].index = j;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < chip_info->width; i++) {
|
||||
IdString x_id = id(stringf("X%d", i));
|
||||
x_ids.push_back(x_id);
|
||||
id_to_x[x_id] = i;
|
||||
}
|
||||
for (int i = 0; i < chip_info->height; i++) {
|
||||
IdString y_id = id(stringf("Y%d", i));
|
||||
y_ids.push_back(y_id);
|
||||
id_to_y[y_id] = i;
|
||||
}
|
||||
init_cell_pin_data();
|
||||
// Validate and set up package
|
||||
package_idx = -1;
|
||||
@ -193,17 +190,17 @@ IdString Arch::archArgsToId(ArchArgs args) const { return id(args.device); }
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
BelId Arch::getBelByName(IdString name) const
|
||||
BelId Arch::getBelByName(IdStringList name) const
|
||||
{
|
||||
int x, y;
|
||||
std::string belname;
|
||||
std::tie(x, y, belname) = split_identifier_name(name.str(this));
|
||||
if (name.size() != 3)
|
||||
return BelId();
|
||||
int x = id_to_x.at(name[0]);
|
||||
int y = id_to_y.at(name[1]);
|
||||
NPNR_ASSERT(x >= 0 && x < chip_info->width);
|
||||
NPNR_ASSERT(y >= 0 && y < chip_info->height);
|
||||
auto &tile = db->loctypes[chip_info->grid[y * chip_info->width + x].loc_type];
|
||||
IdString bn = id(belname);
|
||||
for (size_t i = 0; i < tile.bels.size(); i++) {
|
||||
if (tile.bels[i].name == bn.index) {
|
||||
if (tile.bels[i].name == name[2].index) {
|
||||
BelId ret;
|
||||
ret.tile = y * chip_info->width + x;
|
||||
ret.index = i;
|
||||
@ -305,17 +302,17 @@ std::vector<std::pair<IdString, std::string>> Arch::getBelAttrs(BelId bel) const
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
WireId Arch::getWireByName(IdString name) const
|
||||
WireId Arch::getWireByName(IdStringList name) const
|
||||
{
|
||||
int x, y;
|
||||
std::string wirename;
|
||||
std::tie(x, y, wirename) = split_identifier_name(name.str(this));
|
||||
if (name.size() != 3)
|
||||
return WireId();
|
||||
int x = id_to_x.at(name[0]);
|
||||
int y = id_to_y.at(name[1]);
|
||||
NPNR_ASSERT(x >= 0 && x < chip_info->width);
|
||||
NPNR_ASSERT(y >= 0 && y < chip_info->height);
|
||||
auto &tile = db->loctypes[chip_info->grid[y * chip_info->width + x].loc_type];
|
||||
IdString wn = id(wirename);
|
||||
for (size_t i = 0; i < tile.wires.size(); i++) {
|
||||
if (tile.wires[i].name == wn.index) {
|
||||
if (tile.wires[i].name == name[2].index) {
|
||||
WireId ret;
|
||||
ret.tile = y * chip_info->width + x;
|
||||
ret.index = i;
|
||||
@ -342,26 +339,27 @@ std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) co
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
PipId Arch::getPipByName(IdString name) const
|
||||
PipId Arch::getPipByName(IdStringList name) const
|
||||
{
|
||||
int x, y;
|
||||
std::string pipname;
|
||||
std::tie(x, y, pipname) = split_identifier_name(name.str(this));
|
||||
if (name.size() != 5)
|
||||
return PipId();
|
||||
int x = id_to_x.at(name[0]);
|
||||
int y = id_to_y.at(name[1]);
|
||||
NPNR_ASSERT(x >= 0 && x < chip_info->width);
|
||||
NPNR_ASSERT(y >= 0 && y < chip_info->height);
|
||||
PipId ret;
|
||||
ret.tile = y * chip_info->width + x;
|
||||
auto sep_pos = pipname.find(':');
|
||||
ret.index = std::stoi(pipname.substr(0, sep_pos));
|
||||
ret.index = std::stoi(name[2].str(this));
|
||||
return ret;
|
||||
}
|
||||
|
||||
IdString Arch::getPipName(PipId pip) const
|
||||
IdStringList Arch::getPipName(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
return id(stringf("X%d/Y%d/%d:%s->%s", pip.tile % chip_info->width, pip.tile / chip_info->width, pip.index,
|
||||
nameOf(loc_data(pip).wires[pip_data(pip).from_wire].name),
|
||||
nameOf(loc_data(pip).wires[pip_data(pip).to_wire].name)));
|
||||
std::array<IdString, 5> ids{x_ids.at(pip.tile % chip_info->width), y_ids.at(pip.tile / chip_info->width),
|
||||
id(stringf("%d", pip.index)), IdString(loc_data(pip).wires[pip_data(pip).to_wire].name),
|
||||
IdString(loc_data(pip).wires[pip_data(pip).from_wire].name)};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
IdString Arch::getPipType(PipId pip) const { return IdString(); }
|
||||
|
44
nexus/arch.h
44
nexus/arch.h
@ -897,6 +897,11 @@ struct Arch : BaseCtx
|
||||
std::unordered_map<WireId, NetInfo *> wire_to_net;
|
||||
std::unordered_map<PipId, NetInfo *> pip_to_net;
|
||||
|
||||
// fast access to X and Y IdStrings for building object names
|
||||
std::vector<IdString> x_ids, y_ids;
|
||||
// inverse of the above for name->object mapping
|
||||
std::unordered_map<IdString, int> id_to_x, id_to_y;
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
std::string getChipName() const;
|
||||
@ -909,20 +914,18 @@ struct Arch : BaseCtx
|
||||
int getGridDimY() const { return chip_info->height; }
|
||||
int getTileBelDimZ(int, int) const { return 256; }
|
||||
int getTilePipDimZ(int, int) const { return 1; }
|
||||
char getNameDelimiter() const { return '/'; }
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
BelId getBelByName(IdString name) const;
|
||||
BelId getBelByName(IdStringList name) const;
|
||||
|
||||
IdString getBelName(BelId bel) const
|
||||
IdStringList getBelName(BelId bel) const
|
||||
{
|
||||
std::string name = "X";
|
||||
name += std::to_string(bel.tile % chip_info->width);
|
||||
name += "/Y";
|
||||
name += std::to_string(bel.tile / chip_info->width);
|
||||
name += "/";
|
||||
name += nameOf(IdString(bel_data(bel).name));
|
||||
return id(name);
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
std::array<IdString, 3> ids{x_ids.at(bel.tile % chip_info->width), y_ids.at(bel.tile / chip_info->width),
|
||||
IdString(bel_data(bel).name)};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
uint32_t getBelChecksum(BelId bel) const { return (bel.tile << 16) ^ bel.index; }
|
||||
@ -1023,16 +1026,13 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
WireId getWireByName(IdString name) const;
|
||||
IdString getWireName(WireId wire) const
|
||||
WireId getWireByName(IdStringList name) const;
|
||||
IdStringList getWireName(WireId wire) const
|
||||
{
|
||||
std::string name = "X";
|
||||
name += std::to_string(wire.tile % chip_info->width);
|
||||
name += "/Y";
|
||||
name += std::to_string(wire.tile / chip_info->width);
|
||||
name += "/";
|
||||
name += nameOf(IdString(wire_data(wire).name));
|
||||
return id(name);
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
std::array<IdString, 3> ids{x_ids.at(wire.tile % chip_info->width), y_ids.at(wire.tile / chip_info->width),
|
||||
IdString(wire_data(wire).name)};
|
||||
return IdStringList(ids);
|
||||
}
|
||||
|
||||
IdString getWireType(WireId wire) const;
|
||||
@ -1136,8 +1136,8 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
PipId getPipByName(IdString name) const;
|
||||
IdString getPipName(PipId pip) const;
|
||||
PipId getPipByName(IdStringList name) const;
|
||||
IdStringList getPipName(PipId pip) const;
|
||||
|
||||
void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
|
||||
{
|
||||
@ -1289,8 +1289,8 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
GroupId getGroupByName(IdString name) const { return GroupId(); }
|
||||
IdString getGroupName(GroupId group) const { return IdString(); }
|
||||
GroupId getGroupByName(IdStringList name) const { return GroupId(); }
|
||||
IdStringList getGroupName(GroupId group) const { return IdStringList(); }
|
||||
std::vector<GroupId> getGroups() const { return {}; }
|
||||
std::vector<BelId> getGroupBels(GroupId group) const { return {}; }
|
||||
std::vector<WireId> getGroupWires(GroupId group) const { return {}; }
|
||||
|
@ -544,7 +544,7 @@ struct NexusPacker
|
||||
{
|
||||
if (!ci->attrs.count(id_BEL))
|
||||
return BelId();
|
||||
return ctx->getBelByName(ctx->id(ci->attrs.at(id_BEL).as_string()));
|
||||
return ctx->getBelByNameStr(ci->attrs.at(id_BEL).as_string());
|
||||
}
|
||||
|
||||
void pack_io()
|
||||
|
Loading…
Reference in New Issue
Block a user