static: Allow a custom delay prediction function

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2026-08-11 15:39:09 +02:00 committed by myrtle
parent df871def22
commit 930fef448e
4 changed files with 33 additions and 2 deletions

View File

@ -1295,8 +1295,8 @@ class StaticPlacer
RealPair drv_loc = cell_loc(ni->driver.cell, false); RealPair drv_loc = cell_loc(ni->driver.cell, false);
for (auto usr : ni->users.enumerate()) { for (auto usr : ni->users.enumerate()) {
RealPair usr_loc = cell_loc(usr.value.cell, false); 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) + delay_t est_delay = cfg.predict_delay(ctx, cfg, Loc(drv_loc.x, drv_loc.y, 0), ni->driver.port,
cfg.timing_my * std::abs(drv_loc.y - usr_loc.y); Loc(usr_loc.x, usr_loc.y, 0), usr.value.port);
tmg.set_route_delay(CellPortKey(usr.value), DelayPair(est_delay)); tmg.set_route_delay(CellPortKey(usr.value), DelayPair(est_delay));
} }
} }
@ -1721,6 +1721,12 @@ PlacerStaticCfg::PlacerStaticCfg(Context *ctx)
hpwl_scale_x = 1; hpwl_scale_x = 1;
hpwl_scale_y = 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 NEXTPNR_NAMESPACE_END

View File

@ -72,6 +72,9 @@ struct PlacerStaticCfg
// this is an optional callback to override the area of a cell e.g. based on configuration // this is an optional callback to override the area of a cell e.g. based on configuration
std::function<std::optional<StaticRect>(Context *, const CellInfo *)> get_cell_area_override = std::function<std::optional<StaticRect>(Context *, const CellInfo *)> get_cell_area_override =
[](Context *, const CellInfo *) { return std::optional<StaticRect>{}; }; [](Context *, const CellInfo *) { return std::optional<StaticRect>{}; };
// override the default delay estimation formula (we can't use predictDelay because we don't have concrete bels)
std::function<delay_t(Context *, const PlacerStaticCfg &, Loc, IdString, Loc, IdString)> predict_delay;
}; };
extern bool placer_static(Context *ctx, PlacerStaticCfg cfg); extern bool placer_static(Context *ctx, PlacerStaticCfg cfg);

View File

@ -630,6 +630,18 @@ void configure_static(Arch *arch, PlacerStaticCfg &cfg)
cfg.timing_c = (120 - 22 * arch->args.speed) * 6; cfg.timing_c = (120 - 22 * arch->args.speed) * 6;
cfg.timing_mx = (120 - 22 * arch->args.speed); cfg.timing_mx = (120 - 22 * arch->args.speed);
cfg.timing_my = (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 } // namespace

View File

@ -362,6 +362,16 @@ void XilinxImpl::configurePlacerStatic(PlacerStaticCfg &cfg)
cfg.timing_mx = 25; cfg.timing_mx = 25;
cfg.timing_my = 50; 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(); cfg.cell_groups.emplace_back();
auto &comb = cfg.cell_groups.back(); auto &comb = cfg.cell_groups.back();