aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-02-10 12:28:40 +0000
committergatecat <gatecat@ds0.me>2021-02-10 14:18:12 +0000
commit535723f414a77eb4aa43b794627bbd4aca56f6f0 (patch)
treead130cb32c2b6ff29de73d88d12bdbfe0ed2fd66 /common
parent85bb108ba40f9573571de0a785f9fbc91c4e1dd0 (diff)
downloadnextpnr-535723f414a77eb4aa43b794627bbd4aca56f6f0.tar.gz
nextpnr-535723f414a77eb4aa43b794627bbd4aca56f6f0.tar.bz2
nextpnr-535723f414a77eb4aa43b794627bbd4aca56f6f0.zip
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>
Diffstat (limited to 'common')
-rw-r--r--common/nextpnr.cc92
-rw-r--r--common/nextpnr.h4
-rw-r--r--common/router1.cc10
-rw-r--r--common/router2.cc12
-rw-r--r--common/timing.cc2
5 files changed, 83 insertions, 37 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index 880e0344..11acf991 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -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;
- if (cursor == src_wire)
- return delay + getWireDelay(src_wire).maxDelay();
+ delay += getPipDelay(pip).maxDelay();
+ delay += getWireDelay(cursor).maxDelay();
+ cursor = getPipSrcWire(pip);
+ }
- return predictDelay(net_info, user_info);
+ 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
+ }
+ return max_delay;
}
static uint32_t xorshift32(uint32_t x)
diff --git a/common/nextpnr.h b/common/nextpnr.h
index cf04f831..cb4dbc28 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -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
diff --git a/common/router1.cc b/common/router1.cc
index d2816c1e..51a356bc 100644
--- a/common/router1.cc
+++ b/common/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;
diff --git a/common/router2.cc b/common/router2.cc
index 49d5fdec..d1e4e347 100644
--- a/common/router2.cc
+++ b/common/router2.cc
@@ -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;
diff --git a/common/timing.cc b/common/timing.cc
index 9fb14a33..a741c6ee 100644
--- a/common/timing.cc
+++ b/common/timing.cc
@@ -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)));