Merge pull request #37 from YosysHQ/ngapi

API change: Use CellInfo* and NetInfo* as cell/net handles
This commit is contained in:
Clifford Wolf 2018-08-05 16:46:24 +02:00 committed by GitHub
commit 6c8319e29a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 298 additions and 289 deletions

View File

@ -232,25 +232,26 @@ void Context::check() const
auto ni = n.second.get();
NPNR_ASSERT(n.first == ni->name);
for (auto &w : ni->wires) {
NPNR_ASSERT(n.first == getBoundWireNet(w.first));
NPNR_ASSERT(ni == getBoundWireNet(w.first));
if (w.second.pip != PipId()) {
NPNR_ASSERT(w.first == getPipDstWire(w.second.pip));
NPNR_ASSERT(n.first == getBoundPipNet(w.second.pip));
NPNR_ASSERT(ni == getBoundPipNet(w.second.pip));
}
}
}
for (auto w : getWires()) {
IdString net = getBoundWireNet(w);
if (net != IdString()) {
NPNR_ASSERT(nets.at(net)->wires.count(w));
auto ni = getBoundWireNet(w);
if (ni != nullptr) {
NPNR_ASSERT(ni->wires.count(w));
}
}
for (auto &c : cells) {
NPNR_ASSERT(c.first == c.second->name);
if (c.second->bel != BelId())
NPNR_ASSERT(getBoundBelCell(c.second->bel) == c.first);
auto ci = c.second.get();
NPNR_ASSERT(c.first == ci->name);
if (ci->bel != BelId())
NPNR_ASSERT(getBoundBelCell(c.second->bel) == ci);
for (auto &port : c.second->ports) {
NetInfo *net = port.second.net;
if (net != nullptr) {

View File

@ -437,6 +437,13 @@ struct BaseCtx
const Context *getCtx() const { return reinterpret_cast<const Context *>(this); }
template<typename T> const char *nameOf(const T *obj)
{
if (obj == nullptr)
return "";
return obj->name.c_str(getCtx());
}
// --------------------------------------------------------------
bool allUiReload = true;

View File

@ -131,7 +131,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
if (iters >= 4)
wirelen += ctx->rng(25);
if (wirelen <= best_ripup_wirelen) {
CellInfo *curr_cell = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
CellInfo *curr_cell = ctx->getBoundBelCell(bel);
if (curr_cell->belStrength < STRENGTH_STRONG) {
best_ripup_wirelen = wirelen;
ripup_bel = bel;
@ -158,7 +158,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
if (ctx->verbose)
log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx),
ctx->getBelName(best_bel).c_str(ctx));
ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
cell = ripup_target;
}
@ -232,8 +232,8 @@ class ConstraintLegaliseWorker
return false;
}
if (!ctx->checkBelAvail(locBel)) {
IdString confCell = ctx->getConflictingBelCell(locBel);
if (ctx->cells[confCell]->belStrength >= STRENGTH_STRONG) {
CellInfo *confCell = ctx->getConflictingBelCell(locBel);
if (confCell->belStrength >= STRENGTH_STRONG) {
return false;
}
}
@ -362,18 +362,17 @@ class ConstraintLegaliseWorker
cp.second.y, cp.second.z);
BelId target = ctx->getBelByLocation(cp.second);
if (!ctx->checkBelAvail(target)) {
IdString conflicting = ctx->getConflictingBelCell(target);
if (conflicting != IdString()) {
CellInfo *confl_cell = ctx->cells.at(conflicting).get();
CellInfo *confl_cell = ctx->getConflictingBelCell(target);
if (confl_cell != nullptr) {
if (ctx->verbose)
log_info(" '%s' already placed at '%s'\n", conflicting.c_str(ctx),
log_info(" '%s' already placed at '%s'\n", ctx->nameOf(confl_cell),
ctx->getBelName(confl_cell->bel).c_str(ctx));
NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG);
ctx->unbindBel(target);
rippedCells.insert(conflicting);
rippedCells.insert(confl_cell->name);
}
}
ctx->bindBel(target, cp.first, STRENGTH_LOCKED);
ctx->bindBel(target, ctx->cells.at(cp.first).get(), STRENGTH_LOCKED);
rippedCells.erase(cp.first);
}
NPNR_ASSERT(constraints_satisfied(cell));

View File

@ -105,7 +105,7 @@ class SAPlacer
cell->type.c_str(ctx));
}
ctx->bindBel(bel, cell->name, STRENGTH_USER);
ctx->bindBel(bel, cell, STRENGTH_USER);
locked_bels.insert(bel);
placed_cells++;
}
@ -256,11 +256,11 @@ class SAPlacer
// Final post-pacement validitiy check
ctx->yield();
for (auto bel : ctx->getBels()) {
IdString cell = ctx->getBoundBelCell(bel);
CellInfo *cell = ctx->getBoundBelCell(bel);
if (!ctx->isBelLocationValid(bel)) {
std::string cell_text = "no cell";
if (cell != IdString())
cell_text = std::string("cell '") + cell.str(ctx) + "'";
if (cell != nullptr)
cell_text = std::string("cell '") + ctx->nameOf(cell) + "'";
if (ctx->force) {
log_warning("post-placement validity check failed for Bel '%s' "
"(%s)\n",
@ -309,7 +309,7 @@ class SAPlacer
uint64_t score = ctx->rng64();
if (score <= best_ripup_score) {
best_ripup_score = score;
ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
ripup_target = ctx->getBoundBelCell(bel);
ripup_bel = bel;
}
}
@ -324,7 +324,7 @@ class SAPlacer
} else {
all_placed = true;
}
ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
// Back annotate location
cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx);
@ -340,20 +340,17 @@ class SAPlacer
new_lengths.clear();
update.clear();
BelId oldBel = cell->bel;
IdString other = ctx->getBoundBelCell(newBel);
CellInfo *other_cell = nullptr;
if (other != IdString()) {
other_cell = ctx->cells[other].get();
if (other_cell->belStrength > STRENGTH_WEAK)
CellInfo *other_cell = ctx->getBoundBelCell(newBel);
if (other_cell != nullptr && other_cell->belStrength > STRENGTH_WEAK) {
return false;
}
int old_dist = get_constraints_distance(ctx, cell);
int new_dist;
if (other != IdString())
if (other_cell != nullptr)
old_dist += get_constraints_distance(ctx, other_cell);
wirelen_t new_metric = 0, delta;
ctx->unbindBel(oldBel);
if (other != IdString()) {
if (other_cell != nullptr) {
ctx->unbindBel(newBel);
}
@ -361,20 +358,20 @@ class SAPlacer
if (port.second.net != nullptr)
update.insert(port.second.net);
if (other != IdString()) {
if (other_cell != nullptr) {
for (const auto &port : other_cell->ports)
if (port.second.net != nullptr)
update.insert(port.second.net);
}
ctx->bindBel(newBel, cell->name, STRENGTH_WEAK);
ctx->bindBel(newBel, cell, STRENGTH_WEAK);
if (other != IdString()) {
ctx->bindBel(oldBel, other_cell->name, STRENGTH_WEAK);
if (other_cell != nullptr) {
ctx->bindBel(oldBel, other_cell, STRENGTH_WEAK);
}
if (!ctx->isBelLocationValid(newBel) || ((other != IdString() && !ctx->isBelLocationValid(oldBel)))) {
if (!ctx->isBelLocationValid(newBel) || ((other_cell != nullptr && !ctx->isBelLocationValid(oldBel)))) {
ctx->unbindBel(newBel);
if (other != IdString())
if (other_cell != nullptr)
ctx->unbindBel(oldBel);
goto swap_fail;
}
@ -391,7 +388,7 @@ class SAPlacer
}
new_dist = get_constraints_distance(ctx, cell);
if (other != IdString())
if (other_cell != nullptr)
new_dist += get_constraints_distance(ctx, other_cell);
delta = new_metric - curr_metric;
delta += (cfg.constraintWeight / temp) * (new_dist - old_dist);
@ -400,7 +397,7 @@ class SAPlacer
if (delta < 0 || (temp > 1e-6 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
n_accept++;
} else {
if (other != IdString())
if (other_cell != nullptr)
ctx->unbindBel(oldBel);
ctx->unbindBel(newBel);
goto swap_fail;
@ -411,9 +408,9 @@ class SAPlacer
return true;
swap_fail:
ctx->bindBel(oldBel, cell->name, STRENGTH_WEAK);
if (other != IdString()) {
ctx->bindBel(newBel, other, STRENGTH_WEAK);
ctx->bindBel(oldBel, cell, STRENGTH_WEAK);
if (other_cell != nullptr) {
ctx->bindBel(newBel, other_cell, STRENGTH_WEAK);
}
return false;
}

View File

@ -140,6 +140,14 @@ template <typename T> struct deref_and_wrap
using ret_type = ContextualWrapper<T &>;
};
template <typename T> struct addr_and_unwrap
{
inline T *operator()(Context *ctx, ContextualWrapper<T &> x) { return &(x.base); }
using arg_type = ContextualWrapper<T &>;
using ret_type = T *;
};
// Function wrapper
// Zero parameters, one return
template <typename Class, typename FuncT, FuncT fn, typename rv_conv> struct fn_wrapper_0a

View File

@ -159,15 +159,15 @@ struct Router
if (!ctx->checkWireAvail(next_wire)) {
if (!ripup)
continue;
IdString ripupWireNet = ctx->getConflictingWireNet(next_wire);
if (ripupWireNet == net_name || ripupWireNet == IdString())
NetInfo *ripupWireNet = ctx->getConflictingWireNet(next_wire);
if (ripupWireNet == nullptr || ripupWireNet->name == net_name)
continue;
auto it1 = scores.wireScores.find(next_wire);
if (it1 != scores.wireScores.end())
next_delay += (it1->second * ripup_penalty) / 8;
auto it2 = scores.netWireScores.find(std::make_pair(ripupWireNet, next_wire));
auto it2 = scores.netWireScores.find(std::make_pair(ripupWireNet->name, next_wire));
if (it2 != scores.netWireScores.end())
next_delay += it2->second * ripup_penalty;
@ -177,15 +177,15 @@ struct Router
if (!ctx->checkPipAvail(pip)) {
if (!ripup)
continue;
IdString ripupPipNet = ctx->getConflictingPipNet(pip);
if (ripupPipNet == net_name || ripupPipNet == IdString())
NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip);
if (ripupPipNet == nullptr || ripupPipNet->name == net_name)
continue;
auto it1 = scores.pipScores.find(pip);
if (it1 != scores.pipScores.end())
next_delay += (it1->second * ripup_penalty) / 8;
auto it2 = scores.netPipScores.find(std::make_pair(ripupPipNet, pip));
auto it2 = scores.netPipScores.find(std::make_pair(ripupPipNet->name, pip));
if (it2 != scores.netPipScores.end())
next_delay += it2->second * ripup_penalty;
@ -294,12 +294,12 @@ struct Router
if (reroute) {
// complete ripup
ripup_net(ctx, net_name);
ctx->bindWire(src_wire, net_name, STRENGTH_WEAK);
ctx->bindWire(src_wire, ctx->nets.at(net_name).get(), STRENGTH_WEAK);
src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay();
} else {
// re-use existing routes as much as possible
if (net_info->wires.count(src_wire) == 0)
ctx->bindWire(src_wire, net_name, STRENGTH_WEAK);
ctx->bindWire(src_wire, ctx->nets.at(net_name).get(), STRENGTH_WEAK);
src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay();
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) {
@ -399,42 +399,42 @@ struct Router
if (src_wires.count(cursor))
break;
IdString conflicting_wire_net = ctx->getConflictingWireNet(cursor);
NetInfo *conflicting_wire_net = ctx->getConflictingWireNet(cursor);
if (conflicting_wire_net != IdString()) {
if (conflicting_wire_net != nullptr) {
NPNR_ASSERT(ripup);
NPNR_ASSERT(conflicting_wire_net != net_name);
NPNR_ASSERT(conflicting_wire_net->name != net_name);
ctx->unbindWire(cursor);
if (!ctx->checkWireAvail(cursor))
ripup_net(ctx, conflicting_wire_net);
ripup_net(ctx, conflicting_wire_net->name);
rippedNets.insert(conflicting_wire_net);
rippedNets.insert(conflicting_wire_net->name);
scores.wireScores[cursor]++;
scores.netWireScores[std::make_pair(net_name, cursor)]++;
scores.netWireScores[std::make_pair(conflicting_wire_net, cursor)]++;
scores.netWireScores[std::make_pair(conflicting_wire_net->name, cursor)]++;
}
PipId pip = visited[cursor].pip;
IdString conflicting_pip_net = ctx->getConflictingPipNet(pip);
NetInfo *conflicting_pip_net = ctx->getConflictingPipNet(pip);
if (conflicting_pip_net != IdString()) {
if (conflicting_pip_net != nullptr) {
NPNR_ASSERT(ripup);
NPNR_ASSERT(conflicting_pip_net != net_name);
NPNR_ASSERT(conflicting_pip_net->name != net_name);
if (ctx->getBoundPipNet(pip) == conflicting_pip_net)
ctx->unbindPip(pip);
if (!ctx->checkPipAvail(pip))
ripup_net(ctx, conflicting_pip_net);
ripup_net(ctx, conflicting_pip_net->name);
rippedNets.insert(conflicting_pip_net);
rippedNets.insert(conflicting_pip_net->name);
scores.pipScores[visited[cursor].pip]++;
scores.netPipScores[std::make_pair(net_name, visited[cursor].pip)]++;
scores.netPipScores[std::make_pair(conflicting_pip_net, visited[cursor].pip)]++;
scores.netPipScores[std::make_pair(conflicting_pip_net->name, visited[cursor].pip)]++;
}
ctx->bindPip(visited[cursor].pip, net_name, STRENGTH_WEAK);
ctx->bindPip(visited[cursor].pip, ctx->nets.at(net_name).get(), STRENGTH_WEAK);
src_wires[cursor] = visited[cursor].delay;
cursor = ctx->getPipSrcWire(visited[cursor].pip);
}

View File

@ -139,11 +139,11 @@ Returns true if the given bel is a global buffer. A global buffer does not "pull
Return a (preferably unique) number that represents this bel. This is used in design state checksum calculations.
### void bindBel(BelId bel, IdString cell, PlaceStrength strength)
### void bindBel(BelId bel, CellInfo \*cell, PlaceStrength strength)
Bind a given bel to a given cell with the given strength.
This method must also update `CellInfo::bel` and `CellInfo::belStrength`.
This method must also update `cell->bel` and `cell->belStrength`.
### void unbindBel(BelId bel)
@ -155,13 +155,13 @@ This method must also update `CellInfo::bel` and `CellInfo::belStrength`.
Returns true if the bel is available. A bel can be unavailable because it is bound, or because it is exclusive to some other resource that is bound.
### IdString getBoundBelCell(BelId bel) const
### CellInfo \*getBoundBelCell(BelId bel) const
Return the cell the given bel is bound to, or `IdString()` if the bel is not bound.
Return the cell the given bel is bound to, or nullptr if the bel is not bound.
### IdString getConflictingBelCell(BelId bel) const
### CellInfo \*getConflictingBelCell(BelId bel) const
If the bel is unavailable, and unbinding a single cell would make it available, then this method must return the name of that cell.
If the bel is unavailable, and unbinding a single cell would make it available, then this method must return that cell.
### const\_range\<BelId\> getBels() const
@ -204,12 +204,12 @@ simply return `IdString()`.
Return a (preferably unique) number that represents this wire. This is used in design state checksum calculations.
### void bindWire(WireId wire, IdString net, PlaceStrength strength)
### void bindWire(WireId wire, NetInfo \*net, PlaceStrength strength)
Bind a wire to a net. This method must be used when binding a wire that is driven by a bel pin. Use `binPip()`
when binding a wire that is driven by a pip.
This method must also update `NetInfo::wires`.
This method must also update `net->wires`.
### void unbindWire(WireId wire)
@ -221,16 +221,16 @@ This method must also update `NetInfo::wires`.
Return true if the wire is available, i.e. can be bound to a net.
### IdString getBoundWireNet(WireId wire) const
### NetInfo \*getBoundWireNet(WireId wire) const
Return the net a wire is bound to.
### IdString getConflictingWireNet(WireId wire) const
### NetInfo \*getConflictingWireNet(WireId wire) const
If this returns a non-empty IdString, then unbinding that net
If this returns a non-nullptr, then unbinding that net
will make the given wire available.
This returns an empty IdString if the wire is already available,
This returns nullptr if the wire is already available,
or if there is no single net that can be unbound to make this
wire available.
@ -266,11 +266,11 @@ implementations may simply return `IdString()`.
Return a (preferably unique) number that represents this pip. This is used in design state checksum calculations.
### void bindPip(PipId pip, IdString net, PlaceStrength strength)
### void bindPip(PipId pip, NetInfo \*net, PlaceStrength strength)
Bid a pip to a net. This also bind the destination wire of that pip.
This method must also update `NetInfo::wires`.
This method must also update `net->wires`.
### void unbindPip(PipId pip)
@ -282,11 +282,11 @@ This method must also update `NetInfo::wires`.
Returns true if the given pip is available to be bound to a net.
### IdString getBoundPipNet(PipId pip) const
### NetInfo \*getBoundPipNet(PipId pip) const
Return the net this pip is bound to.
### IdString getConflictingPipNet(PipId pip) const
### NetInfo \*getConflictingPipNet(PipId pip) const
Return the net that needs to be unbound in order to make this
pip available.

View File

@ -479,7 +479,7 @@ DecalXY Arch::getBelDecal(BelId bel) const
decalxy.decal.type = DecalId::TYPE_BEL;
decalxy.decal.location = bel.location;
decalxy.decal.z = bel.index;
decalxy.decal.active = bel_to_cell.count(bel) && (bel_to_cell.at(bel) != IdString());
decalxy.decal.active = bel_to_cell.count(bel) && (bel_to_cell.at(bel) != nullptr);
return decalxy;
}

View File

@ -404,10 +404,9 @@ struct Arch : BaseCtx
mutable std::unordered_map<IdString, WireId> wire_by_name;
mutable std::unordered_map<IdString, PipId> pip_by_name;
std::unordered_map<BelId, IdString> bel_to_cell;
std::unordered_map<WireId, IdString> wire_to_net;
std::unordered_map<PipId, IdString> pip_to_net;
std::unordered_map<PipId, IdString> switches_locked;
std::unordered_map<BelId, CellInfo *> bel_to_cell;
std::unordered_map<WireId, NetInfo *> wire_to_net;
std::unordered_map<PipId, NetInfo *> pip_to_net;
ArchArgs args;
Arch(ArchArgs args);
@ -447,23 +446,23 @@ struct Arch : BaseCtx
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
void bindBel(BelId bel, IdString cell, PlaceStrength strength)
void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel] == IdString());
NPNR_ASSERT(bel_to_cell[bel] == nullptr);
bel_to_cell[bel] = cell;
cells[cell]->bel = bel;
cells[cell]->belStrength = strength;
cell->bel = bel;
cell->belStrength = strength;
refreshUiBel(bel);
}
void unbindBel(BelId bel)
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel] != IdString());
cells[bel_to_cell[bel]]->bel = BelId();
cells[bel_to_cell[bel]]->belStrength = STRENGTH_NONE;
bel_to_cell[bel] = IdString();
NPNR_ASSERT(bel_to_cell[bel] != nullptr);
bel_to_cell[bel]->bel = BelId();
bel_to_cell[bel]->belStrength = STRENGTH_NONE;
bel_to_cell[bel] = nullptr;
refreshUiBel(bel);
}
@ -484,23 +483,23 @@ struct Arch : BaseCtx
bool checkBelAvail(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == IdString();
return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == nullptr;
}
IdString getBoundBelCell(BelId bel) const
CellInfo *getBoundBelCell(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
if (bel_to_cell.find(bel) == bel_to_cell.end())
return IdString();
return nullptr;
else
return bel_to_cell.at(bel);
}
IdString getConflictingBelCell(BelId bel) const
CellInfo *getConflictingBelCell(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
if (bel_to_cell.find(bel) == bel_to_cell.end())
return IdString();
return nullptr;
else
return bel_to_cell.at(bel);
}
@ -557,53 +556,53 @@ struct Arch : BaseCtx
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
void bindWire(WireId wire, IdString net, PlaceStrength strength)
void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire] == IdString());
NPNR_ASSERT(wire_to_net[wire] == nullptr);
wire_to_net[wire] = net;
nets[net]->wires[wire].pip = PipId();
nets[net]->wires[wire].strength = strength;
net->wires[wire].pip = PipId();
net->wires[wire].strength = strength;
}
void unbindWire(WireId wire)
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire] != IdString());
NPNR_ASSERT(wire_to_net[wire] != nullptr);
auto &net_wires = nets[wire_to_net[wire]]->wires;
auto &net_wires = wire_to_net[wire]->wires;
auto it = net_wires.find(wire);
NPNR_ASSERT(it != net_wires.end());
auto pip = it->second.pip;
if (pip != PipId()) {
pip_to_net[pip] = IdString();
pip_to_net[pip] = nullptr;
}
net_wires.erase(it);
wire_to_net[wire] = IdString();
wire_to_net[wire] = nullptr;
}
bool checkWireAvail(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == IdString();
return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == nullptr;
}
IdString getBoundWireNet(WireId wire) const
NetInfo *getBoundWireNet(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
if (wire_to_net.find(wire) == wire_to_net.end())
return IdString();
return nullptr;
else
return wire_to_net.at(wire);
}
IdString getConflictingWireNet(WireId wire) const
NetInfo *getConflictingWireNet(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
if (wire_to_net.find(wire) == wire_to_net.end())
return IdString();
return nullptr;
else
return wire_to_net.at(wire);
}
@ -637,57 +636,57 @@ struct Arch : BaseCtx
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
void bindPip(PipId pip, IdString net, PlaceStrength strength)
void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{
NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip] == IdString());
NPNR_ASSERT(pip_to_net[pip] == nullptr);
pip_to_net[pip] = net;
WireId dst;
dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
NPNR_ASSERT(wire_to_net[dst] == IdString());
NPNR_ASSERT(wire_to_net[dst] == nullptr);
wire_to_net[dst] = net;
nets[net]->wires[dst].pip = pip;
nets[net]->wires[dst].strength = strength;
net->wires[dst].pip = pip;
net->wires[dst].strength = strength;
}
void unbindPip(PipId pip)
{
NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip] != IdString());
NPNR_ASSERT(pip_to_net[pip] != nullptr);
WireId dst;
dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
NPNR_ASSERT(wire_to_net[dst] != IdString());
wire_to_net[dst] = IdString();
nets[pip_to_net[pip]]->wires.erase(dst);
NPNR_ASSERT(wire_to_net[dst] != nullptr);
wire_to_net[dst] = nullptr;
pip_to_net[pip]->wires.erase(dst);
pip_to_net[pip] = IdString();
pip_to_net[pip] = nullptr;
}
bool checkPipAvail(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == IdString();
return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == nullptr;
}
IdString getBoundPipNet(PipId pip) const
NetInfo *getBoundPipNet(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
if (pip_to_net.find(pip) == pip_to_net.end())
return IdString();
return nullptr;
else
return pip_to_net.at(pip);
}
IdString getConflictingPipNet(PipId pip) const
NetInfo *getConflictingPipNet(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
if (pip_to_net.find(pip) == pip_to_net.end())
return IdString();
return nullptr;
else
return pip_to_net.at(pip);
}

