archapi: Use arbitrary rather than actual placement in predictDelay

This makes predictDelay be based on an arbitrary belpin pair rather
than a arc of a net based on cell placement. This way 'what-if'
decisions can be evaluated without actually changing placement;
potentially useful for parallel placement.

A new helper predictArcDelay behaves like the old predictDelay to
minimise the impact on existing passes; only arches need be updated.

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2021-12-19 16:41:34 +00:00
parent 56d5507333
commit ddb084e9a8
26 changed files with 89 additions and 70 deletions

View File

@ -110,7 +110,7 @@ template <typename R> struct ArchAPI : BaseCtx
virtual typename R::GroupPipsRangeT getGroupPips(GroupId group) const = 0; virtual typename R::GroupPipsRangeT getGroupPips(GroupId group) const = 0;
virtual typename R::GroupGroupsRangeT getGroupGroups(GroupId group) const = 0; virtual typename R::GroupGroupsRangeT getGroupGroups(GroupId group) const = 0;
// Delay Methods // Delay Methods
virtual delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const = 0; virtual delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const = 0;
virtual delay_t getDelayEpsilon() const = 0; virtual delay_t getDelayEpsilon() const = 0;
virtual delay_t getRipupDelayPenalty() const = 0; virtual delay_t getRipupDelayPenalty() const = 0;
virtual float getDelayNS(delay_t v) const = 0; virtual float getDelayNS(delay_t v) const = 0;

View File

@ -90,6 +90,25 @@ WireId Context::getNetinfoSinkWire(const NetInfo *net_info, const PortRef &sink,
return WireId(); return WireId();
} }
delay_t Context::predictArcDelay(const NetInfo *net_info, const PortRef &sink) const
{
if (net_info->driver.cell == nullptr || net_info->driver.cell->bel == BelId() || sink.cell->bel == BelId())
return 0;
IdString driver_pin, sink_pin;
// Pick the first pin for a prediction; assume all will be similar enouhg
for (auto pin : getBelPinsForCellPin(net_info->driver.cell, net_info->driver.port)) {
driver_pin = pin;
break;
}
for (auto pin : getBelPinsForCellPin(sink.cell, sink.port)) {
sink_pin = pin;
break;
}
if (driver_pin == IdString() || sink_pin == IdString())
return 0;
return predictDelay(net_info->driver.cell->bel, driver_pin, sink.cell->bel, sink_pin);
}
delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &user_info) const delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &user_info) const
{ {
#ifdef ARCH_ECP5 #ifdef ARCH_ECP5
@ -98,7 +117,7 @@ delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &us
#endif #endif
if (net_info->wires.empty()) if (net_info->wires.empty())
return predictDelay(net_info, user_info); return predictArcDelay(net_info, user_info);
WireId src_wire = getNetinfoSourceWire(net_info); WireId src_wire = getNetinfoSourceWire(net_info);
if (src_wire == WireId()) if (src_wire == WireId())
@ -128,7 +147,7 @@ delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &us
if (cursor == src_wire) if (cursor == src_wire)
max_delay = std::max(max_delay, delay + getWireDelay(src_wire).maxDelay()); // routed max_delay = std::max(max_delay, delay + getWireDelay(src_wire).maxDelay()); // routed
else else
max_delay = std::max(max_delay, predictDelay(net_info, user_info)); // unrouted max_delay = std::max(max_delay, predictArcDelay(net_info, user_info)); // unrouted
} }
return max_delay; return max_delay;
} }

View File

@ -51,6 +51,8 @@ struct Context : Arch, DeterministicRNG
// -------------------------------------------------------------- // --------------------------------------------------------------
delay_t predictArcDelay(const NetInfo *net_info, const PortRef &sink) const;
WireId getNetinfoSourceWire(const NetInfo *net_info) const; WireId getNetinfoSourceWire(const NetInfo *net_info) const;
SSOArray<WireId, 2> getNetinfoSinkWires(const NetInfo *net_info, const PortRef &sink) const; SSOArray<WireId, 2> getNetinfoSinkWires(const NetInfo *net_info, const PortRef &sink) const;
size_t getNetinfoSinkWireCount(const NetInfo *net_info, const PortRef &sink) const; size_t getNetinfoSinkWireCount(const NetInfo *net_info, const PortRef &sink) const;

View File

