diff options
author | Alessandro Comodi <acomodi@antmicro.com> | 2021-06-02 09:49:30 +0200 |
---|---|---|
committer | Alessandro Comodi <acomodi@antmicro.com> | 2021-06-11 11:19:01 +0200 |
commit | 104536b7aae5970ae1d1e95394f26fbf04603d12 (patch) | |
tree | 0f1fad9a952f272e6436456077fe54ba3a7730ea /fpga_interchange/site_router.cc | |
parent | 7278d3c0edbc6f92ef4c69d7c5db66e811c7e9c4 (diff) | |
download | nextpnr-104536b7aae5970ae1d1e95394f26fbf04603d12.tar.gz nextpnr-104536b7aae5970ae1d1e95394f26fbf04603d12.tar.bz2 nextpnr-104536b7aae5970ae1d1e95394f26fbf04603d12.zip |
interchange: add support for generating BEL clusters
Clustering greatly helps the placer to identify and pack together
specific cells at the same site (e.g. LUT+FF), or cells that are chained through
dedicated interconnections (e.g. CARRY CHAINS)
Signed-off-by: Alessandro Comodi <acomodi@antmicro.com>
Diffstat (limited to 'fpga_interchange/site_router.cc')
-rw-r--r-- | fpga_interchange/site_router.cc | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/fpga_interchange/site_router.cc b/fpga_interchange/site_router.cc index 090b9342..cae81d52 100644 --- a/fpga_interchange/site_router.cc +++ b/fpga_interchange/site_router.cc @@ -60,7 +60,9 @@ bool check_initial_wires(const Context *ctx, SiteInformation *site_info) if (!cell->ports.count(pin_pair.first)) continue; const PortInfo &port = cell->ports.at(pin_pair.first); - NPNR_ASSERT(port.net != nullptr); + + if (port.net == nullptr) + continue; for (IdString bel_pin_name : pin_pair.second) { BelPin bel_pin; @@ -297,7 +299,11 @@ struct SiteExpansionLoop // already unroutable! solution.clear(); solution.store_solution(ctx, node_storage, net->driver, completed_routes); - solution.verify(ctx, *net); + bool verify = solution.verify(ctx, *net); + + if (!verify) + return false; + for (size_t route : completed_routes) { SiteWire wire = node_storage->get_node(route)->wire; targets.erase(wire); @@ -1086,6 +1092,40 @@ static void block_lut_outputs(SiteArch *site_arch, const pool<std::pair<IdString } } +// Block outputs of unavailable LUTs to prevent site router from using them. +static void block_cluster_wires(SiteArch *site_arch) +{ + const Context *ctx = site_arch->site_info->ctx; + auto &cells_in_site = site_arch->site_info->cells_in_site; + + for (auto &cell : cells_in_site) { + if (cell->cluster == ClusterId()) + continue; + + if (ctx->getClusterRootCell(cell->cluster) != cell) + continue; + + Cluster cluster = ctx->clusters.at(cell->cluster); + + uint32_t cluster_id = cluster.index; + auto &cluster_data = cluster_info(ctx->chip_info, cluster_id); + + if (cluster_data.chainable_ports.size() == 0) + continue; + + IdString cluster_chain_input(cluster_data.chainable_ports[0].cell_sink); + + if (cluster_chain_input == IdString()) + continue; + + auto &cell_bel_pins = cell->cell_bel_pins.at(cluster_chain_input); + for (auto &bel_pin : cell_bel_pins) { + SiteWire bel_pin_wire = site_arch->getBelPinWire(cell->bel, bel_pin); + site_arch->bindWire(bel_pin_wire, &site_arch->blocking_site_net); + } + } +} + // Recursively visit downhill PIPs until a SITE_PORT_SINK is reached. // Marks all PIPs for all valid paths. static bool visit_downhill_pips(const SiteArch *site_arch, const SiteWire &site_wire, std::vector<PipId> &valid_pips) @@ -1205,6 +1245,7 @@ bool SiteRouter::checkSiteRouting(const Context *ctx, const TileStatus &tile_sta // site_arch.archcheck(); block_lut_outputs(&site_arch, blocked_wires); + block_cluster_wires(&site_arch); // Do a detailed routing check to see if the site has at least 1 valid // routing solution. @@ -1264,6 +1305,7 @@ void SiteRouter::bindSiteRouting(Context *ctx) SiteArch site_arch(&site_info); block_lut_outputs(&site_arch, blocked_wires); + block_cluster_wires(&site_arch); NPNR_ASSERT(route_site(&site_arch, &ctx->site_routing_cache, &ctx->node_storage, /*explain=*/false)); check_routing(site_arch); |