View File

@ -68,19 +68,18 @@ bool Arch::isBelLocationValid(BelId bel) const
std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) {
const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other);
CellInfo *cell_other = getBoundBelCell(bel_other);
if (cell_other != nullptr) {
bel_cells.push_back(cell_other);
}
}
return slicesCompatible(bel_cells);
} else {
IdString cellId = getBoundBelCell(bel);
if (cellId == IdString())
CellInfo *cell = getBoundBelCell(bel);
if (cell == nullptr)
return true;
else
return isValidBelForCell(cells.at(cellId).get(), bel);
return isValidBelForCell(cell, bel);
}
}
@ -92,10 +91,9 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString() && bel_other != bel) {
const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other);
CellInfo *cell_other = getBoundBelCell(bel_other);
if (cell_other != nullptr && bel_other != bel) {
bel_cells.push_back(cell_other);
}
}

View File

@ -60,13 +60,13 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel");
addr_and_unwrap<CellInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel");
fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap(
ctx_cls, "unbindBel");
fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, conv_to_str<IdString>,
fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, deref_and_wrap<CellInfo>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell");
fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell,
conv_to_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
deref_and_wrap<CellInfo>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,
"getBels");
@ -78,15 +78,15 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire");
addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire");
fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap(
ctx_cls, "unbindWire");
fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail");
fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, conv_to_str<IdString>,
fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, deref_and_wrap<NetInfo>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet");
fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet,
conv_to_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet");
deref_and_wrap<NetInfo>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet");
fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, wrap_context<WireRange>>::def_wrap(
ctx_cls, "getWires");
@ -96,15 +96,15 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip");
addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip");
fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap(
ctx_cls, "unbindPip");
fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail");
fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, conv_to_str<IdString>,
fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, deref_and_wrap<NetInfo>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet");
fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet,
conv_to_str<IdString>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet");
deref_and_wrap<NetInfo>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet");
fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill");

