mirror of https://github.com/YosysHQ/nextpnr.git
gatemate: removing recursion in GateMateImpl::reassign_bridges (#1697)
* gatemate: removing recursion in GateMateImpl::reassign_bridges * gatemate: improving comments in GateMateImpl:reassign_bridges * gatemate: making naming more consistent, adding comments about the need for recursion removal
This commit is contained in:
parent
a3bccdd33d
commit
e6ecd8fab4
|
|
@ -425,62 +425,77 @@ void GateMateImpl::preRoute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GateMateImpl::reassign_bridges(NetInfo *ni, const dict<WireId, PipMap> &net_wires, WireId wire,
|
void GateMateImpl::reassign_bridges(NetInfo *start_net, const dict<WireId, PipMap> &net_wires,
|
||||||
dict<WireId, IdString> &wire_to_net, int &num)
|
WireId start_wire, dict<WireId, IdString> &wire_to_net, int &num)
|
||||||
{
|
{
|
||||||
wire_to_net.insert({wire, ni->name});
|
// Processing list, holds parameters to implement the equivalent of recursive calls.
|
||||||
|
// This avoids a stack overflow when recursion becomes deep, as the function
|
||||||
|
// has a relatively large stack footprint.
|
||||||
|
struct record { NetInfo *net; WireId wire; };
|
||||||
|
std::vector<record> to_process;
|
||||||
|
// Insert start record.
|
||||||
|
to_process.push_back({start_net, start_wire});
|
||||||
|
// For as long as there are pending records, process them.
|
||||||
|
while (!to_process.empty()) {
|
||||||
|
// Get the next record to process.
|
||||||
|
record cur = to_process.back();
|
||||||
|
to_process.pop_back();
|
||||||
|
|
||||||
for (auto pip : ctx->getPipsDownhill(wire)) {
|
wire_to_net.insert({cur.wire, cur.net->name});
|
||||||
auto dst = ctx->getPipDstWire(pip);
|
|
||||||
|
|
||||||
// Ignore wires not part of the net
|
for (auto pip : ctx->getPipsDownhill(cur.wire)) {
|
||||||
auto it = net_wires.find(dst);
|
auto dst = ctx->getPipDstWire(pip);
|
||||||
if (it == net_wires.end())
|
|
||||||
continue;
|
|
||||||
// Ignore pips if the wire is driven by another pip.
|
|
||||||
if (pip != it->second.pip)
|
|
||||||
continue;
|
|
||||||
// Ignore wires already visited.
|
|
||||||
if (wire_to_net.count(dst))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto &extra_data = *pip_extra_data(pip);
|
// Ignore wires not part of the net
|
||||||
// If not a bridge, just recurse.
|
auto it = net_wires.find(dst);
|
||||||
if (extra_data.type != PipExtra::PIP_EXTRA_MUX || !(extra_data.flags & MUX_ROUTING)) {
|
if (it == net_wires.end())
|
||||||
reassign_bridges(ni, net_wires, dst, wire_to_net, num);
|
continue;
|
||||||
continue;
|
// Ignore pips if the wire is driven by another pip.
|
||||||
|
if (pip != it->second.pip)
|
||||||
|
continue;
|
||||||
|
// Ignore wires already visited.
|
||||||
|
if (wire_to_net.count(dst))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto &extra_data = *pip_extra_data(pip);
|
||||||
|
// If not a bridge, just recurse.
|
||||||
|
if (extra_data.type != PipExtra::PIP_EXTRA_MUX || !(extra_data.flags & MUX_ROUTING)) {
|
||||||
|
// Insert in processing list (recurse).
|
||||||
|
to_process.push_back({cur.net, dst});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have a bridge that needs to be translated to a bel.
|
||||||
|
IdString name = ctx->idf("%s$bridge%d", cur.net->name.c_str(ctx), num);
|
||||||
|
|
||||||
|
IdStringList id = ctx->getPipName(pip);
|
||||||
|
Loc loc = ctx->getPipLocation(pip);
|
||||||
|
BelId bel = ctx->getBelByLocation({loc.x, loc.y, CPE_BRIDGE_Z});
|
||||||
|
CellInfo *cell = ctx->createCell(name, id_CPE_BRIDGE);
|
||||||
|
ctx->bindBel(bel, cell, PlaceStrength::STRENGTH_FIXED);
|
||||||
|
cell->params[id_C_BR] = Property(Property::State::S1, 1);
|
||||||
|
cell->params[id_C_SN] = Property(extra_data.value, 3);
|
||||||
|
|
||||||
|
NetInfo *new_net = ctx->createNet(ctx->idf("%s$muxout", name.c_str(ctx)));
|
||||||
|
IdString in_port = ctx->idf("IN%d", extra_data.value + 1);
|
||||||
|
|
||||||
|
auto add_port = [&](const IdString id, PortType dir) {
|
||||||
|
cell->ports[id].name = id;
|
||||||
|
cell->ports[id].type = dir;
|
||||||
|
cell->cell_bel_pins[id] = std::vector{id};
|
||||||
|
};
|
||||||
|
|
||||||
|
add_port(in_port, PORT_IN);
|
||||||
|
add_port(id_MUXOUT, PORT_OUT);
|
||||||
|
|
||||||
|
cell->connectPort(in_port, cur.net);
|
||||||
|
cell->connectPort(id_MUXOUT, new_net);
|
||||||
|
pass_backtrace[cell->name][id_MUXOUT] = in_port;
|
||||||
|
|
||||||
|
num++;
|
||||||
|
// Insert in processing list (recurse).
|
||||||
|
to_process.push_back({new_net, dst});
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have a bridge that needs to be translated to a bel.
|
|
||||||
IdString name = ctx->idf("%s$bridge%d", ni->name.c_str(ctx), num);
|
|
||||||
|
|
||||||
IdStringList id = ctx->getPipName(pip);
|
|
||||||
Loc loc = ctx->getPipLocation(pip);
|
|
||||||
BelId bel = ctx->getBelByLocation({loc.x, loc.y, CPE_BRIDGE_Z});
|
|
||||||
CellInfo *cell = ctx->createCell(name, id_CPE_BRIDGE);
|
|
||||||
ctx->bindBel(bel, cell, PlaceStrength::STRENGTH_FIXED);
|
|
||||||
cell->params[id_C_BR] = Property(Property::State::S1, 1);
|
|
||||||
cell->params[id_C_SN] = Property(extra_data.value, 3);
|
|
||||||
|
|
||||||
NetInfo *new_net = ctx->createNet(ctx->idf("%s$muxout", name.c_str(ctx)));
|
|
||||||
IdString in_port = ctx->idf("IN%d", extra_data.value + 1);
|
|
||||||
|
|
||||||
auto add_port = [&](const IdString id, PortType dir) {
|
|
||||||
cell->ports[id].name = id;
|
|
||||||
cell->ports[id].type = dir;
|
|
||||||
cell->cell_bel_pins[id] = std::vector{id};
|
|
||||||
};
|
|
||||||
|
|
||||||
add_port(in_port, PORT_IN);
|
|
||||||
add_port(id_MUXOUT, PORT_OUT);
|
|
||||||
|
|
||||||
cell->connectPort(in_port, ni);
|
|
||||||
cell->connectPort(id_MUXOUT, new_net);
|
|
||||||
pass_backtrace[cell->name][id_MUXOUT] = in_port;
|
|
||||||
|
|
||||||
num++;
|
|
||||||
|
|
||||||
reassign_bridges(new_net, net_wires, dst, wire_to_net, num);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ struct GateMateImpl : HimbaechelAPI
|
||||||
void assign_cell_info();
|
void assign_cell_info();
|
||||||
void route_clock();
|
void route_clock();
|
||||||
void route_mult();
|
void route_mult();
|
||||||
void reassign_bridges(NetInfo *net, const dict<WireId, PipMap> &net_wires, WireId wire,
|
void reassign_bridges(NetInfo *start_net, const dict<WireId, PipMap> &net_wires, WireId start_wire,
|
||||||
dict<WireId, IdString> &wire_to_net, int &num);
|
dict<WireId, IdString> &wire_to_net, int &num);
|
||||||
void reassign_cplines(NetInfo *net, const dict<WireId, PipMap> &net_wires, WireId wire,
|
void reassign_cplines(NetInfo *net, const dict<WireId, PipMap> &net_wires, WireId wire,
|
||||||
dict<WireId, IdString> &wire_to_net, int &num, IdString in_port);
|
dict<WireId, IdString> &wire_to_net, int &num, IdString in_port);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue