timing_opt: Functions to calculate arc delay limits

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2018-12-01 13:43:12 +00:00
parent 83e3277577
commit 2de506c071
3 changed files with 74 additions and 11 deletions

View File

@ -85,14 +85,7 @@ struct CriticalPath
delay_t path_period; 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<ClockPair, CriticalPath> CriticalPathMap;
typedef std::unordered_map<IdString, NetCriticalityInfo> NetCriticalityMap; 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.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.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 NEXTPNR_NAMESPACE_END

View File

@ -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, void timing_analysis(Context *ctx, bool slack_histogram = true, bool print_fmax = true, bool print_path = false,
bool warn_on_failure = 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 NEXTPNR_NAMESPACE_END
#endif #endif

View File

@ -23,8 +23,10 @@
* https://www.cerc.utexas.edu/utda/publications/C205.pdf * https://www.cerc.utexas.edu/utda/publications/C205.pdf
*/ */
#include "timing.h"
#include "timing_opt.h" #include "timing_opt.h"
#include "nextpnr.h" #include "nextpnr.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
class TimingOptimiser class TimingOptimiser
@ -37,8 +39,52 @@ class TimingOptimiser
// Ratio of available to already-candidates to begin borrowing // Ratio of available to already-candidates to begin borrowing
const float borrow_thresh = 0.2; 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) { 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) { bool acceptable_bel_candidate(CellInfo *cell, BelId newBel) {
@ -109,8 +155,11 @@ unbind:
std::vector<IdString> path_cells; std::vector<IdString> path_cells;
std::unordered_map<IdString, std::unordered_set<BelId>> cell_neighbour_bels; std::unordered_map<IdString, std::unordered_set<BelId>> cell_neighbour_bels;
std::unordered_map<BelId, std::unordered_set<IdString>> bel_candidate_cells; std::unordered_map<BelId, std::unordered_set<IdString>> bel_candidate_cells;
// Map net users to net delay limit // Map cell ports to net delay limit
std::unordered_map<IdString, std::vector<delay_t>> max_net_delay; std::unordered_map<std::pair<IdString, IdString>, delay_t> max_net_delay;
// Criticality data from timing analysis
NetCriticalityMap net_crit;
Context *ctx; Context *ctx;
}; };