View File

@ -163,7 +163,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
// Add all set, configurable pips to the config
for (auto pip : ctx->getPips()) {
if (ctx->getBoundPipNet(pip) != IdString()) {
if (ctx->getBoundPipNet(pip) != nullptr) {
if (ctx->getPipClass(pip) == 0) { // ignore fixed pips
std::string tile = ctx->getPipTilename(pip);
std::string source = get_trellis_wirename(ctx, pip.location, ctx->getPipSrcWire(pip));
@ -244,9 +244,9 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
cc.tiles[tname].add_enum(slice + ".REG1.REGSET",
str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET"));
cc.tiles[tname].add_enum(slice + ".CEMUX", str_or_default(ci->params, ctx->id("CEMUX"), "1"));
IdString lsrnet;
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->name;
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) {
cc.tiles[tname].add_enum("LSR0.SRMODE", str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));

View File

@ -148,7 +148,7 @@ int main(int argc, char *argv[])
#ifndef NO_GUI
if (vm.count("gui")) {
Application a(argc, argv);
MainWindow w(std::move(ctx),args);
MainWindow w(std::move(ctx), args);
w.show();
return a.exec();

View File

@ -214,27 +214,27 @@ uint32_t Arch::getBelChecksum(BelId bel) const
return 0;
}
void Arch::bindBel(BelId bel, IdString cell, PlaceStrength strength)
void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
{
bels.at(bel).bound_cell = cell;
cells.at(cell)->bel = bel;
cells.at(cell)->belStrength = strength;
cell->bel = bel;
cell->belStrength = strength;
refreshUiBel(bel);
}
void Arch::unbindBel(BelId bel)
{
cells.at(bels.at(bel).bound_cell)->bel = BelId();
cells.at(bels.at(bel).bound_cell)->belStrength = STRENGTH_NONE;
bels.at(bel).bound_cell = IdString();
bels.at(bel).bound_cell->bel = BelId();
bels.at(bel).bound_cell->belStrength = STRENGTH_NONE;
bels.at(bel).bound_cell = nullptr;
refreshUiBel(bel);
}
bool Arch::checkBelAvail(BelId bel) const { return bels.at(bel).bound_cell == IdString(); }
bool Arch::checkBelAvail(BelId bel) const { return bels.at(bel).bound_cell == nullptr; }
IdString Arch::getBoundBelCell(BelId bel) const { return bels.at(bel).bound_cell; }
CellInfo *Arch::getBoundBelCell(BelId bel) const { return bels.at(bel).bound_cell; }
IdString Arch::getConflictingBelCell(BelId bel) const { return bels.at(bel).bound_cell; }
CellInfo *Arch::getConflictingBelCell(BelId bel) const { return bels.at(bel).bound_cell; }
const std::vector<BelId> &Arch::getBels() const { return bel_ids; }
@ -271,34 +271,34 @@ uint32_t Arch::getWireChecksum(WireId wire) const
return 0;
}
void Arch::bindWire(WireId wire, IdString net, PlaceStrength strength)
void Arch::bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
{
wires.at(wire).bound_net = net;
nets.at(net)->wires[wire].pip = PipId();
nets.at(net)->wires[wire].strength = strength;
net->wires[wire].pip = PipId();
net->wires[wire].strength = strength;
refreshUiWire(wire);
}
void Arch::unbindWire(WireId wire)
{
auto &net_wires = nets[wires.at(wire).bound_net]->wires;
auto &net_wires = wires.at(wire).bound_net->wires;
auto pip = net_wires.at(wire).pip;
if (pip != PipId()) {
pips.at(pip).bound_net = IdString();
pips.at(pip).bound_net = nullptr;
refreshUiPip(pip);
}
net_wires.erase(wire);
wires.at(wire).bound_net = IdString();
wires.at(wire).bound_net = nullptr;
refreshUiWire(wire);
}
bool Arch::checkWireAvail(WireId wire) const { return wires.at(wire).bound_net == IdString(); }
bool Arch::checkWireAvail(WireId wire) const { return wires.at(wire).bound_net == nullptr; }
IdString Arch::getBoundWireNet(WireId wire) const { return wires.at(wire).bound_net; }
NetInfo *Arch::getBoundWireNet(WireId wire) const { return wires.at(wire).bound_net; }
IdString Arch::getConflictingWireNet(WireId wire) const { return wires.at(wire).bound_net; }
NetInfo *Arch::getConflictingWireNet(WireId wire) const { return wires.at(wire).bound_net; }
const std::vector<BelPin> &Arch::getWireBelPins(WireId wire) const { return wires.at(wire).bel_pins; }
@ -323,13 +323,13 @@ uint32_t Arch::getPipChecksum(PipId wire) const
return 0;
}
void Arch::bindPip(PipId pip, IdString net, PlaceStrength strength)
void Arch::bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{
WireId wire = pips.at(pip).dstWire;
pips.at(pip).bound_net = net;
wires.at(wire).bound_net = net;
nets.at(net)->wires[wire].pip = pip;
nets.at(net)->wires[wire].strength = strength;
net->wires[wire].pip = pip;
net->wires[wire].strength = strength;
refreshUiPip(pip);
refreshUiWire(wire);
}
@ -337,18 +337,18 @@ void Arch::bindPip(PipId pip, IdString net, PlaceStrength strength)
void Arch::unbindPip(PipId pip)
{
WireId wire = pips.at(pip).dstWire;
nets.at(wires.at(wire).bound_net)->wires.erase(wire);
pips.at(pip).bound_net = IdString();
wires.at(wire).bound_net = IdString();
wires.at(wire).bound_net->wires.erase(wire);
pips.at(pip).bound_net = nullptr;
wires.at(wire).bound_net = nullptr;
refreshUiPip(pip);
refreshUiWire(wire);
}
bool Arch::checkPipAvail(PipId pip) const { return pips.at(pip).bound_net == IdString(); }
bool Arch::checkPipAvail(PipId pip) const { return pips.at(pip).bound_net == nullptr; }
IdString Arch::getBoundPipNet(PipId pip) const { return pips.at(pip).bound_net; }
NetInfo *Arch::getBoundPipNet(PipId pip) const { return pips.at(pip).bound_net; }
IdString Arch::getConflictingPipNet(PipId pip) const { return pips.at(pip).bound_net; }
NetInfo *Arch::getConflictingPipNet(PipId pip) const { return pips.at(pip).bound_net; }
const std::vector<PipId> &Arch::getPips() const { return pip_ids; }

View File

@ -31,7 +31,8 @@ struct WireInfo;
struct PipInfo
{
IdString name, type, bound_net;
IdString name, type;
NetInfo *bound_net;
WireId srcWire, dstWire;
DelayInfo delay;
DecalXY decalxy;
@ -39,7 +40,8 @@ struct PipInfo
struct WireInfo
{
IdString name, type, bound_net;
IdString name, type;
NetInfo *bound_net;
std::vector<PipId> downhill, uphill, aliases;
BelPin uphill_bel_pin;
std::vector<BelPin> downhill_bel_pins;
@ -57,7 +59,8 @@ struct PinInfo
struct BelInfo
{
IdString name, type, bound_cell;
IdString name, type;
CellInfo *bound_cell;
std::unordered_map<IdString, PinInfo> pins;
DecalXY decalxy;
int x, y, z;
@ -142,11 +145,11 @@ struct Arch : BaseCtx
const std::vector<BelId> &getBelsByTile(int x, int y) const;
bool getBelGlobalBuf(BelId bel) const;
uint32_t getBelChecksum(BelId bel) const;
void bindBel(BelId bel, IdString cell, PlaceStrength strength);
void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength);
void unbindBel(BelId bel);
bool checkBelAvail(BelId bel) const;
IdString getBoundBelCell(BelId bel) const;
IdString getConflictingBelCell(BelId bel) const;
CellInfo *getBoundBelCell(BelId bel) const;
CellInfo *getConflictingBelCell(BelId bel) const;
const std::vector<BelId> &getBels() const;
BelType getBelType(BelId bel) const;
WireId getBelPinWire(BelId bel, PortPin pin) const;
@ -157,11 +160,11 @@ struct Arch : BaseCtx
IdString getWireName(WireId wire) const;
IdString getWireType(WireId wire) const;
uint32_t getWireChecksum(WireId wire) const;
void bindWire(WireId wire, IdString net, PlaceStrength strength);
void bindWire(WireId wire, NetInfo *net, PlaceStrength strength);
void unbindWire(WireId wire);
bool checkWireAvail(WireId wire) const;
IdString getBoundWireNet(WireId wire) const;
IdString getConflictingWireNet(WireId wire) const;
NetInfo *getBoundWireNet(WireId wire) const;
NetInfo *getConflictingWireNet(WireId wire) const;
DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); }
const std::vector<WireId> &getWires() const;
const std::vector<BelPin> &getWireBelPins(WireId wire) const;
@ -170,11 +173,11 @@ struct Arch : BaseCtx
IdString getPipName(PipId pip) const;
IdString getPipType(PipId pip) const;
uint32_t getPipChecksum(PipId pip) const;
void bindPip(PipId pip, IdString net, PlaceStrength strength);
void bindPip(PipId pip, NetInfo *net, PlaceStrength strength);
void unbindPip(PipId pip);
bool checkPipAvail(PipId pip) const;
IdString getBoundPipNet(PipId pip) const;
IdString getConflictingPipNet(PipId pip) const;
NetInfo *getBoundPipNet(PipId pip) const;
NetInfo *getConflictingPipNet(PipId pip) const;
const std::vector<PipId> &getPips() const;
WireId getPipSrcWire(PipId pip) const;
WireId getPipDstWire(PipId pip) const;

View File

@ -407,8 +407,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", ctx->belTypeToId(ctx->getBelType(bel)).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel));
addProperty(topItem, QVariant::String, "Bound Cell", ctx->getBoundBelCell(bel).c_str(ctx), ElementType::CELL);
addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->getConflictingBelCell(bel).c_str(ctx),
addProperty(topItem, QVariant::String, "Bound Cell", ctx->nameOf(ctx->getBoundBelCell(bel)), ElementType::CELL);
addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->nameOf(ctx->getConflictingBelCell(bel)),
ElementType::CELL);
QtProperty *belpinsItem = addSubGroup(topItem, "Ports");
@ -429,8 +429,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire));
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundWireNet(wire).c_str(ctx), ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingWireNet(wire).c_str(ctx),
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)),
ElementType::NET);
DelayInfo delay = ctx->getWireDelay(wire);
@ -484,8 +484,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundPipNet(pip).c_str(ctx), ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingPipNet(pip).c_str(ctx),
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
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);

