Merge pull request #561 from YosysHQ/dave/idstringlist

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

View File

@ -10,6 +10,9 @@ readonly_wrapper<Context, decltype(&Context::hierarchy), &Context::hierarchy, wr
readwrite_wrapper<Context, decltype(&Context::top_module), &Context::top_module, conv_to_str<IdString>,
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>,

View File

@ -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));

View File

@ -69,6 +69,41 @@ void IdString::initialize_add(const BaseCtx *ctx, const char *s, int idx)
ctx->idstring_idx_to_str->push_back(&insert_rc.first->first);
}
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);
}

View File

@ -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;

View File

@ -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;
}
};

View File

@ -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)

View File

@ -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",

View File

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

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -92,6 +92,10 @@ Get Z dimension for the specified tile for bels. All bels with at specified X an
Get Z dimension for the specified tile for pips. All pips with at specified X and Y coordinates must have a Z coordinate in the range `0 .. getTileDimZ(X,Y)-1` (inclusive).
### 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.)

View File

@ -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

View File

@ -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;

View File

@ -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)
{

View File

@ -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 =

View File

@ -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;
}

View File

@ -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));

View File

@ -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);
}

View File

@ -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(); }

View File

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

View File

@ -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

View File

@ -759,14 +759,14 @@ void IdString::initialize_arch(const BaseCtx *ctx)
// ---------------------------------------------------------------
BelId Arch::getBelByName(IdString name) const
BelId Arch::getBelByName(IdStringList name) const
{
if (bels.count(name))
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
{

View File

@ -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;

View File

@ -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));
}

View File

@ -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:

View File

@ -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 = "";

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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());
}

View File

@ -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

View File

@ -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")

View File

@ -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)

View File

@ -417,7 +417,7 @@ static BelId find_padin_gbuf(Context *ctx, BelId bel, IdString port_name)
auto wire = ctx->getBelPinWire(bel, port_name);
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

View File

@ -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(); }

View File

@ -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 {}; }

View File

@ -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()