aboutsummaryrefslogtreecommitdiffstats
path: root/fpga_interchange/dedicated_interconnect.cc
diff options
context:
space:
mode:
authorKeith Rothman <537074+litghost@users.noreply.github.com>2021-02-23 13:35:45 -0800
committerKeith Rothman <537074+litghost@users.noreply.github.com>2021-02-23 14:09:28 -0800
commita30043c8da1b1cc46a2dcfb90aa3a06d4f4ed4e9 (patch)
tree7d9558216c7b9858bd31323ff3482b50e9d5c05f /fpga_interchange/dedicated_interconnect.cc
parent184665652eaf351bf9337b524c5d82a50ce54041 (diff)
downloadnextpnr-a30043c8da1b1cc46a2dcfb90aa3a06d4f4ed4e9.tar.gz
nextpnr-a30043c8da1b1cc46a2dcfb90aa3a06d4f4ed4e9.tar.bz2
nextpnr-a30043c8da1b1cc46a2dcfb90aa3a06d4f4ed4e9.zip
Fix assorted bugs in FPGA interchange.
Fixes: - Only use map constant pins during routing, and not during placement. - Unmapped cell ports have no BEL pins. - Fix SiteRouter congestion not taking into account initial expansion. - Fix psuedo-site pip output. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
Diffstat (limited to 'fpga_interchange/dedicated_interconnect.cc')
-rw-r--r--fpga_interchange/dedicated_interconnect.cc524
1 files changed, 260 insertions, 264 deletions
diff --git a/fpga_interchange/dedicated_interconnect.cc b/fpga_interchange/dedicated_interconnect.cc
index b9ef93b5..820896a3 100644
--- a/fpga_interchange/dedicated_interconnect.cc
+++ b/fpga_interchange/dedicated_interconnect.cc
@@ -18,8 +18,8 @@
*
*/
-#include "nextpnr.h"
#include "log.h"
+#include "nextpnr.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN
@@ -32,13 +32,15 @@ NEXTPNR_NAMESPACE_BEGIN
// terminate at another site. Routing that "flys" over a site is expressed as
// a psuedo-pip connected the relevant site pin wires, rather than traversing
// the site.
-enum WireNodeState {
+enum WireNodeState
+{
IN_SINK_SITE = 0,
IN_ROUTING = 1,
IN_SOURCE_SITE = 2
};
-struct WireNode {
+struct WireNode
+{
WireId wire;
WireNodeState state;
int depth;
@@ -50,32 +52,33 @@ struct WireNode {
// interconnect.
constexpr int kMaxDepth = 20;
-void DedicatedInterconnect::init(const Context *ctx) {
+void DedicatedInterconnect::init(const Context *ctx)
+{
this->ctx = ctx;
- if(ctx->debug) {
+ if (ctx->debug) {
log_info("Finding dedicated interconnect!\n");
}
find_dedicated_interconnect();
- if(ctx->debug) {
+ if (ctx->debug) {
print_dedicated_interconnect();
}
}
-bool DedicatedInterconnect::check_routing(
- BelId src_bel, IdString src_bel_pin,
- BelId dst_bel, IdString dst_bel_pin) const {
+bool DedicatedInterconnect::check_routing(BelId src_bel, IdString src_bel_pin, BelId dst_bel,
+ IdString dst_bel_pin) const
+{
std::vector<WireNode> nodes_to_expand;
WireId src_wire = ctx->getBelPinWire(src_bel, src_bel_pin);
- const auto & src_wire_data = ctx->wire_info(src_wire);
+ const auto &src_wire_data = ctx->wire_info(src_wire);
NPNR_ASSERT(src_wire_data.site != -1);
WireId dst_wire = ctx->getBelPinWire(dst_bel, dst_bel_pin);
- const auto & dst_wire_data = ctx->wire_info(dst_wire);
+ const auto &dst_wire_data = ctx->wire_info(dst_wire);
NPNR_ASSERT(dst_wire_data.site != -1);
WireNode wire_node;
@@ -85,30 +88,29 @@ bool DedicatedInterconnect::check_routing(
nodes_to_expand.push_back(wire_node);
- while(!nodes_to_expand.empty()) {
+ while (!nodes_to_expand.empty()) {
WireNode node_to_expand = nodes_to_expand.back();
nodes_to_expand.pop_back();
- for(PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) {
- if(ctx->is_pip_synthetic(pip)) {
+ for (PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) {
+ if (ctx->is_pip_synthetic(pip)) {
continue;
}
WireId wire = ctx->getPipDstWire(pip);
- if(wire == WireId()) {
+ if (wire == WireId()) {
continue;
}
#ifdef DEBUG_EXPANSION
- log_info(" - At wire %s via %s\n",
- ctx->nameOfWire(wire), ctx->nameOfPip(pip));
+ log_info(" - At wire %s via %s\n", ctx->nameOfWire(wire), ctx->nameOfPip(pip));
#endif
WireNode next_node;
next_node.wire = wire;
next_node.depth = node_to_expand.depth += 1;
- if(next_node.depth > kMaxDepth) {
+ if (next_node.depth > kMaxDepth) {
// Dedicated routing should reach sources by kMaxDepth (with
// tuning).
//
@@ -116,55 +118,52 @@ bool DedicatedInterconnect::check_routing(
return false;
}
- auto const & wire_data = ctx->wire_info(wire);
+ auto const &wire_data = ctx->wire_info(wire);
bool expand_node = true;
- if(ctx->is_site_port(pip)) {
- switch(node_to_expand.state) {
- case IN_SOURCE_SITE:
- NPNR_ASSERT(wire_data.site == -1);
- next_node.state = IN_ROUTING;
- break;
- case IN_ROUTING:
- NPNR_ASSERT(wire_data.site != -1);
- if(wire.tile == src_wire.tile && wire_data.site == src_wire_data.site) {
- // Dedicated routing won't have straight loops,
- // general routing looks like that.
+ if (ctx->is_site_port(pip)) {
+ switch (node_to_expand.state) {
+ case IN_SOURCE_SITE:
+ NPNR_ASSERT(wire_data.site == -1);
+ next_node.state = IN_ROUTING;
+ break;
+ case IN_ROUTING:
+ NPNR_ASSERT(wire_data.site != -1);
+ if (wire.tile == src_wire.tile && wire_data.site == src_wire_data.site) {
+ // Dedicated routing won't have straight loops,
+ // general routing looks like that.
#ifdef DEBUG_EXPANSION
- log_info(" - Not dedicated site routing because loop!");
+ log_info(" - Not dedicated site routing because loop!");
#endif
- return false;
- }
- next_node.state = IN_SINK_SITE;
- break;
- case IN_SINK_SITE:
- // Once entering a site, do not leave it again.
- // This path is not a legal route!
- expand_node = false;
- break;
- default:
- // Unreachable!!!
- NPNR_ASSERT(false);
+ return false;
+ }
+ next_node.state = IN_SINK_SITE;
+ break;
+ case IN_SINK_SITE:
+ // Once entering a site, do not leave it again.
+ // This path is not a legal route!
+ expand_node = false;
+ break;
+ default:
+ // Unreachable!!!
+ NPNR_ASSERT(false);
}
} else {
next_node.state = node_to_expand.state;
}
- if(expand_node) {
+ if (expand_node) {
nodes_to_expand.push_back(next_node);
} else {
continue;
}
- if(next_node.state == IN_SINK_SITE) {
- for(BelPin bel_pin : ctx->getWireBelPins(wire)) {
- if(bel_pin.bel == dst_bel && bel_pin.pin == dst_bel_pin) {
- if(ctx->verbose) {
- log_info("Valid dedicated interconnect from %s/%s to %s/%s\n",
- ctx->nameOfBel(src_bel),
- src_bel_pin.c_str(ctx),
- ctx->nameOfBel(dst_bel),
- dst_bel_pin.c_str(ctx));
+ if (next_node.state == IN_SINK_SITE) {
+ for (BelPin bel_pin : ctx->getWireBelPins(wire)) {
+ if (bel_pin.bel == dst_bel && bel_pin.pin == dst_bel_pin) {
+ if (ctx->debug) {
+ log_info("Valid dedicated interconnect from %s/%s to %s/%s\n", ctx->nameOfBel(src_bel),
+ src_bel_pin.c_str(ctx), ctx->nameOfBel(dst_bel), dst_bel_pin.c_str(ctx));
}
return true;
}
@@ -176,8 +175,9 @@ bool DedicatedInterconnect::check_routing(
return false;
}
-bool DedicatedInterconnect::is_driver_on_net_valid(BelId driver_bel,
- const CellInfo* cell, IdString driver_port, NetInfo *net) const {
+bool DedicatedInterconnect::is_driver_on_net_valid(BelId driver_bel, const CellInfo *cell, IdString driver_port,
+ NetInfo *net) const
+{
const auto &driver_bel_data = bel_info(ctx->chip_info, driver_bel);
TileTypeBelPin type_bel_pin;
@@ -186,27 +186,34 @@ bool DedicatedInterconnect::is_driver_on_net_valid(BelId driver_bel,
Loc driver_loc = ctx->getBelLocation(driver_bel);
- for(IdString driver_bel_pin : ctx->getBelPinsForCellPin(cell, driver_port)) {
+ for (IdString driver_bel_pin : ctx->getBelPinsForCellPin(cell, driver_port)) {
type_bel_pin.bel_pin = driver_bel_pin;
auto iter = sources.find(type_bel_pin);
- if(iter == sources.end()) {
+ if (iter == sources.end()) {
// This BEL pin doesn't have a dedicate interconnect.
continue;
}
- for(const PortRef & port_ref : net->users) {
+ for (const PortRef &port_ref : net->users) {
NPNR_ASSERT(port_ref.cell != nullptr);
- if(port_ref.cell->bel == BelId()) {
- return true;
+ if (port_ref.cell->bel == BelId()) {
+ // FIXME: This should actually return "unknown!" because the
+ // sink is unplaced. Once the sink is placed, this constraint
+ // can be evaluated.
+ if (ctx->debug) {
+ log_info("BEL %s is not valid because sink cell %s/%s is not placed\n", ctx->nameOfBel(driver_bel),
+ port_ref.cell->name.c_str(ctx), port_ref.port.c_str(ctx));
+ }
+ return false;
}
BelId sink_bel = port_ref.cell->bel;
const auto &sink_bel_data = bel_info(ctx->chip_info, sink_bel);
Loc sink_loc = ctx->getBelLocation(port_ref.cell->bel);
- if(sink_bel.tile == driver_bel.tile && sink_bel_data.site == driver_bel_data.site) {
+ if (sink_bel.tile == driver_bel.tile && sink_bel_data.site == driver_bel_data.site) {
// This is a site local routing, even though this is a sink
// with a dedicated interconnect.
continue;
@@ -218,18 +225,15 @@ bool DedicatedInterconnect::is_driver_on_net_valid(BelId driver_bel,
sink_type_bel_pin.type_bel_pin.tile_type = ctx->chip_info->tiles[sink_bel.tile].type;
sink_type_bel_pin.type_bel_pin.bel_index = sink_bel.index;
- for(IdString sink_bel_pin : ctx->getBelPinsForCellPin(port_ref.cell, port_ref.port)) {
+ for (IdString sink_bel_pin : ctx->getBelPinsForCellPin(port_ref.cell, port_ref.port)) {
sink_type_bel_pin.type_bel_pin.bel_pin = sink_bel_pin;
// Do fast routing check to see if the pair of driver and sink
// every are valid.
- if(iter->second.count(sink_type_bel_pin) == 0) {
- if(ctx->verbose) {
- log_info("BEL %s is not valid because pin %s cannot reach %s/%s\n",
- ctx->nameOfBel(driver_bel),
- driver_bel_pin.c_str(ctx),
- ctx->nameOfBel(sink_bel),
- sink_bel_pin.c_str(ctx));
+ if (iter->second.count(sink_type_bel_pin) == 0) {
+ if (ctx->debug) {
+ log_info("BEL %s is not valid because pin %s cannot reach %s/%s\n", ctx->nameOfBel(driver_bel),
+ driver_bel_pin.c_str(ctx), ctx->nameOfBel(sink_bel), sink_bel_pin.c_str(ctx));
}
return false;
}
@@ -239,15 +243,11 @@ bool DedicatedInterconnect::is_driver_on_net_valid(BelId driver_bel,
// FIXME: This might be too slow, but it handles a case on
// SLICEL.COUT -> SLICEL.CIN has delta_y = {1, 2}, but the
// delta_y=2 case is rare.
- if(!check_routing(
- driver_bel, driver_bel_pin,
- sink_bel, sink_bel_pin)) {
- if(ctx->verbose) {
+ if (!check_routing(driver_bel, driver_bel_pin, sink_bel, sink_bel_pin)) {
+ if (ctx->debug) {
log_info("BEL %s is not valid because pin %s cannot be reach %s/%s (via detailed check)\n",
- ctx->nameOfBel(driver_bel),
- driver_bel_pin.c_str(ctx),
- ctx->nameOfBel(sink_bel),
- sink_bel_pin.c_str(ctx));
+ ctx->nameOfBel(driver_bel), driver_bel_pin.c_str(ctx), ctx->nameOfBel(sink_bel),
+ sink_bel_pin.c_str(ctx));
}
return false;
}
@@ -258,52 +258,62 @@ bool DedicatedInterconnect::is_driver_on_net_valid(BelId driver_bel,
return true;
}
-bool DedicatedInterconnect::is_sink_on_net_valid(BelId bel, const CellInfo* cell, IdString port_name, NetInfo *net) const {
- BelId driver_bel = net->driver.cell->bel;
- if(driver_bel == BelId()) {
- return true;
- }
-
+bool DedicatedInterconnect::is_sink_on_net_valid(BelId bel, const CellInfo *cell, IdString port_name,
+ NetInfo *net) const
+{
const auto &bel_data = bel_info(ctx->chip_info, bel);
- const auto &driver_bel_data = bel_info(ctx->chip_info, driver_bel);
-
Loc bel_loc = ctx->getBelLocation(bel);
- Loc driver_loc = ctx->getBelLocation(driver_bel);
- DeltaTileTypeBelPin driver_type_bel_pin;
- driver_type_bel_pin.delta_x = driver_loc.x - bel_loc.x;
- driver_type_bel_pin.delta_y = driver_loc.y - bel_loc.y;
- driver_type_bel_pin.type_bel_pin.tile_type = ctx->chip_info->tiles[driver_bel.tile].type;
- driver_type_bel_pin.type_bel_pin.bel_index = driver_bel.index;
- driver_type_bel_pin.type_bel_pin.bel_pin = get_only_value(ctx->getBelPinsForCellPin(net->driver.cell, net->driver.port));
+ BelId driver_bel = net->driver.cell->bel;
- for(IdString bel_pin : ctx->getBelPinsForCellPin(cell, port_name)) {
+ for (IdString bel_pin : ctx->getBelPinsForCellPin(cell, port_name)) {
TileTypeBelPin type_bel_pin;
type_bel_pin.tile_type = ctx->chip_info->tiles[bel.tile].type;
type_bel_pin.bel_index = bel.index;
type_bel_pin.bel_pin = bel_pin;
auto iter = sinks.find(type_bel_pin);
- if(iter == sinks.end()) {
+ if (iter == sinks.end()) {
// This BEL pin doesn't have a dedicate interconnect.
continue;
}
- if(bel.tile == driver_bel.tile && bel_data.site == driver_bel_data.site) {
+ if (driver_bel == BelId()) {
+ // FIXME: This should actually return "unknown!" because the
+ // driver is unplaced. Once the driver is placed, this constraint
+ // can be evaluated.
+ if (ctx->debug) {
+ log_info("BEL %s is not valid because driver cell %s/%s is not placed\n", ctx->nameOfBel(bel),
+ net->driver.cell->name.c_str(ctx), net->driver.port.c_str(ctx));
+ }
+ return false;
+ }
+
+ const auto &driver_bel_data = bel_info(ctx->chip_info, driver_bel);
+
+ if (bel.tile == driver_bel.tile && bel_data.site == driver_bel_data.site) {
// This is a site local routing, even though this is a sink
// with a dedicated interconnect.
continue;
}
+ Loc driver_loc = ctx->getBelLocation(driver_bel);
+
+ DeltaTileTypeBelPin driver_type_bel_pin;
+ driver_type_bel_pin.delta_x = driver_loc.x - bel_loc.x;
+ driver_type_bel_pin.delta_y = driver_loc.y - bel_loc.y;
+ driver_type_bel_pin.type_bel_pin.tile_type = ctx->chip_info->tiles[driver_bel.tile].type;
+ driver_type_bel_pin.type_bel_pin.bel_index = driver_bel.index;
+ driver_type_bel_pin.type_bel_pin.bel_pin =
+ get_only_value(ctx->getBelPinsForCellPin(net->driver.cell, net->driver.port));
+
// Do fast routing check to see if the pair of driver and sink
// every are valid.
- if(iter->second.count(driver_type_bel_pin) == 0) {
- if(ctx->verbose) {
- log_info("BEL %s is not valid because pin %s cannot be driven by %s/%s\n",
- ctx->nameOfBel(bel),
- bel_pin.c_str(ctx),
- ctx->nameOfBel(driver_bel),
- driver_type_bel_pin.type_bel_pin.bel_pin.c_str(ctx));
+ if (iter->second.count(driver_type_bel_pin) == 0) {
+ if (ctx->debug) {
+ log_info("BEL %s is not valid because pin %s cannot be driven by %s/%s\n", ctx->nameOfBel(bel),
+ bel_pin.c_str(ctx), ctx->nameOfBel(driver_bel),
+ driver_type_bel_pin.type_bel_pin.bel_pin.c_str(ctx));
}
return false;
}
@@ -313,15 +323,11 @@ bool DedicatedInterconnect::is_sink_on_net_valid(BelId bel, const CellInfo* cell
// FIXME: This might be too slow, but it handles a case on
// SLICEL.COUT -> SLICEL.CIN has delta_y = {1, 2}, but the
// delta_y=2 case is rare.
- if(!check_routing(
- driver_bel, driver_type_bel_pin.type_bel_pin.bel_pin,
- bel, bel_pin)) {
- if(ctx->verbose) {
+ if (!check_routing(driver_bel, driver_type_bel_pin.type_bel_pin.bel_pin, bel, bel_pin)) {
+ if (ctx->debug) {
log_info("BEL %s is not valid because pin %s cannot be driven by %s/%s (via detailed check)\n",
- ctx->nameOfBel(bel),
- bel_pin.c_str(ctx),
- ctx->nameOfBel(driver_bel),
- driver_type_bel_pin.type_bel_pin.bel_pin.c_str(ctx));
+ ctx->nameOfBel(bel), bel_pin.c_str(ctx), ctx->nameOfBel(driver_bel),
+ driver_type_bel_pin.type_bel_pin.bel_pin.c_str(ctx));
}
return false;
}
@@ -330,13 +336,14 @@ bool DedicatedInterconnect::is_sink_on_net_valid(BelId bel, const CellInfo* cell
return true;
}
-bool DedicatedInterconnect::isBelLocationValid(BelId bel, const CellInfo* cell) const {
+bool DedicatedInterconnect::isBelLocationValid(BelId bel, const CellInfo *cell) const
+{
NPNR_ASSERT(bel != BelId());
- for(const auto &port_pair : cell->ports) {
+ for (const auto &port_pair : cell->ports) {
IdString port_name = port_pair.first;
NetInfo *net = port_pair.second.net;
- if(net == nullptr) {
+ if (net == nullptr) {
continue;
}
@@ -344,12 +351,12 @@ bool DedicatedInterconnect::isBelLocationValid(BelId bel, const CellInfo* cell)
NPNR_ASSERT(net->driver.cell != nullptr);
// Only check sink BELs.
- if(net->driver.cell == cell && net->driver.port == port_name) {
- if(!is_driver_on_net_valid(bel, cell, port_name, net)) {
+ if (net->driver.cell == cell && net->driver.port == port_name) {
+ if (!is_driver_on_net_valid(bel, cell, port_name, net)) {
return false;
}
} else {
- if(!is_sink_on_net_valid(bel, cell, port_name, net)) {
+ if (!is_sink_on_net_valid(bel, cell, port_name, net)) {
return false;
}
}
@@ -358,100 +365,84 @@ bool DedicatedInterconnect::isBelLocationValid(BelId bel, const CellInfo* cell)
return true;
}
-void DedicatedInterconnect::print_dedicated_interconnect() const {
+void DedicatedInterconnect::print_dedicated_interconnect() const
+{
log_info("Found %zu sinks with dedicated interconnect\n", sinks.size());
log_info("Found %zu sources with dedicated interconnect\n", sources.size());
std::vector<TileTypeBelPin> sorted_keys;
- for(const auto & sink_to_srcs : sinks) {
+ for (const auto &sink_to_srcs : sinks) {
sorted_keys.push_back(sink_to_srcs.first);
}
- for(const auto & src_to_sinks : sources) {
+ for (const auto &src_to_sinks : sources) {
sorted_keys.push_back(src_to_sinks.first);
}
std::sort(sorted_keys.begin(), sorted_keys.end());
- for(const auto & key : sorted_keys) {
+ for (const auto &key : sorted_keys) {
auto iter = sinks.find(key);
- if(iter != sinks.end()) {
+ if (iter != sinks.end()) {
auto dst = key;
- for(const auto & src_delta : iter->second) {
+ for (const auto &src_delta : iter->second) {
auto src = src_delta.type_bel_pin;
auto delta_x = src_delta.delta_x;
auto delta_y = src_delta.delta_y;
- const TileTypeInfoPOD & src_tile_type = ctx->chip_info->tile_types[src.tile_type];
- const BelInfoPOD & src_bel_info = src_tile_type.bel_data[src.bel_index];
+ const TileTypeInfoPOD &src_tile_type = ctx->chip_info->tile_types[src.tile_type];
+ const BelInfoPOD &src_bel_info = src_tile_type.bel_data[src.bel_index];
IdString src_site_type = IdString(src_tile_type.site_types[src_bel_info.site]);
IdString src_bel_pin = src.bel_pin;
- const TileTypeInfoPOD & dst_tile_type = ctx->chip_info->tile_types[dst.tile_type];
- const BelInfoPOD & dst_bel_info = dst_tile_type.bel_data[dst.bel_index];
+ const TileTypeInfoPOD &dst_tile_type = ctx->chip_info->tile_types[dst.tile_type];
+ const BelInfoPOD &dst_bel_info = dst_tile_type.bel_data[dst.bel_index];
IdString dst_site_type = IdString(dst_tile_type.site_types[dst_bel_info.site]);
IdString dst_bel_pin = dst.bel_pin;
- log_info("%s.%s[%d]/%s/%s (%d, %d) -> %s.%s[%d]/%s/%s\n",
- IdString(src_tile_type.name).c_str(ctx),
- src_site_type.c_str(ctx),
- src_bel_info.site,
- IdString(src_bel_info.name).c_str(ctx),
- src_bel_pin.c_str(ctx),
- delta_x,
- delta_y,
- IdString(dst_tile_type.name).c_str(ctx),
- dst_site_type.c_str(ctx),
- dst_bel_info.site,
- IdString(dst_bel_info.name).c_str(ctx),
- dst_bel_pin.c_str(ctx));
-
+ log_info("%s.%s[%d]/%s/%s (%d, %d) -> %s.%s[%d]/%s/%s\n", IdString(src_tile_type.name).c_str(ctx),
+ src_site_type.c_str(ctx), src_bel_info.site, IdString(src_bel_info.name).c_str(ctx),
+ src_bel_pin.c_str(ctx), delta_x, delta_y, IdString(dst_tile_type.name).c_str(ctx),
+ dst_site_type.c_str(ctx), dst_bel_info.site, IdString(dst_bel_info.name).c_str(ctx),
+ dst_bel_pin.c_str(ctx));
}
} else {
auto src = key;
- for(const auto & dst_delta : sources.at(key)) {
+ for (const auto &dst_delta : sources.at(key)) {
auto dst = dst_delta.type_bel_pin;
auto delta_x = dst_delta.delta_x;
auto delta_y = dst_delta.delta_y;
- const TileTypeInfoPOD & src_tile_type = ctx->chip_info->tile_types[src.tile_type];
- const BelInfoPOD & src_bel_info = src_tile_type.bel_data[src.bel_index];
+ const TileTypeInfoPOD &src_tile_type = ctx->chip_info->tile_types[src.tile_type];
+ const BelInfoPOD &src_bel_info = src_tile_type.bel_data[src.bel_index];
IdString src_site_type = IdString(src_tile_type.site_types[src_bel_info.site]);
IdString src_bel_pin = src.bel_pin;
- const TileTypeInfoPOD & dst_tile_type = ctx->chip_info->tile_types[dst.tile_type];
- const BelInfoPOD & dst_bel_info = dst_tile_type.bel_data[dst.bel_index];
+ const TileTypeInfoPOD &dst_tile_type = ctx->chip_info->tile_types[dst.tile_type];
+ const BelInfoPOD &dst_bel_info = dst_tile_type.bel_data[dst.bel_index];
IdString dst_site_type = IdString(dst_tile_type.site_types[dst_bel_info.site]);
IdString dst_bel_pin = dst.bel_pin;
- log_info("%s.%s[%d]/%s/%s -> %s.%s[%d]/%s/%s (%d, %d)\n",
- IdString(src_tile_type.name).c_str(ctx),
- src_site_type.c_str(ctx),
- src_bel_info.site,
- IdString(src_bel_info.name).c_str(ctx),
- src_bel_pin.c_str(ctx),
- IdString(dst_tile_type.name).c_str(ctx),
- dst_site_type.c_str(ctx),
- dst_bel_info.site,
- IdString(dst_bel_info.name).c_str(ctx),
- dst_bel_pin.c_str(ctx),
- delta_x,
- delta_y);
-
+ log_info("%s.%s[%d]/%s/%s -> %s.%s[%d]/%s/%s (%d, %d)\n", IdString(src_tile_type.name).c_str(ctx),
+ src_site_type.c_str(ctx), src_bel_info.site, IdString(src_bel_info.name).c_str(ctx),
+ src_bel_pin.c_str(ctx), IdString(dst_tile_type.name).c_str(ctx), dst_site_type.c_str(ctx),
+ dst_bel_info.site, IdString(dst_bel_info.name).c_str(ctx), dst_bel_pin.c_str(ctx), delta_x,
+ delta_y);
}
}
}
}
-void DedicatedInterconnect::find_dedicated_interconnect() {
- for(BelId bel : ctx->getBels()) {
- const auto & bel_data = bel_info(ctx->chip_info, bel);
- if(bel_data.category != BEL_CATEGORY_LOGIC) {
+void DedicatedInterconnect::find_dedicated_interconnect()
+{
+ for (BelId bel : ctx->getBels()) {
+ const auto &bel_data = bel_info(ctx->chip_info, bel);
+ if (bel_data.category != BEL_CATEGORY_LOGIC) {
continue;
}
- if(bel_data.synthetic) {
+ if (bel_data.synthetic) {
continue;
}
- for(size_t i = 0; i < bel_data.num_bel_wires; ++i) {
- if(bel_data.types[i] != PORT_IN) {
+ for (size_t i = 0; i < bel_data.num_bel_wires; ++i) {
+ if (bel_data.types[i] != PORT_IN) {
continue;
}
@@ -464,27 +455,26 @@ void DedicatedInterconnect::find_dedicated_interconnect() {
}
std::unordered_set<TileTypeBelPin> seen_pins;
- for(auto sink_pair : sinks) {
- for(auto src : sink_pair.second) {
+ for (auto sink_pair : sinks) {
+ for (auto src : sink_pair.second) {
seen_pins.emplace(src.type_bel_pin);
}
}
- for(BelId bel : ctx->getBels()) {
- const auto & bel_data = bel_info(ctx->chip_info, bel);
- if(bel_data.category != BEL_CATEGORY_LOGIC) {
+ for (BelId bel : ctx->getBels()) {
+ const auto &bel_data = bel_info(ctx->chip_info, bel);
+ if (bel_data.category != BEL_CATEGORY_LOGIC) {
continue;
}
- if(bel_data.synthetic) {
+ if (bel_data.synthetic) {
continue;
}
- for(size_t i = 0; i < bel_data.num_bel_wires; ++i) {
- if(bel_data.types[i] != PORT_OUT) {
+ for (size_t i = 0; i < bel_data.num_bel_wires; ++i) {
+ if (bel_data.types[i] != PORT_OUT) {
continue;
}
-
IdString bel_pin(bel_data.ports[i]);
TileTypeBelPin type_bel_pin;
@@ -493,7 +483,7 @@ void DedicatedInterconnect::find_dedicated_interconnect() {
type_bel_pin.bel_pin = bel_pin;
// Don't visit src pins already handled in the sink expansion!
- if(seen_pins.count(type_bel_pin)) {
+ if (seen_pins.count(type_bel_pin)) {
continue;
}
@@ -506,7 +496,8 @@ void DedicatedInterconnect::find_dedicated_interconnect() {
}
}
-void DedicatedInterconnect::expand_sink_bel(BelId sink_bel, IdString sink_pin, WireId sink_wire) {
+void DedicatedInterconnect::expand_sink_bel(BelId sink_bel, IdString sink_pin, WireId sink_wire)
+{
NPNR_ASSERT(sink_bel != BelId());
#ifdef DEBUG_EXPANSION
log_info("Expanding from %s/%s\n", ctx->nameOfBel(sink_bel), pin.c_str(ctx));
@@ -514,7 +505,7 @@ void DedicatedInterconnect::expand_sink_bel(BelId sink_bel, IdString sink_pin, W
std::vector<WireNode> nodes_to_expand;
- const auto & sink_wire_data = ctx->wire_info(sink_wire);
+ const auto &sink_wire_data = ctx->wire_info(sink_wire);
NPNR_ASSERT(sink_wire_data.site != -1);
WireNode wire_node;
@@ -527,89 +518,91 @@ void DedicatedInterconnect::expand_sink_bel(BelId sink_bel, IdString sink_pin, W
Loc sink_loc = ctx->getBelLocation(sink_bel);
std::unordered_set<DeltaTileTypeBelPin> srcs;
- while(!nodes_to_expand.empty()) {
+ while (!nodes_to_expand.empty()) {
WireNode node_to_expand = nodes_to_expand.back();
nodes_to_expand.pop_back();
- for(PipId pip : ctx->getPipsUphill(node_to_expand.wire)) {
- if(ctx->is_pip_synthetic(pip)) {
+ for (PipId pip : ctx->getPipsUphill(node_to_expand.wire)) {
+ if (ctx->is_pip_synthetic(pip)) {
continue;
}
WireId wire = ctx->getPipSrcWire(pip);
- if(wire == WireId()) {
+ if (wire == WireId()) {
continue;
}
#ifdef DEBUG_EXPANSION
- log_info(" - At wire %s via %s\n",
- ctx->nameOfWire(wire), ctx->nameOfPip(pip));
+ log_info(" - At wire %s via %s\n", ctx->nameOfWire(wire), ctx->nameOfPip(pip));
#endif
WireNode next_node;
next_node.wire = wire;
next_node.depth = node_to_expand.depth += 1;
- if(next_node.depth > kMaxDepth) {
+ if (next_node.depth > kMaxDepth) {
// Dedicated routing should reach sources by kMaxDepth (with
// tuning).
//
// FIXME: Consider removing kMaxDepth and use kMaxSources?
+#ifdef DEBUG_EXPANSION
+ log_info(" - Exceeded max depth!\n");
+#endif
return;
}
- auto const & wire_data = ctx->wire_info(wire);
+ auto const &wire_data = ctx->wire_info(wire);
bool expand_node = true;
- if(ctx->is_site_port(pip)) {
- switch(node_to_expand.state) {
- case IN_SINK_SITE:
- NPNR_ASSERT(wire_data.site == -1);
- next_node.state = IN_ROUTING;
- break;
- case IN_ROUTING:
- NPNR_ASSERT(wire_data.site != -1);
- if(wire.tile == sink_wire.tile && wire_data.site == sink_wire_data.site) {
- // Dedicated routing won't have straight loops,
- // general routing looks like that.
+ if (ctx->is_site_port(pip)) {
+ switch (node_to_expand.state) {
+ case IN_SINK_SITE:
+ NPNR_ASSERT(wire_data.site == -1);
+ next_node.state = IN_ROUTING;
+ break;
+ case IN_ROUTING:
+ NPNR_ASSERT(wire_data.site != -1);
+ if (wire.tile == sink_wire.tile && wire_data.site == sink_wire_data.site) {
+ // Dedicated routing won't have straight loops,
+ // general routing looks like that.
#ifdef DEBUG_EXPANSION
- log_info(" - Not dedicated site routing because loop!");
+ log_info(" - Not dedicated site routing because loop!");
#endif
- return;
- }
- next_node.state = IN_SOURCE_SITE;
- break;
- case IN_SOURCE_SITE:
- // Once entering a site, do not leave it again.
- // This path is not a legal route!
- expand_node = false;
- break;
- default:
- // Unreachable!!!
- NPNR_ASSERT(false);
+ return;
+ }
+ next_node.state = IN_SOURCE_SITE;
+ break;
+ case IN_SOURCE_SITE:
+ // Once entering a site, do not leave it again.
+ // This path is not a legal route!
+ expand_node = false;
+ break;
+ default:
+ // Unreachable!!!
+ NPNR_ASSERT(false);
}
} else {
next_node.state = node_to_expand.state;
}
- if(expand_node) {
+ if (expand_node) {
nodes_to_expand.push_back(next_node);
} else {
continue;
}
- if(next_node.state == IN_SOURCE_SITE) {
- for(BelPin bel_pin : ctx->getWireBelPins(wire)) {
+ if (next_node.state == IN_SOURCE_SITE) {
+ for (BelPin bel_pin : ctx->getWireBelPins(wire)) {
BelId src_bel = bel_pin.bel;
- auto const & bel_data = bel_info(ctx->chip_info, src_bel);
+ auto const &bel_data = bel_info(ctx->chip_info, src_bel);
- if(bel_data.category != BEL_CATEGORY_LOGIC) {
+ if (bel_data.category != BEL_CATEGORY_LOGIC) {
continue;
}
- if(bel_data.synthetic) {
+ if (bel_data.synthetic) {
continue;
}
- if(ctx->getBelPinType(bel_pin.bel, bel_pin.pin) != PORT_OUT) {
+ if (ctx->getBelPinType(bel_pin.bel, bel_pin.pin) != PORT_OUT) {
continue;
}
@@ -637,24 +630,25 @@ void DedicatedInterconnect::expand_sink_bel(BelId sink_bel, IdString sink_pin, W
type_bel_pin.bel_pin = sink_pin;
auto result = sinks.emplace(type_bel_pin, srcs);
- if(!result.second) {
+ if (!result.second) {
// type_bel_pin was already present! Add any new sources from this
// sink type (if any);
- for(auto src : srcs) {
+ for (auto src : srcs) {
result.first->second.emplace(src);
}
}
}
-void DedicatedInterconnect::expand_source_bel(BelId src_bel, IdString src_pin, WireId src_wire) {
+void DedicatedInterconnect::expand_source_bel(BelId src_bel, IdString src_pin, WireId src_wire)
+{
NPNR_ASSERT(src_bel != BelId());
#ifdef DEBUG_EXPANSION
- log_info("Expanding from %s/%s\n", ctx->nameOfBel(src_bel), pin.c_str(ctx));
+ log_info("Expanding from %s/%s\n", ctx->nameOfBel(src_bel), src_pin.c_str(ctx));
#endif
std::vector<WireNode> nodes_to_expand;
- const auto & src_wire_data = ctx->wire_info(src_wire);
+ const auto &src_wire_data = ctx->wire_info(src_wire);
NPNR_ASSERT(src_wire_data.site != -1);
WireNode wire_node;
@@ -667,89 +661,91 @@ void DedicatedInterconnect::expand_source_bel(BelId src_bel, IdString src_pin, W
Loc src_loc = ctx->getBelLocation(src_bel);
std::unordered_set<DeltaTileTypeBelPin> dsts;
- while(!nodes_to_expand.empty()) {
+ while (!nodes_to_expand.empty()) {
WireNode node_to_expand = nodes_to_expand.back();
nodes_to_expand.pop_back();
- for(PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) {
- if(ctx->is_pip_synthetic(pip)) {
+ for (PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) {
+ if (ctx->is_pip_synthetic(pip)) {
continue;
}
WireId wire = ctx->getPipDstWire(pip);
- if(wire == WireId()) {
+ if (wire == WireId()) {
continue;
}
#ifdef DEBUG_EXPANSION
- log_info(" - At wire %s via %s\n",
- ctx->nameOfWire(wire), ctx->nameOfPip(pip));
+ log_info(" - At wire %s via %s\n", ctx->nameOfWire(wire), ctx->nameOfPip(pip));
#endif
WireNode next_node;
next_node.wire = wire;
next_node.depth = node_to_expand.depth += 1;
- if(next_node.depth > kMaxDepth) {
+ if (next_node.depth > kMaxDepth) {
// Dedicated routing should reach sources by kMaxDepth (with
// tuning).
//
// FIXME: Consider removing kMaxDepth and use kMaxSources?
+#ifdef DEBUG_EXPANSION
+ log_info(" - Exceeded max depth!\n");
+#endif
return;
}
- auto const & wire_data = ctx->wire_info(wire);
+ auto const &wire_data = ctx->wire_info(wire);
bool expand_node = true;
- if(ctx->is_site_port(pip)) {
- switch(node_to_expand.state) {
- case IN_SOURCE_SITE:
- NPNR_ASSERT(wire_data.site == -1);
- next_node.state = IN_ROUTING;
- break;
- case IN_ROUTING:
- NPNR_ASSERT(wire_data.site != -1);
- if(wire.tile == src_wire.tile && wire_data.site == src_wire_data.site) {
- // Dedicated routing won't have straight loops,
- // general routing looks like that.
+ if (ctx->is_site_port(pip)) {
+ switch (node_to_expand.state) {
+ case IN_SOURCE_SITE:
+ NPNR_ASSERT(wire_data.site == -1);
+ next_node.state = IN_ROUTING;
+ break;
+ case IN_ROUTING:
+ NPNR_ASSERT(wire_data.site != -1);
+ if (wire.tile == src_wire.tile && wire_data.site == src_wire_data.site) {
+ // Dedicated routing won't have straight loops,
+ // general routing looks like that.
#ifdef DEBUG_EXPANSION
- log_info(" - Not dedicated site routing because loop!");
+ log_info(" - Not dedicated site routing because loop!");
#endif
- return;
- }
- next_node.state = IN_SINK_SITE;
- break;
- case IN_SINK_SITE:
- // Once entering a site, do not leave it again.
- // This path is not a legal route!
- expand_node = false;
- break;
- default:
- // Unreachable!!!
- NPNR_ASSERT(false);
+ return;
+ }
+ next_node.state = IN_SINK_SITE;
+ break;
+ case IN_SINK_SITE:
+ // Once entering a site, do not leave it again.
+ // This path is not a legal route!
+ expand_node = false;
+ break;
+ default:
+ // Unreachable!!!
+ NPNR_ASSERT(false);
}
} else {
next_node.state = node_to_expand.state;
}
- if(expand_node) {
+ if (expand_node) {
nodes_to_expand.push_back(next_node);
} else {
continue;
}
- if(next_node.state == IN_SINK_SITE) {
- for(BelPin bel_pin : ctx->getWireBelPins(wire)) {
+ if (next_node.state == IN_SINK_SITE) {
+ for (BelPin bel_pin : ctx->getWireBelPins(wire)) {
BelId sink_bel = bel_pin.bel;
- auto const & bel_data = bel_info(ctx->chip_info, sink_bel);
+ auto const &bel_data = bel_info(ctx->chip_info, sink_bel);
- if(bel_data.category != BEL_CATEGORY_LOGIC) {
+ if (bel_data.category != BEL_CATEGORY_LOGIC) {
continue;
}
- if(bel_data.synthetic) {
+ if (bel_data.synthetic) {
continue;
}
- if(ctx->getBelPinType(bel_pin.bel, bel_pin.pin) != PORT_IN) {
+ if (ctx->getBelPinType(bel_pin.bel, bel_pin.pin) != PORT_IN) {
continue;
}
@@ -776,11 +772,11 @@ void DedicatedInterconnect::expand_source_bel(BelId src_bel, IdString src_pin, W
type_bel_pin.bel_index = src_bel.index;
type_bel_pin.bel_pin = src_pin;
- auto result = sinks.emplace(type_bel_pin, dsts);
- if(!result.second) {
+ auto result = sources.emplace(type_bel_pin, dsts);
+ if (!result.second) {
// type_bel_pin was already present! Add any new sources from this
// sink type (if any);
- for(auto dst : dsts) {
+ for (auto dst : dsts) {
result.first->second.emplace(dst);
}
}