View File

@ -672,7 +672,7 @@ DecalXY Arch::getBelDecal(BelId bel) const
DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_BEL;
decalxy.decal.index = bel.index;
decalxy.decal.active = bel_to_cell.at(bel.index) != IdString();
decalxy.decal.active = bel_to_cell.at(bel.index) != nullptr;
return decalxy;
}
@ -681,7 +681,7 @@ DecalXY Arch::getWireDecal(WireId wire) const
DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_WIRE;
decalxy.decal.index = wire.index;
decalxy.decal.active = wire_to_net.at(wire.index) != IdString();
decalxy.decal.active = wire_to_net.at(wire.index) != nullptr;
return decalxy;
}
@ -690,7 +690,7 @@ DecalXY Arch::getPipDecal(PipId pip) const
DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_PIP;
decalxy.decal.index = pip.index;
decalxy.decal.active = pip_to_net.at(pip.index) != IdString();
decalxy.decal.active = pip_to_net.at(pip.index) != nullptr;
return decalxy;
};

View File

@ -400,10 +400,10 @@ struct Arch : BaseCtx
mutable std::unordered_map<Loc, int> bel_by_loc;
std::vector<bool> bel_carry;
std::vector<IdString> bel_to_cell;
std::vector<IdString> wire_to_net;
std::vector<IdString> pip_to_net;
std::vector<IdString> switches_locked;
std::vector<CellInfo*> bel_to_cell;
std::vector<NetInfo*> wire_to_net;
std::vector<NetInfo*> pip_to_net;
std::vector<NetInfo*> switches_locked;
ArchArgs args;
Arch(ArchArgs args);
@ -437,26 +437,25 @@ struct Arch : BaseCtx
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
void bindBel(BelId bel, IdString cell, PlaceStrength strength)
void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] == IdString());
auto &c = cells[cell];
NPNR_ASSERT(bel_to_cell[bel.index] == nullptr);
bel_to_cell[bel.index] = cell;
bel_carry[bel.index] = (c->type == id_icestorm_lc && c->lcInfo.carryEnable);
c->bel = bel;
c->belStrength = strength;
bel_carry[bel.index] = (cell->type == id_icestorm_lc && cell->lcInfo.carryEnable);
cell->bel = bel;
cell->belStrength = strength;
refreshUiBel(bel);
}
void unbindBel(BelId bel)
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] != IdString());
cells[bel_to_cell[bel.index]]->bel = BelId();
cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE;
bel_to_cell[bel.index] = IdString();
NPNR_ASSERT(bel_to_cell[bel.index] != nullptr);
bel_to_cell[bel.index]->bel = BelId();
bel_to_cell[bel.index]->belStrength = STRENGTH_NONE;
bel_to_cell[bel.index] = nullptr;
bel_carry[bel.index] = false;
refreshUiBel(bel);
}
@ -464,16 +463,16 @@ struct Arch : BaseCtx
bool checkBelAvail(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index] == IdString();
return bel_to_cell[bel.index] == nullptr;
}
IdString getBoundBelCell(BelId bel) const
CellInfo *getBoundBelCell(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index];
}
IdString getConflictingBelCell(BelId bel) const
CellInfo *getConflictingBelCell(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index];
@ -525,49 +524,49 @@ struct Arch : BaseCtx
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
void bindWire(WireId wire, IdString net, PlaceStrength strength)
void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire.index] == IdString());
NPNR_ASSERT(wire_to_net[wire.index] == nullptr);
wire_to_net[wire.index] = net;
nets[net]->wires[wire].pip = PipId();
nets[net]->wires[wire].strength = strength;
net->wires[wire].pip = PipId();
net->wires[wire].strength = strength;
refreshUiWire(wire);
}
void unbindWire(WireId wire)
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire.index] != IdString());
NPNR_ASSERT(wire_to_net[wire.index] != nullptr);
auto &net_wires = nets[wire_to_net[wire.index]]->wires;
auto &net_wires = wire_to_net[wire.index]->wires;
auto it = net_wires.find(wire);
NPNR_ASSERT(it != net_wires.end());
auto pip = it->second.pip;
if (pip != PipId()) {
pip_to_net[pip.index] = IdString();
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString();
pip_to_net[pip.index] = nullptr;
switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr;
}
net_wires.erase(it);
wire_to_net[wire.index] = IdString();
wire_to_net[wire.index] = nullptr;
refreshUiWire(wire);
}
bool checkWireAvail(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index] == IdString();
return wire_to_net[wire.index] == nullptr;
}
IdString getBoundWireNet(WireId wire) const
NetInfo *getBoundWireNet(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index];
}
IdString getConflictingWireNet(WireId wire) const
NetInfo *getConflictingWireNet(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index];
@ -605,21 +604,21 @@ struct Arch : BaseCtx
PipId getPipByName(IdString name) const;
void bindPip(PipId pip, IdString net, PlaceStrength strength)
void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{
NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] == IdString());
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString());
NPNR_ASSERT(pip_to_net[pip.index] == nullptr);
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == nullptr);
pip_to_net[pip.index] = net;
switches_locked[chip_info->pip_data[pip.index].switch_index] = net;
WireId dst;
dst.index = chip_info->pip_data[pip.index].dst;
NPNR_ASSERT(wire_to_net[dst.index] == IdString());
NPNR_ASSERT(wire_to_net[dst.index] == nullptr);
wire_to_net[dst.index] = net;
nets[net]->wires[dst].pip = pip;
nets[net]->wires[dst].strength = strength;
net->wires[dst].pip = pip;
net->wires[dst].strength = strength;
refreshUiPip(pip);
refreshUiWire(dst);
}
@ -627,17 +626,17 @@ struct Arch : BaseCtx
void unbindPip(PipId pip)
{
NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] != IdString());
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != IdString());
NPNR_ASSERT(pip_to_net[pip.index] != nullptr);
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != nullptr);
WireId dst;
dst.index = chip_info->pip_data[pip.index].dst;
NPNR_ASSERT(wire_to_net[dst.index] != IdString());
wire_to_net[dst.index] = IdString();
nets[pip_to_net[pip.index]]->wires.erase(dst);
NPNR_ASSERT(wire_to_net[dst.index] != nullptr);
wire_to_net[dst.index] = nullptr;
pip_to_net[pip.index]->wires.erase(dst);
pip_to_net[pip.index] = IdString();
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString();
pip_to_net[pip.index] = nullptr;
switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr;
refreshUiPip(pip);
refreshUiWire(dst);
}
@ -648,12 +647,12 @@ struct Arch : BaseCtx
auto &pi = chip_info->pip_data[pip.index];
auto &si = chip_info->bits_info->switches[pi.switch_index];
if (switches_locked[pi.switch_index] != IdString())
if (switches_locked[pi.switch_index] != nullptr)
return false;
if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) {
NPNR_ASSERT(si.bel >= 0);
if (bel_to_cell[si.bel] != IdString())
if (bel_to_cell[si.bel] != nullptr)
return false;
}
@ -666,13 +665,13 @@ struct Arch : BaseCtx
return true;
}
IdString getBoundPipNet(PipId pip) const
NetInfo *getBoundPipNet(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
return pip_to_net[pip.index];
}
IdString getConflictingPipNet(PipId pip) const
NetInfo *getConflictingPipNet(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
return switches_locked[chip_info->pip_data[pip.index].switch_index];

View File

@ -74,19 +74,18 @@ bool Arch::isBelLocationValid(BelId bel) const
std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) {
const CellInfo *ci_other = cells.at(cell_other).get();
CellInfo *ci_other = getBoundBelCell(bel_other);
if (ci_other != nullptr) {
bel_cells.push_back(ci_other);
}
}
return logicCellsCompatible(bel_cells);
} else {
IdString cellId = getBoundBelCell(bel);
if (cellId == IdString())
CellInfo *ci = getBoundBelCell(bel);
if (ci == nullptr)
return true;
else
return isValidBelForCell(cells.at(cellId).get(), bel);
return isValidBelForCell(ci, bel);
}
}
@ -98,9 +97,8 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString() && bel_other != bel) {
const CellInfo *ci_other = cells.at(cell_other).get();
CellInfo *ci_other = getBoundBelCell(bel_other);
if (ci_other != nullptr && bel_other != bel) {
bel_cells.push_back(ci_other);
}
}
@ -126,12 +124,12 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
if (pll_bel.index != -1) {
auto pll_cell = getBoundBelCell(pll_bel);
// Is a PLL placed in this PLL bel?
if (pll_cell != IdString()) {
if (pll_cell != nullptr) {
// Is the shared port driving a net?
auto pi = cells.at(pll_cell)->ports[portPinToId(pll_bel_pin)];
auto pi = pll_cell->ports[portPinToId(pll_bel_pin)];
if (pi.net != nullptr) {
// Are we perhaps a PAD INPUT Bel that can be placed here?
if (cells.at(pll_cell)->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) {
if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) {
return true;
}
return false;

View File

@ -70,13 +70,13 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel");
addr_and_unwrap<CellInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel");
fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap(
ctx_cls, "unbindBel");
fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, conv_to_str<IdString>,
fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, deref_and_wrap<CellInfo>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell");
fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell,
conv_to_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
deref_and_wrap<CellInfo>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,
"getBels");
@ -88,15 +88,15 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire");
addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire");
fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap(
ctx_cls, "unbindWire");
fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail");
fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, conv_to_str<IdString>,
fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, deref_and_wrap<NetInfo>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet");
fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet,
conv_to_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet");
deref_and_wrap<NetInfo>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet");
fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, wrap_context<WireRange>>::def_wrap(
ctx_cls, "getWires");
@ -106,15 +106,15 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip");
addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip");
fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap(
ctx_cls, "unbindPip");
fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail");
fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, conv_to_str<IdString>,
fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, deref_and_wrap<NetInfo>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet");
fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet,
conv_to_str<IdString>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet");
deref_and_wrap<NetInfo>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet");
fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill");

View File

@ -291,7 +291,7 @@ void write_asc(const Context *ctx, std::ostream &out)
}
// Set pips
for (auto pip : ctx->getPips()) {
if (ctx->pip_to_net[pip.index] != IdString()) {
if (ctx->pip_to_net[pip.index] != nullptr) {
const PipInfoPOD &pi = ci.pip_data[pip.index];
const SwitchInfoPOD &swi = bi.switches[pi.switch_index];
int sw_bel_idx = swi.bel;
@ -310,7 +310,7 @@ void write_asc(const Context *ctx, std::ostream &out)
WireId permWire;
for (auto permPip : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) {
if (ctx->getBoundPipNet(permPip) != IdString()) {
if (ctx->getBoundPipNet(permPip) != nullptr) {
permWire = ctx->getPipSrcWire(permPip);
}
}
@ -384,7 +384,7 @@ void write_asc(const Context *ctx, std::ostream &out)
for (int i = 0; i < 4; i++) {
WireId lut_wire = ctx->getBelPinWire(bel, PortPin(PIN_I0 + i));
for (auto pip : ctx->getPipsUphill(lut_wire)) {
if (ctx->getBoundPipNet(pip) != IdString()) {
if (ctx->getBoundPipNet(pip) != nullptr) {
std::string name = ci.wire_data[ctx->getPipSrcWire(pip).index].name.get();
switch (name.back()) {
case '0':
@ -458,8 +458,8 @@ void write_asc(const Context *ctx, std::ostream &out)
NPNR_ASSERT(iez != -1);
bool input_en = false;
if ((ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_0).index] != IdString()) ||
(ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_1).index] != IdString())) {
if ((ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_0).index] != nullptr) ||
(ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_1).index] != nullptr)) {
input_en = true;
}
@ -618,7 +618,7 @@ void write_asc(const Context *ctx, std::ostream &out)
}
// Set config bits in unused IO and RAM
for (auto bel : ctx->getBels()) {
if (ctx->bel_to_cell[bel.index] == IdString() && ctx->getBelType(bel) == TYPE_SB_IO) {
if (ctx->bel_to_cell[bel.index] == nullptr && ctx->getBelType(bel) == TYPE_SB_IO) {
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y, z = beli.z;
@ -633,7 +633,7 @@ void write_asc(const Context *ctx, std::ostream &out)
set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), true);
set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), false);
}
} else if (ctx->bel_to_cell[bel.index] == IdString() && ctx->getBelType(bel) == TYPE_ICESTORM_RAM) {
} else if (ctx->bel_to_cell[bel.index] == nullptr && ctx->getBelType(bel) == TYPE_ICESTORM_RAM) {
const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y;
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB];
@ -751,9 +751,9 @@ void write_asc(const Context *ctx, std::ostream &out)
// Write symbols
// const bool write_symbols = 1;
for (auto wire : ctx->getWires()) {
IdString net = ctx->getBoundWireNet(wire);
if (net != IdString())
out << ".sym " << wire.index << " " << net.str(ctx) << std::endl;
NetInfo *net = ctx->getBoundWireNet(wire);
if (net != nullptr)
out << ".sym " << wire.index << " " << net->name.str(ctx) << std::endl;
}
}
@ -825,7 +825,7 @@ void read_config(Context *ctx, std::istream &in, chipconfig_t &config)
WireId wire;
wire.index = wireIndex;
ctx->bindWire(wire, netName, STRENGTH_WEAK);
ctx->bindWire(wire, ctx->nets.at(netName).get(), STRENGTH_WEAK);
}
} else if (line_nr >= 0 && strlen(buffer) > 0) {
if (line_nr > int(config.at(tile_y).at(tile_x).size() - 1))
@ -869,7 +869,7 @@ bool read_asc(Context *ctx, std::istream &in)
isUsed &= !(bool(cbit) ^ val);
}
if (isUsed) {
IdString net = ctx->wire_to_net[pi.dst];
NetInfo *net = ctx->wire_to_net[pi.dst];
WireId wire;
wire.index = pi.dst;
ctx->unbindWire(wire);
@ -896,7 +896,7 @@ bool read_asc(Context *ctx, std::istream &in)
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
IdString name = created->name;
ctx->cells[name] = std::move(created);
ctx->bindBel(bel, name, STRENGTH_WEAK);
ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets and assign values of properties
}
}
@ -916,7 +916,7 @@ bool read_asc(Context *ctx, std::istream &in)
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
IdString name = created->name;
ctx->cells[name] = std::move(created);
ctx->bindBel(bel, name, STRENGTH_WEAK);
ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets and assign values of properties
}
}
@ -933,35 +933,35 @@ bool read_asc(Context *ctx, std::istream &in)
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
IdString name = created->name;
ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets
}
if (ctx->getBelType(belpin.bel) == TYPE_SB_IO) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
IdString name = created->name;
ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets
}
if (ctx->getBelType(belpin.bel) == TYPE_SB_GB) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_GB"));
IdString name = created->name;
ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets
}
if (ctx->getBelType(belpin.bel) == TYPE_SB_WARMBOOT) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT"));
IdString name = created->name;
ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets
}
if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LFOSC) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"));
IdString name = created->name;
ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets
}
}
@ -975,17 +975,17 @@ bool read_asc(Context *ctx, std::istream &in)
PortPin pin = ctx->portPinFromId(port.first);
WireId wire = ctx->getBelPinWire(cell.second->bel, pin);
if (wire != WireId()) {
IdString name = ctx->getBoundWireNet(wire);
if (name != IdString()) {
port.second.net = ctx->nets[name].get();
NetInfo *net = ctx->getBoundWireNet(wire);
if (net != nullptr) {
port.second.net = net;
PortRef ref;
ref.cell = cell.second.get();
ref.port = port.second.name;
if (port.second.type == PORT_OUT)
ctx->nets[name]->driver = ref;
net->driver = ref;
else
ctx->nets[name]->users.push_back(ref);
net->users.push_back(ref);
}
}
}