Start making use of getBelPinsForCellPin API
This replaces getNetinfoSinkWire with 3 new functions for different use cases. At the moment all existing code has been moved to getNetinfoSinkWire with phys_idx=0 so the build doesn't break; but this won't yet function properly with more than one sink. But it provides a base on which to work on refactoring the routers to support this case. Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
85bb108ba4
commit
535723f414
@ -354,19 +354,59 @@ WireId Context::getNetinfoSourceWire(const NetInfo *net_info) const
|
||||
if (src_bel == BelId())
|
||||
return WireId();
|
||||
|
||||
IdString driver_port = net_info->driver.port;
|
||||
return getBelPinWire(src_bel, driver_port);
|
||||
auto bel_pins = getBelPinsForCellPin(net_info->driver.cell, net_info->driver.port);
|
||||
auto iter = bel_pins.begin();
|
||||
if (iter == bel_pins.end())
|
||||
return WireId();
|
||||
WireId driver = getBelPinWire(src_bel, *iter);
|
||||
++iter;
|
||||
NPNR_ASSERT(iter == bel_pins.end()); // assert there is only one driver bel pin;
|
||||
return driver;
|
||||
}
|
||||
|
||||
WireId Context::getNetinfoSinkWire(const NetInfo *net_info, const PortRef &user_info) const
|
||||
SSOArray<WireId, 2> Context::getNetinfoSinkWires(const NetInfo *net_info, const PortRef &user_info) const
|
||||
{
|
||||
auto dst_bel = user_info.cell->bel;
|
||||
|
||||
if (dst_bel == BelId())
|
||||
return WireId();
|
||||
return SSOArray<WireId, 2>(0, WireId());
|
||||
size_t bel_pin_count = 0;
|
||||
// We use an SSOArray here because it avoids any heap allocation for the 99.9% case of 1 or 2 sink wires
|
||||
// but as SSOArray doesn't (currently) support resizing to keep things simple it does mean we have to do
|
||||
// two loops
|
||||
for (auto s : getBelPinsForCellPin(user_info.cell, user_info.port)) {
|
||||
(void)s; // unused
|
||||
++bel_pin_count;
|
||||
}
|
||||
SSOArray<WireId, 2> result(bel_pin_count, WireId());
|
||||
bel_pin_count = 0;
|
||||
for (auto pin : getBelPinsForCellPin(user_info.cell, user_info.port)) {
|
||||
result[bel_pin_count++] = getBelPinWire(dst_bel, pin);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
IdString user_port = user_info.port;
|
||||
return getBelPinWire(dst_bel, user_port);
|
||||
size_t Context::getNetinfoSinkWireCount(const NetInfo *net_info, const PortRef &sink) const
|
||||
{
|
||||
size_t count = 0;
|
||||
for (auto s : getNetinfoSinkWires(net_info, sink)) {
|
||||
(void)s; // unused
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
WireId Context::getNetinfoSinkWire(const NetInfo *net_info, const PortRef &sink, size_t phys_idx) const
|
||||
{
|
||||
size_t count = 0;
|
||||
for (auto s : getNetinfoSinkWires(net_info, sink)) {
|
||||
if (count == phys_idx)
|
||||
return s;
|
||||
++count;
|
||||
}
|
||||
/* TODO: This should be an assertion failure, but for the zero-wire case of unplaced sinks; legacy code currently
|
||||
assumes WireId Remove once the refactoring process is complete.
|
||||
*/
|
||||
return WireId();
|
||||
}
|
||||
|
||||
delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &user_info) const
|
||||
@ -383,29 +423,33 @@ delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &us
|
||||
if (src_wire == WireId())
|
||||
return 0;
|
||||
|
||||
WireId dst_wire = getNetinfoSinkWire(net_info, user_info);
|
||||
WireId cursor = dst_wire;
|
||||
delay_t delay = 0;
|
||||
delay_t max_delay = 0;
|
||||
|
||||
while (cursor != WireId() && cursor != src_wire) {
|
||||
auto it = net_info->wires.find(cursor);
|
||||
for (auto dst_wire : getNetinfoSinkWires(net_info, user_info)) {
|
||||
WireId cursor = dst_wire;
|
||||
delay_t delay = 0;
|
||||
|
||||
if (it == net_info->wires.end())
|
||||
break;
|
||||
while (cursor != WireId() && cursor != src_wire) {
|
||||
auto it = net_info->wires.find(cursor);
|
||||
|
||||
PipId pip = it->second.pip;
|
||||
if (pip == PipId())
|
||||
break;
|
||||
if (it == net_info->wires.end())
|
||||
break;
|
||||
|
||||
delay += getPipDelay(pip).maxDelay();
|
||||
delay += getWireDelay(cursor).maxDelay();
|
||||
cursor = getPipSrcWire(pip);
|
||||
PipId pip = it->second.pip;
|
||||
if (pip == PipId())
|
||||
break;
|
||||
|
||||
delay += getPipDelay(pip).maxDelay();
|
||||
delay += getWireDelay(cursor).maxDelay();
|
||||
cursor = getPipSrcWire(pip);
|
||||
}
|
||||
|
||||
if (cursor == src_wire)
|
||||
max_delay = std::max(max_delay, delay + getWireDelay(src_wire).maxDelay()); // routed
|
||||
else
|
||||
max_delay = std::max(max_delay, predictDelay(net_info, user_info)); // unrouted
|
||||
}
|
||||
|
||||
if (cursor == src_wire)
|
||||
return delay + getWireDelay(src_wire).maxDelay();
|
||||
|
||||
return predictDelay(net_info, user_info);
|
||||
return max_delay;
|
||||
}
|
||||
|
||||
static uint32_t xorshift32(uint32_t x)
|
||||
|
@ -1494,7 +1494,9 @@ struct Context : Arch, DeterministicRNG
|
||||
// --------------------------------------------------------------
|
||||
|
||||
WireId getNetinfoSourceWire(const NetInfo *net_info) const;
|
||||
WireId getNetinfoSinkWire(const NetInfo *net_info, const PortRef &sink) const;
|
||||
SSOArray<WireId, 2> getNetinfoSinkWires(const NetInfo *net_info, const PortRef &sink) const;
|
||||
size_t getNetinfoSinkWireCount(const NetInfo *net_info, const PortRef &sink) const;
|
||||
WireId getNetinfoSinkWire(const NetInfo *net_info, const PortRef &sink, size_t phys_idx) const;
|
||||
delay_t getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &sink) const;
|
||||
|
||||
// provided by router1.cc
|
||||
|
@ -144,7 +144,7 @@ struct Router1
|
||||
int user_idx = arc.user_idx;
|
||||
|
||||
auto src_wire = ctx->getNetinfoSourceWire(net_info);
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx]);
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0);
|
||||
|
||||
arc_queue_insert(arc, src_wire, dst_wire);
|
||||
}
|
||||
@ -302,7 +302,7 @@ struct Router1
|
||||
log_assert(src_wire != WireId());
|
||||
|
||||
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) {
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx]);
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0);
|
||||
log_assert(dst_wire != WireId());
|
||||
|
||||
arc_key arc;
|
||||
@ -375,7 +375,7 @@ struct Router1
|
||||
ctx->nameOf(dst_to_arc.at(src_wire).net_info), dst_to_arc.at(src_wire).user_idx);
|
||||
|
||||
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) {
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx]);
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0);
|
||||
|
||||
if (dst_wire == WireId())
|
||||
log_error("No wire found for port %s on destination cell %s.\n",
|
||||
@ -443,7 +443,7 @@ struct Router1
|
||||
int user_idx = arc.user_idx;
|
||||
|
||||
auto src_wire = ctx->getNetinfoSourceWire(net_info);
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx]);
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0);
|
||||
ripup_flag = false;
|
||||
|
||||
if (ctx->debug) {
|
||||
@ -934,7 +934,7 @@ bool Context::checkRoutedDesign() const
|
||||
|
||||
std::unordered_map<WireId, int> dest_wires;
|
||||
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) {
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx]);
|
||||
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0);
|
||||
log_assert(dst_wire != WireId());
|
||||
dest_wires[dst_wire] = user_idx;
|
||||
|
||||
|
@ -150,7 +150,7 @@ struct Router2
|
||||
|
||||
for (size_t j = 0; j < ni->users.size(); j++) {
|
||||
auto &usr = ni->users.at(j);
|
||||
WireId src_wire = ctx->getNetinfoSourceWire(ni), dst_wire = ctx->getNetinfoSinkWire(ni, usr);
|
||||
WireId src_wire = ctx->getNetinfoSourceWire(ni), dst_wire = ctx->getNetinfoSinkWire(ni, usr, 0);
|
||||
nets.at(i).src_wire = src_wire;
|
||||
if (ni->driver.cell == nullptr)
|
||||
src_wire = dst_wire;
|
||||
@ -405,7 +405,7 @@ struct Router2
|
||||
void reserve_wires_for_arc(NetInfo *net, size_t i)
|
||||
{
|
||||
WireId src = ctx->getNetinfoSourceWire(net);
|
||||
WireId sink = ctx->getNetinfoSinkWire(net, net->users.at(i));
|
||||
WireId sink = ctx->getNetinfoSinkWire(net, net->users.at(i), 0);
|
||||
if (sink == WireId())
|
||||
return;
|
||||
std::unordered_set<WireId> rsv;
|
||||
@ -479,7 +479,7 @@ struct Router2
|
||||
auto &usr = net->users.at(i);
|
||||
ROUTE_LOG_DBG("Routing arc %d of net '%s' (%d, %d) -> (%d, %d)\n", int(i), ctx->nameOf(net), ad.bb.x0, ad.bb.y0,
|
||||
ad.bb.x1, ad.bb.y1);
|
||||
WireId src_wire = ctx->getNetinfoSourceWire(net), dst_wire = ctx->getNetinfoSinkWire(net, usr);
|
||||
WireId src_wire = ctx->getNetinfoSourceWire(net), dst_wire = ctx->getNetinfoSinkWire(net, usr, 0);
|
||||
if (src_wire == WireId())
|
||||
ARC_LOG_ERR("No wire found for port %s on source cell %s.\n", ctx->nameOf(net->driver.port),
|
||||
ctx->nameOf(net->driver.cell));
|
||||
@ -726,7 +726,7 @@ struct Router2
|
||||
if (check_arc_routing(net, i))
|
||||
continue;
|
||||
auto &usr = net->users.at(i);
|
||||
WireId dst_wire = ctx->getNetinfoSinkWire(net, usr);
|
||||
WireId dst_wire = ctx->getNetinfoSinkWire(net, usr, 0);
|
||||
// Case of arcs that were pre-routed strongly (e.g. clocks)
|
||||
if (net->wires.count(dst_wire) && net->wires.at(dst_wire).strength > STRENGTH_STRONG)
|
||||
return ARC_SUCCESS;
|
||||
@ -751,7 +751,7 @@ struct Router2
|
||||
if (res2 != ARC_SUCCESS)
|
||||
log_error("Failed to route arc %d of net '%s', from %s to %s.\n", int(i), ctx->nameOf(net),
|
||||
ctx->nameOfWire(ctx->getNetinfoSourceWire(net)),
|
||||
ctx->nameOfWire(ctx->getNetinfoSinkWire(net, net->users.at(i))));
|
||||
ctx->nameOfWire(ctx->getNetinfoSinkWire(net, net->users.at(i), 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -803,7 +803,7 @@ struct Router2
|
||||
// Skip routes with no source
|
||||
if (src == WireId())
|
||||
return true;
|
||||
WireId dst = ctx->getNetinfoSinkWire(net, usr);
|
||||
WireId dst = ctx->getNetinfoSinkWire(net, usr, 0);
|
||||
// Skip routes where the destination is already bound
|
||||
if (dst == WireId() || ctx->getBoundWireNet(dst) == net)
|
||||
return true;
|
||||
|
@ -869,7 +869,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
|
||||
log_info(" Sink %s.%s\n", sink_cell->name.c_str(ctx), sink->port.c_str(ctx));
|
||||
if (ctx->verbose) {
|
||||
auto driver_wire = ctx->getNetinfoSourceWire(net);
|
||||
auto sink_wire = ctx->getNetinfoSinkWire(net, *sink);
|
||||
auto sink_wire = ctx->getNetinfoSinkWire(net, *sink, 0);
|
||||
log_info(" prediction: %f ns estimate: %f ns\n",
|
||||
ctx->getDelayNS(ctx->predictDelay(net, *sink)),
|
||||
ctx->getDelayNS(ctx->estimateDelay(driver_wire, sink_wire)));
|
||||
|
@ -53,7 +53,7 @@ struct NexusGlobalRouter
|
||||
|
||||
// Lookup source and destination wires
|
||||
WireId src = ctx->getNetinfoSourceWire(net);
|
||||
WireId dst = ctx->getNetinfoSinkWire(net, net->users.at(user_idx));
|
||||
WireId dst = ctx->getNetinfoSinkWire(net, net->users.at(user_idx), 0);
|
||||
|
||||
if (src == WireId())
|
||||
log_error("Net '%s' has an invalid source port %s.%s\n", ctx->nameOf(net), ctx->nameOf(net->driver.cell),
|
||||
|
Loading…
Reference in New Issue
Block a user