ecp5: Implement IdStringList for all arch object names
This is a complete implementation of IdStringList for ECP5; excluding the GUI (which you will have to disable for it to build). Signed-off-by: D. Shah <dave@ds0.me>
This commit is contained in:
parent
9614d37229
commit
d792bce0fb
@ -45,7 +45,7 @@ void archcheck_names(const Context *ctx)
|
||||
|
||||
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", ctx->nameOfWire(wire));
|
||||
@ -64,7 +64,7 @@ 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", ctx->nameOfPip(pip));
|
||||
|
@ -299,19 +299,25 @@ const char *BaseCtx::nameOfBel(BelId bel) const
|
||||
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)
|
||||
@ -320,6 +326,24 @@ BelId BaseCtx::getBelByNameStr(const std::string &str)
|
||||
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
|
||||
{
|
||||
if (net_info->driver.cell == nullptr)
|
||||
@ -701,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;
|
||||
}
|
||||
|
@ -235,8 +235,28 @@ struct IdStringList
|
||||
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; }
|
||||
};
|
||||
|
||||
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
|
||||
@ -890,8 +910,11 @@ struct BaseCtx
|
||||
const char *nameOfPip(PipId pip) const;
|
||||
const char *nameOfGroup(GroupId group) const;
|
||||
|
||||
// Overrides of arch functions that take a string and handle IdStringList parsing
|
||||
// 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);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
|
||||
|
108
ecp5/arch.cc
108
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)
|
||||
@ -133,6 +122,17 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -215,30 +215,22 @@ IdString Arch::archArgsToId(ArchArgs args) const
|
||||
|
||||
BelId Arch::getBelByName(IdStringList name) const
|
||||
{
|
||||
// TODO: take advantage of IdStringList for fast parsing
|
||||
if (name.size() != 3)
|
||||
return BelId();
|
||||
BelId ret;
|
||||
#if 0
|
||||
auto it = bel_by_name.find(name);
|
||||
if (it != bel_by_name.end())
|
||||
return it->second;
|
||||
#endif
|
||||
Location loc;
|
||||
std::string basename;
|
||||
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(getCtx()));
|
||||
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 0
|
||||
if (ret.index >= 0)
|
||||
bel_by_name[name] = ret;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return BelId();
|
||||
}
|
||||
|
||||
BelRange Arch::getBelsByTile(int x, int y) const
|
||||
{
|
||||
@ -286,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;
|
||||
@ -323,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++) {
|
||||
@ -333,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);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -1215,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)
|
||||
@ -1223,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;
|
||||
|
||||
@ -1232,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
|
||||
|
26
ecp5/arch.h
26
ecp5/arch.h
@ -441,9 +441,7 @@ 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;
|
||||
@ -452,6 +450,8 @@ struct Arch : BaseCtx
|
||||
|
||||
// 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);
|
||||
@ -598,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
|
||||
@ -716,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(); }
|
||||
|
||||
@ -895,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;
|
||||
|
@ -42,7 +42,7 @@ template <> struct string_converter<BelId>
|
||||
|
||||
template <> struct string_converter<WireId>
|
||||
{
|
||||
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); }
|
||||
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); }
|
||||
|
||||
std::string to_str(Context *ctx, WireId id)
|
||||
{
|
||||
@ -54,7 +54,7 @@ template <> struct string_converter<WireId>
|
||||
|
||||
template <> struct string_converter<const WireId>
|
||||
{
|
||||
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); }
|
||||
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); }
|
||||
|
||||
std::string to_str(Context *ctx, WireId id)
|
||||
{
|
||||
@ -66,7 +66,7 @@ template <> struct string_converter<const WireId>
|
||||
|
||||
template <> struct string_converter<PipId>
|
||||
{
|
||||
PipId from_str(Context *ctx, std::string name) { return ctx->getPipByName(ctx->id(name)); }
|
||||
PipId from_str(Context *ctx, std::string name) { return ctx->getPipByNameStr(name); }
|
||||
|
||||
std::string to_str(Context *ctx, PipId id)
|
||||
{
|
||||
|
@ -811,14 +811,12 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
NetInfo *lsrnet = nullptr;
|
||||
if (ci->ports.find(ctx->id("LSR")) != ci->ports.end() && ci->ports.at(ctx->id("LSR")).net != nullptr)
|
||||
lsrnet = ci->ports.at(ctx->id("LSR")).net;
|
||||
if (ctx->getBoundWireNet(ctx->getWireByName(
|
||||
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR0")))) == lsrnet) {
|
||||
if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR0")) == lsrnet) {
|
||||
cc.tiles[tname].add_enum("LSR0.SRMODE",
|
||||
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
|
||||
}
|
||||
if (ctx->getBoundWireNet(ctx->getWireByName(
|
||||
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR1")))) == lsrnet) {
|
||||
if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "LSR1")) == lsrnet) {
|
||||
cc.tiles[tname].add_enum("LSR1.SRMODE",
|
||||
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum("LSR1.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
|
||||
@ -827,12 +825,10 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
NetInfo *clknet = nullptr;
|
||||
if (ci->ports.find(ctx->id("CLK")) != ci->ports.end() && ci->ports.at(ctx->id("CLK")).net != nullptr)
|
||||
clknet = ci->ports.at(ctx->id("CLK")).net;
|
||||
if (ctx->getBoundWireNet(ctx->getWireByName(
|
||||
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK0")))) == clknet) {
|
||||
if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK0")) == clknet) {
|
||||
cc.tiles[tname].add_enum("CLK0.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK"));
|
||||
}
|
||||
if (ctx->getBoundWireNet(ctx->getWireByName(
|
||||
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/CLK1")))) == clknet) {
|
||||
if (ctx->getBoundWireNet(ctx->getWireByLocAndBasename(bel.location, "CLK1")) == clknet) {
|
||||
cc.tiles[tname].add_enum("CLK1.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK"));
|
||||
}
|
||||
}
|
||||
@ -907,8 +903,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
(ci->ports.find(ctx->id("IOLTO")) == ci->ports.end() ||
|
||||
ci->ports.at(ctx->id("IOLTO")).net == nullptr)) {
|
||||
// Tie tristate low if unconnected for outputs or bidir
|
||||
std::string jpt = fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/JPADDT" << pio.back());
|
||||
WireId jpt_wire = ctx->getWireByName(ctx->id(jpt));
|
||||
WireId jpt_wire = ctx->getWireByLocAndBasename(bel.location, fmt_str("JPADDT" << pio.back()));
|
||||
PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin();
|
||||
WireId cib_wire = ctx->getPipSrcWire(jpt_pip);
|
||||
std::string cib_tile =
|
||||
|
Loading…
Reference in New Issue
Block a user