Add compute_fmax() with refactoring, plus print out Fmax estimate post-place and post-route
This commit is contained in:
parent
a21cc4dd5b
commit
760a47779a
@ -276,6 +276,7 @@ class SAPlacer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log_info("estimated Fmax = %.2f MHz\n", compute_fmax(ctx) / 1e6);
|
||||||
ctx->unlock();
|
ctx->unlock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -815,6 +815,7 @@ bool router1(Context *ctx)
|
|||||||
ctx->check();
|
ctx->check();
|
||||||
ctx->unlock();
|
ctx->unlock();
|
||||||
#endif
|
#endif
|
||||||
|
log_info("estimated Fmax = %.2f MHz\n", compute_fmax(ctx) / 1e6);
|
||||||
return true;
|
return true;
|
||||||
} catch (log_execution_error_exception) {
|
} catch (log_execution_error_exception) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -76,10 +76,35 @@ static delay_t follow_net(Context *ctx, NetInfo *net, int path_length, delay_t s
|
|||||||
return net_budget;
|
return net_budget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void assign_budget(Context *ctx)
|
static UpdateMap compute_min_slack(Context *ctx, delay_t &min_slack)
|
||||||
{
|
{
|
||||||
UpdateMap updates;
|
UpdateMap updates;
|
||||||
delay_t min_slack = delay_t(1.0e12 / ctx->target_freq);
|
delay_t default_slack = delay_t(1.0e12 / ctx->target_freq);
|
||||||
|
|
||||||
|
// Go through all clocked drivers and distribute the available path
|
||||||
|
// slack evenly into the budget of every sink on the path ---
|
||||||
|
// record this value into the UpdateMap
|
||||||
|
for (auto &cell : ctx->cells) {
|
||||||
|
for (auto port : cell.second->ports) {
|
||||||
|
if (port.second.type == PORT_OUT) {
|
||||||
|
IdString clock_domain = ctx->getPortClock(cell.second.get(), port.first);
|
||||||
|
if (clock_domain != IdString()) {
|
||||||
|
delay_t slack = default_slack; // TODO: clock constraints
|
||||||
|
delay_t clkToQ;
|
||||||
|
if (ctx->getCellDelay(cell.second.get(), clock_domain, port.first, clkToQ))
|
||||||
|
slack -= clkToQ;
|
||||||
|
if (port.second.net)
|
||||||
|
follow_net(ctx, port.second.net, 0, slack, updates, min_slack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return updates;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign_budget(Context *ctx)
|
||||||
|
{
|
||||||
|
|
||||||
log_break();
|
log_break();
|
||||||
log_info("Annotating ports with timing budgets\n");
|
log_info("Annotating ports with timing budgets\n");
|
||||||
@ -90,26 +115,12 @@ void assign_budget(Context *ctx)
|
|||||||
usr.budget = default_slack;
|
usr.budget = default_slack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
min_slack = default_slack;
|
|
||||||
// Go through all clocked drivers and set up paths
|
|
||||||
for (auto &cell : ctx->cells) {
|
|
||||||
for (auto port : cell.second->ports) {
|
|
||||||
if (port.second.type == PORT_OUT) {
|
|
||||||
IdString clock_domain = ctx->getPortClock(cell.second.get(), port.first);
|
|
||||||
if (clock_domain != IdString()) {
|
|
||||||
delay_t slack = delay_t(1.0e12 / ctx->target_freq); // TODO: clock constraints
|
|
||||||
delay_t clkToQ;
|
|
||||||
if (ctx->getCellDelay(cell.second.get(), clock_domain, port.first, clkToQ))
|
|
||||||
slack -= clkToQ;
|
|
||||||
if (port.second.net) {
|
|
||||||
log_break();
|
|
||||||
follow_net(ctx, port.second.net, 0, slack, updates, min_slack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
delay_t min_slack = default_slack;
|
||||||
|
auto updates = compute_min_slack(ctx, min_slack);
|
||||||
|
|
||||||
|
// If user has not specified a frequency, adjust the target frequency
|
||||||
|
// to be equivalent to the critical path
|
||||||
if (!ctx->user_freq) {
|
if (!ctx->user_freq) {
|
||||||
ctx->target_freq = 1e12 / (default_slack - min_slack);
|
ctx->target_freq = 1e12 / (default_slack - min_slack);
|
||||||
if (ctx->verbose)
|
if (ctx->verbose)
|
||||||
@ -145,27 +156,12 @@ void assign_budget(Context *ctx)
|
|||||||
|
|
||||||
void update_budget(Context *ctx)
|
void update_budget(Context *ctx)
|
||||||
{
|
{
|
||||||
UpdateMap updates;
|
|
||||||
delay_t default_slack = delay_t(1.0e12 / ctx->target_freq);
|
delay_t default_slack = delay_t(1.0e12 / ctx->target_freq);
|
||||||
delay_t min_slack = delay_t(1.0e12 / ctx->target_freq);
|
delay_t min_slack = default_slack;
|
||||||
|
auto updates = compute_min_slack(ctx, min_slack);
|
||||||
// Go through all clocked drivers and distribute the available path slack evenly into every budget
|
|
||||||
for (auto &cell : ctx->cells) {
|
|
||||||
for (auto& port : cell.second->ports) {
|
|
||||||
if (port.second.type == PORT_OUT) {
|
|
||||||
IdString clock_domain = ctx->getPortClock(cell.second.get(), port.first);
|
|
||||||
if (clock_domain != IdString()) {
|
|
||||||
delay_t slack = default_slack; // TODO: clock constraints
|
|
||||||
delay_t clkToQ;
|
|
||||||
if (ctx->getCellDelay(cell.second.get(), clock_domain, port.first, clkToQ))
|
|
||||||
slack -= clkToQ;
|
|
||||||
if (port.second.net)
|
|
||||||
follow_net(ctx, port.second.net, 0, slack, updates, min_slack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// If user has not specified a frequency, adjust the target frequency
|
||||||
|
// to be +5% higher than the current critical path
|
||||||
if (!ctx->user_freq) {
|
if (!ctx->user_freq) {
|
||||||
ctx->target_freq = 1.05 * (1e12 / (default_slack - min_slack));
|
ctx->target_freq = 1.05 * (1e12 / (default_slack - min_slack));
|
||||||
if (ctx->verbose)
|
if (ctx->verbose)
|
||||||
@ -199,4 +195,12 @@ void update_budget(Context *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float compute_fmax(Context *ctx)
|
||||||
|
{
|
||||||
|
delay_t default_slack = delay_t(1.0e12 / ctx->target_freq);
|
||||||
|
delay_t min_slack = default_slack;
|
||||||
|
compute_min_slack(ctx, min_slack);
|
||||||
|
return 1e12 / (default_slack - min_slack);
|
||||||
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -27,8 +27,11 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||||||
// Assign "budget" values for all user ports in the design
|
// Assign "budget" values for all user ports in the design
|
||||||
void assign_budget(Context *ctx);
|
void assign_budget(Context *ctx);
|
||||||
|
|
||||||
|
// Evenly redistribute the total path slack amongst all sinks on each path
|
||||||
void update_budget(Context *ctx);
|
void update_budget(Context *ctx);
|
||||||
|
|
||||||
|
float compute_fmax(Context *ctx);
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user