From 428b56570dcbb3ff145ac33989fbf6384c249e73 Mon Sep 17 00:00:00 2001 From: Alessandro Comodi Date: Thu, 13 May 2021 17:35:17 +0200 Subject: [PATCH] interchange: pseudo pips: fix illegal tile pseudo PIPs Signed-off-by: Alessandro Comodi --- fpga_interchange/pseudo_pip_model.cc | 52 ++++++++++++++++++++-------- fpga_interchange/site_router.cc | 30 ++++++++++++---- fpga_interchange/site_router.h | 1 + 3 files changed, 62 insertions(+), 21 deletions(-) diff --git a/fpga_interchange/pseudo_pip_model.cc b/fpga_interchange/pseudo_pip_model.cc index 524b48d5e9..64da454837 100644 --- a/fpga_interchange/pseudo_pip_model.cc +++ b/fpga_interchange/pseudo_pip_model.cc @@ -353,6 +353,37 @@ void PseudoPipModel::update_site(const Context *ctx, size_t site) } } + std::vector lut_thru_cells; + lut_thru_cells.reserve(tile_status.sites[site].lut_thrus.size()); + for (auto input_bel_pin : tile_status.sites[site].lut_thrus) { + if (ctx->wire_lut == nullptr) + break; + + BelId bel; + bel.index = input_bel_pin.second; + bel.tile = tile; + const auto &bel_data = bel_info(ctx->chip_info, bel); + + NPNR_ASSERT(bel_data.lut_element != -1); + + lut_thru_cells.emplace_back(); + CellInfo &cell = lut_thru_cells.back(); + + cell.bel = bel; + + cell.type = IdString(ctx->wire_lut->cell); + NPNR_ASSERT(ctx->wire_lut->input_pins.size() == 1); + cell.lut_cell.pins.push_back(IdString(ctx->wire_lut->input_pins[0])); + + cell.lut_cell.equation.resize(2); + cell.lut_cell.equation.set(0, false); + cell.lut_cell.equation.set(1, true); + + cell.cell_bel_pins[IdString(ctx->wire_lut->input_pins[0])].push_back(input_bel_pin.first); + + lut_mappers[bel_data.lut_element].cells.push_back(&cell); + } + std::vector lut_cells; lut_cells.reserve(used_bels.size()); for (const auto &bel_pair : used_bels) { @@ -370,9 +401,8 @@ void PseudoPipModel::update_site(const Context *ctx, size_t site) cell.bel.tile = tile; cell.bel.index = bel_pair.first; - if (ctx->wire_lut == nullptr) { + if (ctx->wire_lut == nullptr) continue; - } cell.type = IdString(ctx->wire_lut->cell); NPNR_ASSERT(ctx->wire_lut->input_pins.size() == 1); @@ -437,11 +467,6 @@ void PseudoPipModel::update_site(const Context *ctx, size_t site) } } - if (blocked_by_bel) { - allowed_pseudo_pips.set(pseudo_pip, false); - continue; - } - bool blocked_by_lut_eq = false; // See if any BELs are part of a LUT element. If so, see if using @@ -480,20 +505,17 @@ void PseudoPipModel::update_site(const Context *ctx, size_t site) } } - if (blocked_by_lut_eq) { #ifdef DEBUG_PSEUDO_PIP - if (ctx->verbose) { - log_info("Pseudo pip %s is blocked by lut eq\n", ctx->nameOfPip(pip)); - } -#endif - allowed_pseudo_pips.set(pseudo_pip, false); - continue; + if (blocked_by_lut_eq && ctx->verbose) { + log_info("Pseudo pip %s is blocked by invalid LUT equation\n", ctx->nameOfPip(pip)); } +#endif // Pseudo pip should be allowed, mark as such. // // FIXME: Handle non-LUT constraint cases, as needed. - allowed_pseudo_pips.set(pseudo_pip, true); + bool allow_pip = !blocked_by_lut_eq && !blocked_by_bel; + allowed_pseudo_pips.set(pseudo_pip, allow_pip); } } diff --git a/fpga_interchange/site_router.cc b/fpga_interchange/site_router.cc index da46a16633..9081a57ec3 100644 --- a/fpga_interchange/site_router.cc +++ b/fpga_interchange/site_router.cc @@ -964,7 +964,7 @@ static void apply_constant_routing(Context *ctx, const SiteArch &site_arch, NetI } } -static void apply_routing(Context *ctx, const SiteArch &site_arch) +static void apply_routing(Context *ctx, const SiteArch &site_arch, HashTables::HashSet, PairHash> &lut_thrus) { IdString gnd_net_name(ctx->chip_info->constants->gnd_net_name); NetInfo *gnd_net = ctx->nets.at(gnd_net_name).get(); @@ -993,6 +993,26 @@ static void apply_routing(Context *ctx, const SiteArch &site_arch) continue; } + auto &pip_data = pip_info(ctx->chip_info, site_pip.pip); + + BelId bel; + bel.tile = site_pip.pip.tile; + bel.index = pip_data.bel; + const auto &bel_data = bel_info(ctx->chip_info, bel); + + // Detect and store LUT thrus for allowance check during routing + if (bel_data.lut_element != -1) { + WireId src_wire = ctx->getPipSrcWire(site_pip.pip); + + for (BelPin bel_pin : ctx->getWireBelPins(src_wire)) { + if (bel_pin.bel != bel) + continue; + + lut_thrus.insert(std::make_pair(bel_pin.pin, bel_pin.bel.index)); + break; + } + } + ctx->bindPip(site_pip.pip, net, STRENGTH_PLACER); } } @@ -1094,10 +1114,9 @@ static bool visit_downhill_pips(const SiteArch *site_arch, const SiteWire &site_ // Checks all downhill PIPs starting from driver wires. // All valid PIPs are stored and returned in a vector. -static std::vector check_downhill_pips(Context *ctx, const SiteArch *site_arch) { +static void check_downhill_pips(Context *ctx, const SiteArch *site_arch, std::vector &valid_pips) { auto &cells_in_site = site_arch->site_info->cells_in_site; - std::vector valid_pips; for (auto &net_pair : site_arch->nets) { NetInfo *net = net_pair.first; const SiteNetInfo *site_net = &net_pair.second; @@ -1108,7 +1127,6 @@ static std::vector check_downhill_pips(Context *ctx, const SiteArch *site visit_downhill_pips(site_arch, site_wire, valid_pips); } } - return valid_pips; } bool SiteRouter::checkSiteRouting(const Context *ctx, const TileStatus &tile_status) const @@ -1251,9 +1269,9 @@ void SiteRouter::bindSiteRouting(Context *ctx) NPNR_ASSERT(route_site(&site_arch, &ctx->site_routing_cache, &ctx->node_storage, /*explain=*/false)); check_routing(site_arch); - apply_routing(ctx, site_arch); + apply_routing(ctx, site_arch, lut_thrus); - valid_pips = check_downhill_pips(ctx, &site_arch); + check_downhill_pips(ctx, &site_arch, valid_pips); if (verbose_site_router(ctx)) { print_current_state(&site_arch); } diff --git a/fpga_interchange/site_router.h b/fpga_interchange/site_router.h index 3222669a04..0328b6b295 100644 --- a/fpga_interchange/site_router.h +++ b/fpga_interchange/site_router.h @@ -39,6 +39,7 @@ struct SiteRouter std::unordered_set cells_in_site; std::vector valid_pips; + HashTables::HashSet, PairHash> lut_thrus; const int16_t site; mutable bool dirty;