diff options
author | Keith Rothman <537074+litghost@users.noreply.github.com> | 2021-02-23 13:35:45 -0800 |
---|---|---|
committer | Keith Rothman <537074+litghost@users.noreply.github.com> | 2021-02-23 14:09:28 -0800 |
commit | a30043c8da1b1cc46a2dcfb90aa3a06d4f4ed4e9 (patch) | |
tree | 7d9558216c7b9858bd31323ff3482b50e9d5c05f /fpga_interchange/dedicated_interconnect.cc | |
parent | 184665652eaf351bf9337b524c5d82a50ce54041 (diff) | |
download | nextpnr-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.cc | 524 |
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); } } |