aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/arch.cc107
-rw-r--r--ecp5/arch.h40
-rw-r--r--ecp5/arch_pybindings.h8
-rw-r--r--ecp5/bitstream.cc15
-rw-r--r--ecp5/globals.cc19
-rw-r--r--ecp5/pack.cc48
6 files changed, 113 insertions, 124 deletions
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 25f95c53..d86bad5d 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -37,17 +37,6 @@
NEXTPNR_NAMESPACE_BEGIN
-static std::tuple<int, int, std::string> split_identifier_name(const std::string &name)
-{
- size_t first_slash = name.find('/');
- NPNR_ASSERT(first_slash != std::string::npos);
- size_t second_slash = name.find('/', first_slash + 1);
- NPNR_ASSERT(second_slash != std::string::npos);
- return std::make_tuple(std::stoi(name.substr(1, first_slash)),
- std::stoi(name.substr(first_slash + 2, second_slash - first_slash)),
- name.substr(second_slash + 1));
-};
-
// -----------------------------------------------------------------------
void IdString::initialize_arch(const BaseCtx *ctx)
@@ -128,6 +117,22 @@ Arch::Arch(ArchArgs args) : args(args)
bucket.name = bel_type;
buckets.push_back(bucket);
}
+
+ for (int i = 0; i < chip_info->width; i++)
+ x_ids.push_back(id(stringf("X%d", i)));
+ for (int i = 0; i < chip_info->height; i++)
+ y_ids.push_back(id(stringf("Y%d", i)));
+
+ for (int i = 0; i < chip_info->width; i++) {
+ IdString x_id = id(stringf("X%d", i));
+ x_ids.push_back(x_id);
+ id_to_x[x_id] = i;
+ }
+ for (int i = 0; i < chip_info->height; i++) {
+ IdString y_id = id(stringf("Y%d", i));
+ y_ids.push_back(y_id);
+ id_to_y[y_id] = i;
+ }
}
// -----------------------------------------------------------------------
@@ -208,27 +213,23 @@ IdString Arch::archArgsToId(ArchArgs args) const
// -----------------------------------------------------------------------
-BelId Arch::getBelByName(IdString name) const
+BelId Arch::getBelByName(IdStringList name) const
{
+ if (name.size() != 3)
+ return BelId();
BelId ret;
- auto it = bel_by_name.find(name);
- if (it != bel_by_name.end())
- return it->second;
-
Location loc;
- std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
+ loc.x = id_to_x.at(name[0]);
+ loc.y = id_to_y.at(name[1]);
ret.location = loc;
const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < int(loci->bel_data.size()); i++) {
- if (std::strcmp(loci->bel_data[i].name.get(), basename.c_str()) == 0) {
+ if (std::strcmp(loci->bel_data[i].name.get(), name[2].c_str(this)) == 0) {
ret.index = i;
- break;
+ return ret;
}
}
- if (ret.index >= 0)
- bel_by_name[name] = ret;
- return ret;
+ return BelId();
}
BelRange Arch::getBelsByTile(int x, int y) const
@@ -277,36 +278,31 @@ PortType Arch::getBelPinType(BelId bel, IdString pin) const
// -----------------------------------------------------------------------
-WireId Arch::getWireByName(IdString name) const
+WireId Arch::getWireByName(IdStringList name) const
{
+ if (name.size() != 3)
+ return WireId();
WireId ret;
- auto it = wire_by_name.find(name);
- if (it != wire_by_name.end())
- return it->second;
-
Location loc;
- std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
+ loc.x = id_to_x.at(name[0]);
+ loc.y = id_to_y.at(name[1]);
ret.location = loc;
const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < int(loci->wire_data.size()); i++) {
- if (std::strcmp(loci->wire_data[i].name.get(), basename.c_str()) == 0) {
+ if (std::strcmp(loci->wire_data[i].name.get(), name[2].c_str(this)) == 0) {
ret.index = i;
- ret.location = loc;
- break;
+ return ret;
}
}
- if (ret.index >= 0)
- wire_by_name[name] = ret;
- else
- ret.location = Location();
- return ret;
+ return WireId();
}
// -----------------------------------------------------------------------
-PipId Arch::getPipByName(IdString name) const
+PipId Arch::getPipByName(IdStringList name) const
{
+ if (name.size() != 3)
+ return PipId();
auto it = pip_by_name.find(name);
if (it != pip_by_name.end())
return it->second;
@@ -314,7 +310,8 @@ PipId Arch::getPipByName(IdString name) const
PipId ret;
Location loc;
std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
+ loc.x = id_to_x.at(name[0]);
+ loc.y = id_to_y.at(name[1]);
ret.location = loc;
const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < int(loci->pip_data.size()); i++) {
@@ -324,24 +321,23 @@ PipId Arch::getPipByName(IdString name) const
pip_by_name[getPipName(curr)] = curr;
}
if (pip_by_name.find(name) == pip_by_name.end())
- NPNR_ASSERT_FALSE_STR("no pip named " + name.str(this));
+ NPNR_ASSERT_FALSE_STR("no pip named " + name.str(getCtx()));
return pip_by_name[name];
}
-IdString Arch::getPipName(PipId pip) const
+IdStringList Arch::getPipName(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
- int x = pip.location.x;
- int y = pip.location.y;
-
- std::string src_name = getWireName(getPipSrcWire(pip)).str(this);
- std::replace(src_name.begin(), src_name.end(), '/', '.');
-
- std::string dst_name = getWireName(getPipDstWire(pip)).str(this);
- std::replace(dst_name.begin(), dst_name.end(), '/', '.');
+ // TODO: can we improve how pip names are stored/built?
+ auto &pip_data = locInfo(pip)->pip_data[pip.index];
+ WireId src = getPipSrcWire(pip), dst = getPipDstWire(pip);
+ std::string pip_name = stringf("%d_%d_%s->%d_%d_%s", pip_data.rel_src_loc.x, pip_data.rel_src_loc.y,
+ getWireBasename(src).c_str(this), pip_data.rel_dst_loc.x, pip_data.rel_dst_loc.y,
+ getWireBasename(dst).c_str(this));
- return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name);
+ std::array<IdString, 3> ids{x_ids.at(pip.location.x), y_ids.at(pip.location.y), id(pip_name)};
+ return IdStringList(ids);
}
// -----------------------------------------------------------------------
@@ -1206,7 +1202,7 @@ const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
// -----------------------------------------------------------------------
-GroupId Arch::getGroupByName(IdString name) const
+GroupId Arch::getGroupByName(IdStringList name) const
{
for (auto g : getGroups())
if (getGroupName(g) == name)
@@ -1214,7 +1210,7 @@ GroupId Arch::getGroupByName(IdString name) const
return GroupId();
}
-IdString Arch::getGroupName(GroupId group) const
+IdStringList Arch::getGroupName(GroupId group) const
{
std::string suffix;
@@ -1223,10 +1219,11 @@ IdString Arch::getGroupName(GroupId group) const
suffix = "switchbox";
break;
default:
- return IdString();
+ return IdStringList();
}
- return id("X" + std::to_string(group.location.x) + "/Y" + std::to_string(group.location.y) + "/" + suffix);
+ std::array<IdString, 3> ids{x_ids.at(group.location.x), y_ids.at(group.location.y), id(suffix)};
+ return IdStringList(ids);
}
std::vector<GroupId> Arch::getGroups() const
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 18a70fe8..9997cd5c 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -441,15 +441,18 @@ struct Arch : BaseCtx
const PackageInfoPOD *package_info;
const SpeedGradePOD *speed_grade;
- mutable std::unordered_map<IdString, BelId> bel_by_name;
- mutable std::unordered_map<IdString, WireId> wire_by_name;
- mutable std::unordered_map<IdString, PipId> pip_by_name;
+ mutable std::unordered_map<IdStringList, PipId> pip_by_name;
std::vector<CellInfo *> bel_to_cell;
std::unordered_map<WireId, NetInfo *> wire_to_net;
std::unordered_map<PipId, NetInfo *> pip_to_net;
std::unordered_map<WireId, int> wire_fanout;
+ // fast access to X and Y IdStrings for building object names
+ std::vector<IdString> x_ids, y_ids;
+ // inverse of the above for name->object mapping
+ std::unordered_map<IdString, int> id_to_x, id_to_y;
+
ArchArgs args;
Arch(ArchArgs args);
@@ -471,22 +474,23 @@ struct Arch : BaseCtx
int getGridDimY() const { return chip_info->height; };
int getTileBelDimZ(int, int) const { return max_loc_bels; };
int getTilePipDimZ(int, int) const { return 1; };
+ char getNameDelimiter() const { return '/'; }
// -------------------------------------------------
- BelId getBelByName(IdString name) const;
+ BelId getBelByName(IdStringList name) const;
template <typename Id> const LocationTypePOD *locInfo(Id &id) const
{
return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
}
- IdString getBelName(BelId bel) const
+ IdStringList getBelName(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
- std::stringstream name;
- name << "X" << bel.location.x << "/Y" << bel.location.y << "/" << locInfo(bel)->bel_data[bel.index].name.get();
- return id(name.str());
+ std::array<IdString, 3> ids{x_ids.at(bel.location.x), y_ids.at(bel.location.y),
+ id(locInfo(bel)->bel_data[bel.index].name.get())};
+ return IdStringList(ids);
}
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
@@ -594,16 +598,14 @@ struct Arch : BaseCtx
// -------------------------------------------------
- WireId getWireByName(IdString name) const;
+ WireId getWireByName(IdStringList name) const;
- IdString getWireName(WireId wire) const
+ IdStringList getWireName(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
-
- std::stringstream name;
- name << "X" << wire.location.x << "/Y" << wire.location.y << "/"
- << locInfo(wire)->wire_data[wire.index].name.get();
- return id(name.str());
+ std::array<IdString, 3> ids{x_ids.at(wire.location.x), y_ids.at(wire.location.y),
+ id(locInfo(wire)->wire_data[wire.index].name.get())};
+ return IdStringList(ids);
}
IdString getWireType(WireId wire) const
@@ -712,8 +714,8 @@ struct Arch : BaseCtx
// -------------------------------------------------
- PipId getPipByName(IdString name) const;
- IdString getPipName(PipId pip) const;
+ PipId getPipByName(IdStringList name) const;
+ IdStringList getPipName(PipId pip) const;
IdString getPipType(PipId pip) const { return IdString(); }
@@ -891,8 +893,8 @@ struct Arch : BaseCtx
// -------------------------------------------------
- GroupId getGroupByName(IdString name) const;
- IdString getGroupName(GroupId group) const;
+ GroupId getGroupByName(IdStringList name) const;
+ IdStringList getGroupName(GroupId group) const;
std::vector<GroupId> getGroups() const;
std::vector<BelId> getGroupBels(GroupId group) const;
std::vector<WireId> getGroupWires(GroupId group) const;
diff --git a/ecp5/arch_pybindings.h b/ecp5/arch_pybindings.h
index dd3161ae..4228f12b 100644
--- a/ecp5/arch_pybindings.h
+++ b/ecp5/arch_pybindings.h
@@ -30,7 +30,7 @@ namespace PythonConversion {
template <> struct string_converter<BelId>
{
- BelId from_str(Context *ctx, std::string name) { return ctx->getBelByName(ctx->id(name)); }
+ BelId from_str(Context *ctx, std::string name) { return ctx->getBelByNameStr(name); }
std::string to_str(Context *ctx, BelId id)
{
@@ -42,7 +42,7 @@ template <> struct string_converter<BelId>
template <> struct string_converter<WireId>
{
- WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); }
+ WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); }
std::string to_str(Context *ctx, WireId id)
{
@@ -54,7 +54,7 @@ template <> struct string_converter<WireId>
template <> struct string_converter<const WireId>
{
- WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); }
+ WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); }
std::string to_str(Context *ctx, WireId id)
{
@@ -66,7 +66,7 @@ template <> struct string_converter<const WireId>
template <> struct string_converter<PipId>
{
- PipId from_str(Context *ctx, std::string name) { return ctx->getPipByName(ctx->id(name)); }
+ PipId from_str(Context *ctx, std::string name) { return ctx->getPipByNameStr(name); }
std::string to_str(Context *ctx, PipId id)
{
diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc
index 0841fa32..4a43bfca 100644
--- a/ecp5/bitstream.cc
+++ b/ecp5/bitstream.cc
@@ -811,14 +811,12 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
NetInfo *lsrnet = nullptr;
if (ci->ports.find(ctx->id("LSR")) != ci->ports.end() && ci->ports.at(ctx->id("LSR")).net != nullptr)
lsrnet = ci->ports.at(ctx->id("LSR")).net;
- if (ctx->getBoundWireNet(ctx->getWireByName(
- ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR0")))) == lsrnet) {
+ if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR0")) == lsrnet) {
cc.tiles[tname].add_enum("LSR0.SRMODE",
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
}
- if (ctx->getBoundWireNet(ctx->getWireByName(
- ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR1")))) == lsrnet) {
+ if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR1")) == lsrnet) {
cc.tiles[tname].add_enum("LSR1.SRMODE",
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
cc.tiles[tname].add_enum("LSR1.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
@@ -827,12 +825,10 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
NetInfo *clknet = nullptr;
if (ci->ports.find(ctx->id("CLK")) != ci->ports.end() && ci->ports.at(ctx->id("CLK")).net != nullptr)
clknet = ci->ports.at(ctx->id("CLK")).net;
- if (ctx->getBoundWireNet(ctx->getWireByName(
- ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK0")))) == clknet) {
+ if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK0")) == clknet) {
cc.tiles[tname].add_enum("CLK0.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK"));
}
- if (ctx->getBoundWireNet(ctx->getWireByName(
- ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK1")))) == clknet) {
+ if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK1")) == clknet) {
cc.tiles[tname].add_enum("CLK1.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK"));
}
}
@@ -907,8 +903,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
(ci->ports.find(ctx->id("IOLTO")) == ci->ports.end() ||
ci->ports.at(ctx->id("IOLTO")).net == nullptr)) {
// Tie tristate low if unconnected for outputs or bidir
- std::string jpt = fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/JPADDT" << pio.back());
- WireId jpt_wire = ctx->getWireByName(ctx->id(jpt));
+ WireId jpt_wire = ctx->getWireByLocAndBasename(bel.location, fmt_str("JPADDT" << pio.back()));
PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin();
WireId cib_wire = ctx->getPipSrcWire(jpt_pip);
std::string cib_tile =
diff --git a/ecp5/globals.cc b/ecp5/globals.cc
index 218090e1..478e5fac 100644
--- a/ecp5/globals.cc
+++ b/ecp5/globals.cc
@@ -176,8 +176,8 @@ class Ecp5GlobalRouter
}
}
if (upstream.size() > 30000) {
- log_error("failed to route HPBX%02d00 to %s.%s\n", global_index,
- ctx->getBelName(user.cell->bel).c_str(ctx), user.port.c_str(ctx));
+ log_error("failed to route HPBX%02d00 to %s.%s\n", global_index, ctx->nameOfBel(user.cell->bel),
+ user.port.c_str(ctx));
}
}
// Set all the pips we found along the way
@@ -238,8 +238,7 @@ class Ecp5GlobalRouter
if (visit.empty() || visit.size() > 50000) {
if (allow_fail)
return false;
- log_error("cannot route global from %s to %s.\n", ctx->getWireName(src).c_str(ctx),
- ctx->getWireName(dst).c_str(ctx));
+ log_error("cannot route global from %s to %s.\n", ctx->nameOfWire(src), ctx->nameOfWire(dst));
}
cursor = visit.front();
visit.pop();
@@ -300,7 +299,7 @@ class Ecp5GlobalRouter
if (drv.cell == nullptr) {
return 0;
} else if (drv.cell->attrs.count(ctx->id("BEL"))) {
- drv_bel = ctx->getBelByName(ctx->id(drv.cell->attrs.at(ctx->id("BEL")).as_string()));
+ drv_bel = ctx->getBelByNameStr(drv.cell->attrs.at(ctx->id("BEL")).as_string());
} else {
// Check if driver is a singleton
BelId last_bel;
@@ -325,8 +324,8 @@ class Ecp5GlobalRouter
} else {
// Check for dedicated routing
if (has_short_route(ctx->getBelPinWire(drv_bel, drv.port), ctx->getBelPinWire(dcc->bel, id_CLKI))) {
- // log_info("dedicated route %s -> %s\n", ctx->getWireName(ctx->getBelPinWire(drv_bel,
- // drv.port)).c_str(ctx), ctx->getBelName(dcc->bel).c_str(ctx));
+ // log_info("dedicated route %s -> %s\n", ctx->nameOfWire(ctx->getBelPinWire(drv_bel,
+ // drv.port)), ctx->nameOfWire(dcc->bel));
dedicated_routing = true;
return 0;
}
@@ -347,8 +346,8 @@ class Ecp5GlobalRouter
while (true) {
if (visit.empty() || visit.size() > 10000) {
- // log_info ("dist %s -> %s = inf\n", ctx->getWireName(src).c_str(ctx),
- // ctx->getWireName(dst).c_str(ctx));
+ // log_info ("dist %s -> %s = inf\n", ctx->nameOfWire(src),
+ // ctx->nameOfWire(dst));
return false;
}
cursor = visit.front();
@@ -372,7 +371,7 @@ class Ecp5GlobalRouter
cursor = ctx->getPipSrcWire(fnd->second);
length++;
}
- // log_info ("dist %s -> %s = %d\n", ctx->getWireName(src).c_str(ctx), ctx->getWireName(dst).c_str(ctx),
+ // log_info ("dist %s -> %s = %d\n", ctx->nameOfWire(src), ctx->nameOfWire(dst),
// length);
return length < thresh;
}
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index b60d6c7d..ed2dfc29 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -522,7 +522,7 @@ class Ecp5Packer
trio->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str());
} else {
log_info("pin '%s' constrained to Bel '%s'.\n", trio->name.c_str(ctx),
- ctx->getBelName(pinBel).c_str(ctx));
+ ctx->nameOfBel(pinBel));
}
trio->attrs[ctx->id("BEL")] = ctx->getBelName(pinBel).str(ctx);
}
@@ -1657,7 +1657,7 @@ class Ecp5Packer
CellInfo *dcu = clki->driver.cell;
if (!dcu->attrs.count(ctx->id("BEL")))
log_error("DCU must be constrained to a Bel!\n");
- BelId bel = ctx->getBelByName(ctx->id(dcu->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(dcu->attrs.at(ctx->id("BEL")).as_string());
if (bel == BelId())
log_error("Invalid DCU bel '%s'\n", dcu->attrs.at(ctx->id("BEL")).c_str());
Loc loc = ctx->getBelLocation(bel);
@@ -1704,7 +1704,7 @@ class Ecp5Packer
for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL")))
- available_plls.erase(ctx->getBelByName(ctx->id(ci->attrs.at(ctx->id("BEL")).as_string())));
+ available_plls.erase(ctx->getBelByNameStr(ci->attrs.at(ctx->id("BEL")).as_string()));
}
// Place PLL connected to fixed drivers such as IO close to their source
for (auto cell : sorted(ctx->cells)) {
@@ -1716,7 +1716,7 @@ class Ecp5Packer
const CellInfo *drivercell = drivernet->driver.cell;
if (!drivercell->attrs.count(ctx->id("BEL")))
continue;
- BelId drvbel = ctx->getBelByName(ctx->id(drivercell->attrs.at(ctx->id("BEL")).as_string()));
+ BelId drvbel = ctx->getBelByNameStr(drivercell->attrs.at(ctx->id("BEL")).as_string());
Loc drvloc = ctx->getBelLocation(drvbel);
BelId closest_pll;
int closest_distance = std::numeric_limits<int>::max();
@@ -1848,12 +1848,12 @@ class Ecp5Packer
WireId next;
while (true) {
if (upstream.empty() || upstream.size() > 30000)
- log_error("failed to route bank %d ECLK%d to %s.%s\n", bank, found_eclk,
- ctx->getBelName(usr_bel).c_str(ctx), usr_port.name.c_str(ctx));
+ log_error("failed to route bank %d ECLK%d to %s.%s\n", bank, found_eclk, ctx->nameOfBel(usr_bel),
+ usr_port.name.c_str(ctx));
next = upstream.front();
upstream.pop();
if (ctx->debug)
- log_info(" visited %s\n", ctx->getWireName(next).c_str(ctx));
+ log_info(" visited %s\n", ctx->nameOfWire(next));
IdString basename = ctx->getWireBasename(next);
if (basename == bnke_name || basename == global_name) {
break;
@@ -1913,17 +1913,17 @@ class Ecp5Packer
log_error("DQSBUFM can only be used with a pin-constrained PIO connected to its DQSI input"
"(while processing '%s').\n",
ci->name.c_str(ctx));
- BelId pio_bel = ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string()));
+ BelId pio_bel = ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string());
NPNR_ASSERT(pio_bel != BelId());
Loc pio_loc = ctx->getBelLocation(pio_bel);
if (pio_loc.z != 0)
log_error("PIO '%s' does not appear to be a DQS site (expecting an 'A' pin).\n",
- ctx->getBelName(pio_bel).c_str(ctx));
+ ctx->nameOfBel(pio_bel));
pio_loc.z = 8;
BelId dqsbuf = ctx->getBelByLocation(pio_loc);
if (dqsbuf == BelId() || ctx->getBelType(dqsbuf) != id_DQSBUFM)
log_error("PIO '%s' does not appear to be a DQS site (didn't find a DQSBUFM).\n",
- ctx->getBelName(pio_bel).c_str(ctx));
+ ctx->nameOfBel(pio_bel));
ci->attrs[ctx->id("BEL")] = ctx->getBelName(dqsbuf).str(ctx);
bool got_dqsg = ctx->getPIODQSGroup(pio_bel, dqsbuf_dqsg[ci->name].first, dqsbuf_dqsg[ci->name].second);
NPNR_ASSERT(got_dqsg);
@@ -2078,15 +2078,14 @@ class Ecp5Packer
log_error("IOLOGIC functionality (DDR, DELAY, DQS, etc) can only be used with pin-constrained PIO "
"(while processing '%s').\n",
curr->name.c_str(ctx));
- BelId bel = ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string());
NPNR_ASSERT(bel != BelId());
return bel;
};
auto create_pio_iologic = [&](CellInfo *pio, CellInfo *curr) {
BelId bel = get_pio_bel(pio, curr);
- log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx),
- ctx->getBelName(bel).c_str(ctx));
+ log_info("IOLOGIC component %s connected to PIO Bel %s\n", curr->name.c_str(ctx), ctx->nameOfBel(bel));
Loc loc = ctx->getBelLocation(bel);
bool s = false;
if (loc.y == 0 || loc.y == (ctx->chip_info->height - 1))
@@ -2292,8 +2291,7 @@ class Ecp5Packer
replace_port(ci, ctx->id("D2"), iol, id_TXDATA2);
replace_port(ci, ctx->id("D3"), iol, id_TXDATA3);
if (ci->type == ctx->id("ODDR71B")) {
- Loc loc =
- ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
+ Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
if (loc.z % 2 == 1)
log_error("ODDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
replace_port(ci, ctx->id("D4"), iol, id_TXDATA4);
@@ -2326,8 +2324,7 @@ class Ecp5Packer
replace_port(ci, ctx->id("Q2"), iol, id_RXDATA2);
replace_port(ci, ctx->id("Q3"), iol, id_RXDATA3);
if (ci->type == ctx->id("IDDR71B")) {
- Loc loc =
- ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
+ Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(ctx->id("BEL")).as_string()));
if (loc.z % 2 == 1)
log_error("IDDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
replace_port(ci, ctx->id("Q4"), iol, id_RXDATA4);
@@ -2579,7 +2576,7 @@ class Ecp5Packer
if (!user.cell->attrs.count(ctx->id("BEL")))
continue;
Loc user_loc = ctx->getBelLocation(
- ctx->getBelByName(ctx->id(user.cell->attrs.at(ctx->id("BEL")).as_string())));
+ ctx->getBelByNameStr(user.cell->attrs.at(ctx->id("BEL")).as_string()));
for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) != id_ECLKBRIDGECS)
continue;
@@ -2594,8 +2591,8 @@ class Ecp5Packer
CellInfo *drv = input->driver.cell;
if (!drv->attrs.count(ctx->id("BEL")))
continue;
- Loc drv_loc = ctx->getBelLocation(
- ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string())));
+ Loc drv_loc =
+ ctx->getBelLocation(ctx->getBelByNameStr(drv->attrs.at(ctx->id("BEL")).as_string()));
BelId closest;
int closest_x = -1; // aim for same side of chip
for (auto bel : ctx->getBels()) {
@@ -2639,7 +2636,7 @@ class Ecp5Packer
if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) {
if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr)
continue;
- BelId bel = ctx->getBelByName(ctx->id(str_or_default(ci->attrs, ctx->id("BEL"))));
+ BelId bel = ctx->getBelByNameStr(str_or_default(ci->attrs, ctx->id("BEL")));
NPNR_ASSERT(bel != BelId());
Loc pioLoc = ctx->getBelLocation(bel);
if (ci->type == id_DQSBUFM)
@@ -2683,8 +2680,7 @@ class Ecp5Packer
const NetInfo *eclko = net_or_nullptr(ci, id_ECLKO);
if (eclki != nullptr && eclki->driver.cell != nullptr) {
if (eclki->driver.cell->type == id_ECLKBRIDGECS) {
- BelId bel =
- ctx->getBelByName(ctx->id(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(eclki->driver.cell->attrs.at(ctx->id("BEL")).as_string());
Loc loc = ctx->getBelLocation(bel);
ci->attrs[ctx->id("BEL")] =
ctx->getBelName(ctx->getBelByLocation(Loc(loc.x, loc.y, 15))).str(ctx);
@@ -2697,7 +2693,7 @@ class Ecp5Packer
for (auto user : eclko->users) {
if (user.cell->type == id_TRELLIS_ECLKBUF) {
Loc eckbuf_loc = ctx->getBelLocation(
- ctx->getBelByName(ctx->id(user.cell->attrs.at(ctx->id("BEL")).as_string())));
+ ctx->getBelByNameStr(user.cell->attrs.at(ctx->id("BEL")).as_string()));
for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) != id_ECLKSYNCB)
continue;
@@ -2726,7 +2722,7 @@ class Ecp5Packer
const CellInfo *uc = usr.cell;
if (uc->type != id_DQSBUFM || !uc->attrs.count(ctx->id("BEL")))
continue;
- BelId dqsb_bel = ctx->getBelByName(ctx->id(uc->attrs.at(ctx->id("BEL")).as_string()));
+ BelId dqsb_bel = ctx->getBelByNameStr(uc->attrs.at(ctx->id("BEL")).as_string());
Loc dqsb_loc = ctx->getBelLocation(dqsb_bel);
if (dqsb_loc.x > 15)
right_bank_users = true;
@@ -2809,7 +2805,7 @@ class Ecp5Packer
CellInfo *drv = clki->driver.cell;
if (drv->type != id_ECLKSYNCB || !drv->attrs.count(ctx->id("BEL")))
continue;
- BelId bel = ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string()));
+ BelId bel = ctx->getBelByNameStr(drv->attrs.at(ctx->id("BEL")).as_string());
// Find a CLKDIVF that is routeable from the ECLKSYNC
std::queue<WireId> visit;
visit.push(ctx->getBelPinWire(bel, id_ECLKO));