diff options
author | David Shah <dave@ds0.me> | 2018-12-01 13:43:12 +0000 |
---|---|---|
committer | David Shah <dave@ds0.me> | 2018-12-06 10:53:01 +0000 |
commit | 2de506c071b090c18977a594efbd6effd0315bf5 (patch) | |
tree | 20565f5f9f84a947641944b37a9bf30708d7c06a | |
parent | 83e32775775cc06d0f70a18e2a18089c38ff3c35 (diff) | |
download | nextpnr-2de506c071b090c18977a594efbd6effd0315bf5.tar.gz nextpnr-2de506c071b090c18977a594efbd6effd0315bf5.tar.bz2 nextpnr-2de506c071b090c18977a594efbd6effd0315bf5.zip |
timing_opt: Functions to calculate arc delay limits
Signed-off-by: David Shah <dave@ds0.me>
-rw-r--r-- | common/timing.cc | 17 | ||||
-rw-r--r-- | common/timing.h | 13 | ||||
-rw-r--r-- | 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<delay_t> slack; - std::vector<float> criticality; - unsigned max_path_length = 0; -}; + typedef std::unordered_map<ClockPair, CriticalPath> CriticalPathMap; typedef std::unordered_map<IdString, NetCriticalityInfo> 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<delay_t> slack; + std::vector<float> criticality; + unsigned max_path_length = 0; + delay_t cd_worst_slack = std::numeric_limits<delay_t>::max(); +}; + +typedef std::unordered_map<IdString, NetCriticalityInfo> 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<delay_t>::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<IdString> path_cells; std::unordered_map<IdString, std::unordered_set<BelId>> cell_neighbour_bels; std::unordered_map<BelId, std::unordered_set<IdString>> bel_candidate_cells; - // Map net users to net delay limit - std::unordered_map<IdString, std::vector<delay_t>> max_net_delay; + // Map cell ports to net delay limit + std::unordered_map<std::pair<IdString, IdString>, delay_t> max_net_delay; + // Criticality data from timing analysis + NetCriticalityMap net_crit; + Context *ctx; }; |