From 2de506c071b090c18977a594efbd6effd0315bf5 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 1 Dec 2018 13:43:12 +0000 Subject: [PATCH] timing_opt: Functions to calculate arc delay limits Signed-off-by: David Shah --- common/timing.cc | 17 +++++++------- common/timing.h | 13 +++++++++++ common/timing_opt.cc | 55 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/common/timing.cc b/common/timing.cc index ebe3a177..1f48261d 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -85,14 +85,7 @@ struct CriticalPath delay_t path_period; }; -// Data for the timing optimisation algorithm -struct NetCriticalityInfo -{ - // One each per user - std::vector slack; - std::vector criticality; - unsigned max_path_length = 0; -}; + typedef std::unordered_map CriticalPathMap; typedef std::unordered_map NetCriticalityMap; @@ -599,6 +592,7 @@ struct Timing nc.criticality.at(i) = std::max(nc.criticality.at(i), criticality); } nc.max_path_length = std::max(nc.max_path_length, nd.max_path_length); + nc.cd_worst_slack = std::min(nc.cd_worst_slack, worst_slack.at(startdomain.first)); } } } @@ -914,4 +908,11 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p } } +void get_criticalities(Context *ctx, NetCriticalityMap *net_crit) { + CriticalPathMap crit_paths; + net_crit->clear(); + Timing timing(ctx, true, true, &crit_paths, nullptr, net_crit); + timing.walk_paths(); +} + NEXTPNR_NAMESPACE_END diff --git a/common/timing.h b/common/timing.h index 42f928dc..f1d18e8a 100644 --- a/common/timing.h +++ b/common/timing.h @@ -32,6 +32,19 @@ void assign_budget(Context *ctx, bool quiet = false); void timing_analysis(Context *ctx, bool slack_histogram = true, bool print_fmax = true, bool print_path = false, bool warn_on_failure = false); +// Data for the timing optimisation algorithm +struct NetCriticalityInfo +{ + // One each per user + std::vector slack; + std::vector criticality; + unsigned max_path_length = 0; + delay_t cd_worst_slack = std::numeric_limits::max(); +}; + +typedef std::unordered_map NetCriticalityMap; +void get_criticalities(Context *ctx, NetCriticalityMap *net_crit); + NEXTPNR_NAMESPACE_END #endif diff --git a/common/timing_opt.cc b/common/timing_opt.cc index de8e00a5..97860a23 100644 --- a/common/timing_opt.cc +++ b/common/timing_opt.cc @@ -23,8 +23,10 @@ * https://www.cerc.utexas.edu/utda/publications/C205.pdf */ +#include "timing.h" #include "timing_opt.h" #include "nextpnr.h" +#include "util.h" NEXTPNR_NAMESPACE_BEGIN class TimingOptimiser @@ -37,8 +39,52 @@ class TimingOptimiser // Ratio of available to already-candidates to begin borrowing const float borrow_thresh = 0.2; + void setup_delay_limits() { + for (auto net : sorted(ctx->nets)) { + NetInfo *ni = net.second; + max_net_delay[ni].clear(); + max_net_delay[ni].resize(ni->users.size(), std::numeric_limits::max()); + if (!net_crit.count(net.first)) + continue; + auto &nc = net_crit.at(net.first); + if (nc.slack.empty()) + continue; + for (size_t i = 0; i < ni->users.size(); i++) { + delay_t net_delay = ctx->getNetinfoRouteDelay(ni, ni->users.at(i)); + max_net_delay[ni].at(i) = net_delay + ((nc.slack.at(i) - nc.cd_worst_slack) / nc.max_path_length); + } + } + } + bool check_cell_delay_limits(CellInfo *cell) { - + for (const auto &port : cell->ports) { + int nc; + if (ctx->getPortTimingClass(cell, port.first, nc) == TMG_IGNORE) + continue; + NetInfo *net = port.second.net; + if (net == nullptr) + continue; + if (port.second.type == PORT_IN) { + if (net->driver.cell == nullptr || net->driver.cell->bel == BelId()) + continue; + BelId srcBel = net->driver.cell->bel; + if (ctx->estimateDelay(ctx->getBelPinWire(srcBel, net->driver.port), + ctx->getBelPinWire(cell->bel, port.first)) > max_net_delay.at(std::make_pair(cell->name, port.first))) + return false; + } else if (port.second.type == PORT_OUT) { + for (auto user : net->users) { + // This could get expensive for high-fanout nets?? + BelId dstBel = user.cell->bel; + if (dstBel == BelId()) + continue; + if (ctx->estimateDelay(ctx->getBelPinWire(cell->bel, port.first), + ctx->getBelPinWire(dstBel, user.port)) > max_net_delay.at(std::make_pair(user.cell->name, user.port))) + return false; + } + } + + } + return true; } bool acceptable_bel_candidate(CellInfo *cell, BelId newBel) { @@ -109,8 +155,11 @@ unbind: std::vector path_cells; std::unordered_map> cell_neighbour_bels; std::unordered_map> bel_candidate_cells; - // Map net users to net delay limit - std::unordered_map> max_net_delay; + // Map cell ports to net delay limit + std::unordered_map, delay_t> max_net_delay; + // Criticality data from timing analysis + NetCriticalityMap net_crit; + Context *ctx; };