@ -33,6 +33,8 @@
#define USING_NEXTPNR_NAMESPACE #define USING_NEXTPNR_NAMESPACE
#endif #endif
#define NPNR_UNUSED(x) ((void)x)
#if defined(__GNUC__) || defined(__clang__) #if defined(__GNUC__) || defined(__clang__)
#define NPNR_ATTRIBUTE(...) __attribute__((__VA_ARGS__)) #define NPNR_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
#define NPNR_NORETURN __attribute__((noreturn)) #define NPNR_NORETURN __attribute__((noreturn))

View File

@ -50,7 +50,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type
if (load_cell->bel == BelId()) if (load_cell->bel == BelId())
continue; continue;
if (timing_driven) { if (timing_driven) {
delay_t net_delay = ctx->predictDelay(net, load); delay_t net_delay = ctx->predictArcDelay(net, load);
auto slack = load.budget - net_delay; auto slack = load.budget - net_delay;
if (slack < 0) if (slack < 0)
negative_slack += slack; negative_slack += slack;

View File

@ -866,11 +866,11 @@ class SAPlacer
if (ctx->getPortTimingClass(net->driver.cell, net->driver.port, cc) == TMG_IGNORE) if (ctx->getPortTimingClass(net->driver.cell, net->driver.port, cc) == TMG_IGNORE)
return 0; return 0;
if (cfg.budgetBased) { if (cfg.budgetBased) {
double delay = ctx->getDelayNS(ctx->predictDelay(net, net->users.at(user))); double delay = ctx->getDelayNS(ctx->predictArcDelay(net, net->users.at(user)));
return std::min(10.0, std::exp(delay - ctx->getDelayNS(net->users.at(user).budget) / 10)); return std::min(10.0, std::exp(delay - ctx->getDelayNS(net->users.at(user).budget) / 10));
} else { } else {
float crit = tmg.get_criticality(CellPortKey(net->users.at(user))); float crit = tmg.get_criticality(CellPortKey(net->users.at(user)));
double delay = ctx->getDelayNS(ctx->predictDelay(net, net->users.at(user))); double delay = ctx->getDelayNS(ctx->predictArcDelay(net, net->users.at(user)));
return delay * std::pow(crit, crit_exp); return delay * std::pow(crit, crit_exp);
} }
} }

View File

@ -1378,7 +1378,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
auto driver_wire = ctx->getNetinfoSourceWire(net); auto driver_wire = ctx->getNetinfoSourceWire(net);
auto sink_wire = ctx->getNetinfoSinkWire(net, sink_ref, 0); auto sink_wire = ctx->getNetinfoSinkWire(net, sink_ref, 0);
log_info(" prediction: %f ns estimate: %f ns\n", log_info(" prediction: %f ns estimate: %f ns\n",
ctx->getDelayNS(ctx->predictDelay(net, sink_ref)), ctx->getDelayNS(ctx->predictArcDelay(net, sink_ref)),
ctx->getDelayNS(ctx->estimateDelay(driver_wire, sink_wire))); ctx->getDelayNS(ctx->estimateDelay(driver_wire, sink_wire)));
auto cursor = sink_wire; auto cursor = sink_wire;
delay_t delay; delay_t delay;

View File

