aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddie Hung <e.hung@imperial.ac.uk>2018-07-25 18:21:39 -0700
committerEddie Hung <e.hung@imperial.ac.uk>2018-07-25 18:21:39 -0700
commit760a47779aca8aabbc11b4a769e987a1ce42ad0c (patch)
tree06aa1a8bb02876854ddfa8aa2d182bb2a5c06222
parenta21cc4dd5bbbf1c9e5894d8c30a2c3252d21dfd0 (diff)
downloadnextpnr-760a47779aca8aabbc11b4a769e987a1ce42ad0c.tar.gz
nextpnr-760a47779aca8aabbc11b4a769e987a1ce42ad0c.tar.bz2
nextpnr-760a47779aca8aabbc11b4a769e987a1ce42ad0c.zip
Add compute_fmax() with refactoring, plus print out Fmax estimate post-place and post-route
-rw-r--r--common/placer1.cc1
-rw-r--r--common/router1.cc1
-rw-r--r--common/timing.cc76
-rw-r--r--common/timing.h3
4 files changed, 45 insertions, 36 deletions
diff --git a/common/placer1.cc b/common/placer1.cc
index 30f0057c..d38cdd4b 100644
--- a/common/placer1.cc
+++ b/common/placer1.cc
@@ -276,6 +276,7 @@ class SAPlacer
}
}
}
+ log_info("estimated Fmax = %.2f MHz\n", compute_fmax(ctx) / 1e6);
ctx->unlock();
return true;
}
diff --git a/common/router1.cc b/common/router1.cc
index dbf97af7..8664819f 100644
--- a/common/router1.cc
+++ b/common/router1.cc
@@ -815,6 +815,7 @@ bool router1(Context *ctx)
ctx->check();
ctx->unlock();
#endif
+ log_info("estimated Fmax = %.2f MHz\n", compute_fmax(ctx) / 1e6);
return true;
} catch (log_execution_error_exception) {
#ifndef NDEBUG
diff --git a/common/timing.cc b/common/timing.cc
index 2c467961..784952f8 100644
--- a/common/timing.cc
+++ b/common/timing.cc
@@ -76,40 +76,51 @@ static delay_t follow_net(Context *ctx, NetInfo *net, int path_length, delay_t s
return net_budget;
}
-void assign_budget(Context *ctx)
+static UpdateMap compute_min_slack(Context *ctx, delay_t &min_slack)
{
UpdateMap updates;
- delay_t min_slack = delay_t(1.0e12 / ctx->target_freq);
-
- log_break();
- log_info("Annotating ports with timing budgets\n");
- // Clear delays to a very high value first
delay_t default_slack = delay_t(1.0e12 / ctx->target_freq);
- for (auto &net : ctx->nets) {
- for (auto &usr : net.second->users) {
- usr.budget = default_slack;
- }
- }
- min_slack = default_slack;
- // Go through all clocked drivers and set up paths
+
+ // 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 = delay_t(1.0e12 / ctx->target_freq); // TODO: clock constraints
+ 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) {
- log_break();
+ 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_info("Annotating ports with timing budgets\n");
+ // Clear delays to a very high value first
+ delay_t default_slack = delay_t(1.0e12 / ctx->target_freq);
+ for (auto &net : ctx->nets) {
+ for (auto &usr : net.second->users) {
+ usr.budget = default_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) {
ctx->target_freq = 1e12 / (default_slack - min_slack);
if (ctx->verbose)
@@ -145,27 +156,12 @@ void assign_budget(Context *ctx)
void update_budget(Context *ctx)
{
- UpdateMap updates;
delay_t default_slack = delay_t(1.0e12 / ctx->target_freq);
- delay_t min_slack = delay_t(1.0e12 / ctx->target_freq);
-
- // 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);
- }
- }
- }
- }
+ 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 +5% higher than the current critical path
if (!ctx->user_freq) {
ctx->target_freq = 1.05 * (1e12 / (default_slack - min_slack));
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
diff --git a/common/timing.h b/common/timing.h
index b5574392..22aa40c7 100644
--- a/common/timing.h
+++ b/common/timing.h
@@ -27,8 +27,11 @@ NEXTPNR_NAMESPACE_BEGIN
// Assign "budget" values for all user ports in the design
void assign_budget(Context *ctx);
+// Evenly redistribute the total path slack amongst all sinks on each path
void update_budget(Context *ctx);
+float compute_fmax(Context *ctx);
+
NEXTPNR_NAMESPACE_END
#endif