From 930fef448efda3401606b1fb2cd2b3de7b7eaf24 Mon Sep 17 00:00:00 2001 From: gatecat Date: Tue, 11 Aug 2026 15:39:09 +0200 Subject: [PATCH] static: Allow a custom delay prediction function Signed-off-by: gatecat --- common/place/placer_static.cc | 10 ++++++++-- common/place/placer_static.h | 3 +++ ecp5/arch.cc | 12 ++++++++++++ himbaechel/uarch/xilinx/xilinx.cc | 10 ++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/common/place/placer_static.cc b/common/place/placer_static.cc index f8c01d82..d773d123 100644 --- a/common/place/placer_static.cc +++ b/common/place/placer_static.cc @@ -1295,8 +1295,8 @@ class StaticPlacer RealPair drv_loc = cell_loc(ni->driver.cell, false); for (auto usr : ni->users.enumerate()) { RealPair usr_loc = cell_loc(usr.value.cell, false); - delay_t est_delay = cfg.timing_c + cfg.timing_mx * std::abs(drv_loc.x - usr_loc.x) + - cfg.timing_my * std::abs(drv_loc.y - usr_loc.y); + delay_t est_delay = cfg.predict_delay(ctx, cfg, Loc(drv_loc.x, drv_loc.y, 0), ni->driver.port, + Loc(usr_loc.x, usr_loc.y, 0), usr.value.port); tmg.set_route_delay(CellPortKey(usr.value), DelayPair(est_delay)); } } @@ -1721,6 +1721,12 @@ PlacerStaticCfg::PlacerStaticCfg(Context *ctx) hpwl_scale_x = 1; hpwl_scale_y = 1; + + predict_delay = [](Context *ctx, const PlacerStaticCfg &cfg, Loc src_loc, IdString /*src_pin*/, Loc dst_loc, + IdString /*dst_pin*/) -> delay_t { + return cfg.timing_c + delay_t(cfg.timing_mx * std::abs(dst_loc.x - src_loc.x)) + + delay_t(cfg.timing_my * std::abs(dst_loc.y - src_loc.y)); + }; } NEXTPNR_NAMESPACE_END diff --git a/common/place/placer_static.h b/common/place/placer_static.h index 757ced28..8d2e47c4 100644 --- a/common/place/placer_static.h +++ b/common/place/placer_static.h @@ -72,6 +72,9 @@ struct PlacerStaticCfg // this is an optional callback to override the area of a cell e.g. based on configuration std::function(Context *, const CellInfo *)> get_cell_area_override = [](Context *, const CellInfo *) { return std::optional{}; }; + + // override the default delay estimation formula (we can't use predictDelay because we don't have concrete bels) + std::function predict_delay; }; extern bool placer_static(Context *ctx, PlacerStaticCfg cfg); diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 55a5346e..22bfc55a 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -630,6 +630,18 @@ void configure_static(Arch *arch, PlacerStaticCfg &cfg) cfg.timing_c = (120 - 22 * arch->args.speed) * 6; cfg.timing_mx = (120 - 22 * arch->args.speed); cfg.timing_my = (120 - 22 * arch->args.speed); + + cfg.predict_delay = [](Context *ctx, const PlacerStaticCfg &cfg, Loc src_loc, IdString src_pin, Loc dst_loc, + IdString dst_pin) -> delay_t { + if ((src_pin == id_FCO && dst_pin == id_FCI) || dst_pin.in(id_FXA, id_FXB) || + (src_pin == id_F && dst_pin == id_DI)) + return 0; + + int dx = abs(src_loc.x - dst_loc.x), dy = abs(src_loc.y - dst_loc.y); + + return (80 - 9 * ctx->args.speed) * + (6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5))); + }; } } // namespace diff --git a/himbaechel/uarch/xilinx/xilinx.cc b/himbaechel/uarch/xilinx/xilinx.cc index 951af93c..c3c8fa4c 100644 --- a/himbaechel/uarch/xilinx/xilinx.cc +++ b/himbaechel/uarch/xilinx/xilinx.cc @@ -362,6 +362,16 @@ void XilinxImpl::configurePlacerStatic(PlacerStaticCfg &cfg) cfg.timing_mx = 25; cfg.timing_my = 50; + cfg.predict_delay = [](Context *ctx, const PlacerStaticCfg &cfg, Loc src_loc, IdString src_pin, Loc dst_loc, + IdString dst_pin) -> delay_t { + if (dst_pin == id_CIN && src_pin == id_CO3) + return 0; + // TODO: improve sophistication here based on old nextpnr-xilinx code + int dist_x = std::abs(dst_loc.x - src_loc.x), dist_y = std::abs(dst_loc.y - src_loc.y); + return 500 + 12 * (2 * std::max(dist_y - 6, 0) + 4 * std::min(dist_y, 6) + std::max(dist_x - 12, 0) + + 2 * std::min(dist_x, 12)); + }; + { cfg.cell_groups.emplace_back(); auto &comb = cfg.cell_groups.back();