@ -99,7 +99,7 @@ class TimingOptimiser
continue; continue;
for (auto user : net->users) { for (auto user : net->users) {
if (user.cell == cell && user.port == port.first) { if (user.cell == cell && user.port == port.first) {
if (ctx->predictDelay(net, user) > if (ctx->predictArcDelay(net, user) >
1.1 * max_net_delay.at(std::make_pair(cell->name, port.first))) 1.1 * max_net_delay.at(std::make_pair(cell->name, port.first)))
return false; return false;
} }
@ -111,7 +111,7 @@ class TimingOptimiser
BelId dstBel = user.cell->bel; BelId dstBel = user.cell->bel;
if (dstBel == BelId()) if (dstBel == BelId())
continue; continue;
if (ctx->predictDelay(net, user) > if (ctx->predictArcDelay(net, user) >
1.1 * max_net_delay.at(std::make_pair(user.cell->name, user.port))) { 1.1 * max_net_delay.at(std::make_pair(user.cell->name, user.port))) {
return false; return false;
@ -413,7 +413,7 @@ class TimingOptimiser
for (size_t j = 0; j < pn->users.size(); j++) { for (size_t j = 0; j < pn->users.size(); j++) {
auto &usr = pn->users.at(j); auto &usr = pn->users.at(j);
if (usr.cell == path.at(i)->cell && usr.port == path.at(i)->port) { if (usr.cell == path.at(i)->cell && usr.port == path.at(i)->port) {
original_delay += ctx->predictDelay(pn, usr); original_delay += ctx->predictArcDelay(pn, usr);
break; break;
} }
} }
@ -497,7 +497,7 @@ class TimingOptimiser
for (size_t j = 0; j < pn->users.size(); j++) { for (size_t j = 0; j < pn->users.size(); j++) {
auto &usr = pn->users.at(j); auto &usr = pn->users.at(j);
if (usr.cell == path.at(i)->cell && usr.port == path.at(i)->port) { if (usr.cell == path.at(i)->cell && usr.port == path.at(i)->port) {
total_delay += ctx->predictDelay(pn, usr); total_delay += ctx->predictArcDelay(pn, usr);
break; break;
} }
} }

View File

@ -517,7 +517,7 @@ result, and for that estimate it is considered more acceptable to return a
slightly too high result and it is considered less acceptable to return a slightly too high result and it is considered less acceptable to return a
too low result (thus "low upper bound"). too low result (thus "low upper bound").
### delay\_t predictDelay(const NetInfo \*net\_info, const PortRef &sink) const ### delay\_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
Return a reasonably good estimate for the total `maxDelay()` delay for the Return a reasonably good estimate for the total `maxDelay()` delay for the
given arc. This should return a low upper bound for the fastest route for that arc. given arc. This should return a low upper bound for the fastest route for that arc.

View File

@ -80,7 +80,7 @@ As nextpnr allows arbitrary constraints on bels for more advanced packer-free fl
There are several routes for timing information in the placer: There are several routes for timing information in the placer:
- sink `PortRef`s have a `budget` value annotated by calling `assign_budget` which is an estimate of the maximum delay that an arc may have - sink `PortRef`s have a `budget` value annotated by calling `assign_budget` which is an estimate of the maximum delay that an arc may have
- sink ports can have a criticality (value between 0 and 1 where 1 is the critical path) associated with them by using `get_criticalities` and a `NetCriticalityMap` - sink ports can have a criticality (value between 0 and 1 where 1 is the critical path) associated with them by using `get_criticalities` and a `NetCriticalityMap`
- `predictDelay` returns an estimated delay for a sink port based on placement information - `predictDelay` and its derivative `predictArcDelay` returns an estimated delay for a sink port based on placement information
### Bel Buckets ### Bel Buckets

View File

@ -543,26 +543,21 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
return bb; return bb;
} }
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
{ {
const auto &driver = net_info->driver; if ((src_pin == id_FCO && dst_pin == id_FCI) || dst_pin == id_FXA || dst_pin == id_FXB)
if ((driver.port == id_FCO && sink.port == id_FCI) || sink.port == id_FXA || sink.port == id_FXB)
return 0; return 0;
auto driver_loc = getBelLocation(driver.cell->bel); auto driver_loc = getBelLocation(src_bel);
auto sink_loc = getBelLocation(sink.cell->bel); auto sink_loc = getBelLocation(dst_bel);
// Encourage use of direct interconnect // Encourage use of direct interconnect
if (driver_loc.x == sink_loc.x && driver_loc.y == sink_loc.y) { if (driver_loc.x == sink_loc.x && driver_loc.y == sink_loc.y) {
if ((sink.port == id_A0 || sink.port == id_A1) && (driver.port == id_F1) && if ((dst_pin == id_A0 || dst_pin == id_A1) && (src_pin == id_F1) && (driver_loc.z == 2 || driver_loc.z == 3))
(driver_loc.z == 2 || driver_loc.z == 3))
return 0; return 0;
if ((sink.port == id_B0 || sink.port == id_B1) && (driver.port == id_F1) && if ((dst_pin == id_B0 || dst_pin == id_B1) && (src_pin == id_F1) && (driver_loc.z == 0 || driver_loc.z == 1))
(driver_loc.z == 0 || driver_loc.z == 1))
return 0; return 0;
if ((sink.port == id_C0 || sink.port == id_C1) && (driver.port == id_F0) && if ((dst_pin == id_C0 || dst_pin == id_C1) && (src_pin == id_F0) && (driver_loc.z == 2 || driver_loc.z == 3))
(driver_loc.z == 2 || driver_loc.z == 3))
return 0; return 0;
if ((sink.port == id_D0 || sink.port == id_D1) && (driver.port == id_F0) && if ((dst_pin == id_D0 || dst_pin == id_D1) && (src_pin == id_F0) && (driver_loc.z == 0 || driver_loc.z == 1))
(driver_loc.z == 0 || driver_loc.z == 1))
return 0; return 0;
} }

View File

@ -913,7 +913,7 @@ struct Arch : BaseArch<ArchRanges>
delay_t estimateDelay(WireId src, WireId dst) const override; delay_t estimateDelay(WireId src, WireId dst) const override;
ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override; ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override;
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override;
delay_t getDelayEpsilon() const override { return 20; } delay_t getDelayEpsilon() const override { return 20; }
delay_t getRipupDelayPenalty() const override; delay_t getRipupDelayPenalty() const override;
float getDelayNS(delay_t v) const override { return v * 0.001; } float getDelayNS(delay_t v) const override { return v * 0.001; }

View File

@ -1000,14 +1000,16 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
#endif #endif
} }
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
{ {
// FIXME: Implement when adding timing-driven place and route. // FIXME: Implement when adding timing-driven place and route.
NPNR_UNUSED(src_pin);
NPNR_UNUSED(dst_pin);
int src_x, src_y; int src_x, src_y;
get_tile_x_y(net_info->driver.cell->bel.tile, &src_x, &src_y); get_tile_x_y(src_bel.tile, &src_x, &src_y);
int dst_x, dst_y; int dst_x, dst_y;
get_tile_x_y(sink.cell->bel.tile, &dst_x, &dst_y); get_tile_x_y(dst_bel.tile, &dst_x, &dst_y);
delay_t base = 30 * std::min(std::abs(dst_x - src_x), 18) + 10 * std::max(std::abs(dst_x - src_x) - 18, 0) + delay_t base = 30 * std::min(std::abs(dst_x - src_x), 18) + 10 * std::max(std::abs(dst_x - src_x) - 18, 0) +
60 * std::min(std::abs(dst_y - src_y), 6) + 20 * std::max(std::abs(dst_y - src_y) - 6, 0) + 300; 60 * std::min(std::abs(dst_y - src_y), 6) + 20 * std::max(std::abs(dst_y - src_y) - 6, 0) + 300;

View File

@ -700,7 +700,7 @@ struct Arch : ArchAPI<ArchRanges>
// ------------------------------------------------- // -------------------------------------------------
delay_t estimateDelay(WireId src, WireId dst) const final; delay_t estimateDelay(WireId src, WireId dst) const final;
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const final; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const final;
ArcBounds getRouteBoundingBox(WireId src, WireId dst) const final; ArcBounds getRouteBoundingBox(WireId src, WireId dst) const final;
delay_t getDelayEpsilon() const final { return 20; } delay_t getDelayEpsilon() const final { return 20; }
delay_t getRipupDelayPenalty() const final { return 120; } delay_t getRipupDelayPenalty() const final { return 120; }

View File

@ -509,11 +509,12 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
return (dx + dy) * args.delayScale + args.delayOffset; return (dx + dy) * args.delayScale + args.delayOffset;
} }
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
{ {
const auto &driver = net_info->driver; NPNR_UNUSED(src_pin);
auto driver_loc = getBelLocation(driver.cell->bel); NPNR_UNUSED(dst_pin);
auto sink_loc = getBelLocation(sink.cell->bel); auto driver_loc = getBelLocation(src_bel);
auto sink_loc = getBelLocation(dst_bel);
int dx = abs(sink_loc.x - driver_loc.x); int dx = abs(sink_loc.x - driver_loc.x);
int dy = abs(sink_loc.y - driver_loc.y); int dy = abs(sink_loc.y - driver_loc.y);

View File

@ -287,7 +287,7 @@ struct Arch : ArchAPI<ArchRanges>
const std::vector<GroupId> &getGroupGroups(GroupId group) const override; const std::vector<GroupId> &getGroupGroups(GroupId group) const override;
delay_t estimateDelay(WireId src, WireId dst) const override; delay_t estimateDelay(WireId src, WireId dst) const override;
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override;
delay_t getDelayEpsilon() const override { return 0.001; } delay_t getDelayEpsilon() const override { return 0.001; }
delay_t getRipupDelayPenalty() const override { return 0.015; } delay_t getRipupDelayPenalty() const override { return 0.015; }
float getDelayNS(delay_t v) const override { return v; } float getDelayNS(delay_t v) const override { return v; }

View File

@ -1171,11 +1171,12 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
return (dx + dy) * args.delayScale + args.delayOffset; return (dx + dy) * args.delayScale + args.delayOffset;
} }
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
{ {
const auto &driver = net_info->driver; NPNR_UNUSED(src_pin);
auto driver_loc = getBelLocation(driver.cell->bel); NPNR_UNUSED(dst_pin);
auto sink_loc = getBelLocation(sink.cell->bel); auto driver_loc = getBelLocation(src_bel);
auto sink_loc = getBelLocation(dst_bel);
int dx = abs(sink_loc.x - driver_loc.x); int dx = abs(sink_loc.x - driver_loc.x);
int dy = abs(sink_loc.y - driver_loc.y); int dy = abs(sink_loc.y - driver_loc.y);

View File

@ -419,7 +419,7 @@ struct Arch : BaseArch<ArchRanges>
const std::vector<GroupId> &getGroupGroups(GroupId group) const override; const std::vector<GroupId> &getGroupGroups(GroupId group) const override;
delay_t estimateDelay(WireId src, WireId dst) const override; delay_t estimateDelay(WireId src, WireId dst) const override;
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override;
delay_t getDelayEpsilon() const override { return 0.01; } delay_t getDelayEpsilon() const override { return 0.01; }
delay_t getRipupDelayPenalty() const override { return 0.4; } delay_t getRipupDelayPenalty() const override { return 0.4; }
float getDelayNS(delay_t v) const override { return v; } float getDelayNS(delay_t v) const override { return v; }

View File

@ -784,7 +784,7 @@ struct Arch : BaseArch<ArchRanges>
// ------------------------------------------------- // -------------------------------------------------
delay_t estimateDelay(WireId src, WireId dst) const override; delay_t estimateDelay(WireId src, WireId dst) const override;
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override;
delay_t getDelayEpsilon() const override { return 20; } delay_t getDelayEpsilon() const override { return 20; }
delay_t getRipupDelayPenalty() const override { return 200; } delay_t getRipupDelayPenalty() const override { return 200; }
float getDelayNS(delay_t v) const override { return v * 0.001; } float getDelayNS(delay_t v) const override { return v * 0.001; }

View File

@ -188,13 +188,13 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
return v; return v;
} }
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
{ {
const auto &driver = net_info->driver; NPNR_UNUSED(dst_pin);
auto driver_loc = getBelLocation(driver.cell->bel); auto driver_loc = getBelLocation(src_bel);
auto sink_loc = getBelLocation(sink.cell->bel); auto sink_loc = getBelLocation(dst_bel);
if (driver.port == id_COUT) { if (src_pin == id_COUT) {
if (driver_loc.y == sink_loc.y) if (driver_loc.y == sink_loc.y)
return 0; return 0;
return 250; return 250;

View File

@ -387,16 +387,17 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
return (abs(dst.location.x - src.location.x) + abs(dst.location.y - src.location.y)) * (0.01 + 0.01); return (abs(dst.location.x - src.location.x) + abs(dst.location.y - src.location.y)) * (0.01 + 0.01);
} }
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
{ {
BelId src = net_info->driver.cell->bel; NPNR_UNUSED(src_pin);
BelId dst = sink.cell->bel; NPNR_UNUSED(dst_pin);
NPNR_ASSERT(src != BelId()); NPNR_ASSERT(src_bel != BelId());
NPNR_ASSERT(dst != BelId()); NPNR_ASSERT(dst_bel != BelId());
// TODO: Same deal applies here as with estimateDelay. // TODO: Same deal applies here as with estimateDelay.
return (abs(dst.location.x - src.location.x) + abs(dst.location.y - src.location.y)) * (0.01 + 0.01); return (abs(dst_bel.location.x - src_bel.location.x) + abs(dst_bel.location.y - src_bel.location.y)) *
(0.01 + 0.01);
} }
ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const

View File

@ -626,7 +626,7 @@ struct Arch : BaseArch<ArchRanges>
// Delay // Delay
delay_t estimateDelay(WireId src, WireId dst) const override; delay_t estimateDelay(WireId src, WireId dst) const override;
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override;
delay_t getDelayEpsilon() const override { return 0.001; } delay_t getDelayEpsilon() const override { return 0.001; }
delay_t getRipupDelayPenalty() const override { return 0.015; } delay_t getRipupDelayPenalty() const override { return 0.015; }
float getDelayNS(delay_t v) const override { return v; } float getDelayNS(delay_t v) const override { return v; }

View File

@ -418,7 +418,7 @@ struct Arch : BaseArch<ArchRanges>
// ------------------------------------------------- // -------------------------------------------------
delay_t estimateDelay(WireId src, WireId dst) const override; delay_t estimateDelay(WireId src, WireId dst) const override;
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override;
delay_t getDelayEpsilon() const override { return 10; }; delay_t getDelayEpsilon() const override { return 10; };
delay_t getRipupDelayPenalty() const override { return 100; }; delay_t getRipupDelayPenalty() const override { return 100; };
float getDelayNS(delay_t v) const override { return float(v) / 1000.0f; }; float getDelayNS(delay_t v) const override { return float(v) / 1000.0f; };

View File

@ -239,14 +239,12 @@ DelayQuad Arch::getPipDelay(PipId pip) const
return DelayQuad{308}; return DelayQuad{308};
} }
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
{ {
if (net_info->driver.cell == nullptr || net_info->driver.cell->bel == BelId()) NPNR_UNUSED(src_pin);
return 100; NPNR_UNUSED(dst_pin);
if (sink.cell->bel == BelId()) Loc src_loc = getBelLocation(src_bel);
return 100; Loc dst_loc = getBelLocation(dst_bel);
Loc src_loc = getBelLocation(net_info->driver.cell->bel);
Loc dst_loc = getBelLocation(sink.cell->bel);
return std::abs(dst_loc.y - src_loc.y) * 100 + std::abs(dst_loc.x - src_loc.x) * 100 + 100; return std::abs(dst_loc.y - src_loc.y) * 100 + std::abs(dst_loc.x - src_loc.x) * 100 + 100;
} }

View File

@ -603,16 +603,14 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
int dist_y = std::abs(src_y - dst_y); int dist_y = std::abs(src_y - dst_y);
return 75 * dist_x + 75 * dist_y + 250; return 75 * dist_x + 75 * dist_y + 250;
} }
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const delay_t Arch::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
{ {
if (net_info->driver.cell == nullptr || net_info->driver.cell->bel == BelId() || sink.cell->bel == BelId()) NPNR_UNUSED(src_pin);
if (dst_pin == id_FCI)
return 0; return 0;
if (sink.port == id_FCI) int src_x = src_bel.tile % chip_info->width, src_y = src_bel.tile / chip_info->width;
return 0;
int src_x = net_info->driver.cell->bel.tile % chip_info->width,
src_y = net_info->driver.cell->bel.tile / chip_info->width;
int dst_x = sink.cell->bel.tile % chip_info->width, dst_y = sink.cell->bel.tile / chip_info->width; int dst_x = dst_bel.tile % chip_info->width, dst_y = dst_bel.tile / chip_info->width;
int dist_x = std::abs(src_x - dst_x); int dist_x = std::abs(src_x - dst_x);
int dist_y = std::abs(src_y - dst_y); int dist_y = std::abs(src_y - dst_y);
return 100 * dist_x + 100 * dist_y + 250; return 100 * dist_x + 100 * dist_y + 250;

View File

@ -1291,7 +1291,7 @@ struct Arch : BaseArch<ArchRanges>
// ------------------------------------------------- // -------------------------------------------------
delay_t estimateDelay(WireId src, WireId dst) const override; delay_t estimateDelay(WireId src, WireId dst) const override;
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override;
delay_t getDelayEpsilon() const override { return 20; } delay_t getDelayEpsilon() const override { return 20; }
delay_t getRipupDelayPenalty() const override; delay_t getRipupDelayPenalty() const override;
delay_t getWireRipupDelayPenalty(WireId wire) const; delay_t getWireRipupDelayPenalty(WireId wire) const;