aboutsummaryrefslogtreecommitdiffstats
path: root/common/timing.cc
diff options
context:
space:
mode:
Diffstat (limited to 'common/timing.cc')
-rw-r--r--common/timing.cc176
1 files changed, 8 insertions, 168 deletions
diff --git a/common/timing.cc b/common/timing.cc
index f4c0d297..dd38ee45 100644
--- a/common/timing.cc
+++ b/common/timing.cc
@@ -273,6 +273,8 @@ void TimingAnalyser::reset_times()
dp.second.budget = 0;
}
port.second.worst_crit = 0;
+ port.second.worst_setup_slack = std::numeric_limits<delay_t>::max();
+ port.second.worst_hold_slack = std::numeric_limits<delay_t>::max();
}
}
@@ -440,9 +442,12 @@ void TimingAnalyser::compute_slack()
if (!setup_only)
pdp.second.hold_slack = arr.value.minDelay() - req.value.maxDelay();
pdp.second.max_path_length = arr.path_length + req.path_length;
+ pd.worst_setup_slack = std::min(pd.worst_setup_slack, pdp.second.setup_slack);
dp.worst_setup_slack = std::min(dp.worst_setup_slack, pdp.second.setup_slack);
- if (!setup_only)
+ if (!setup_only) {
+ pd.worst_hold_slack = std::min(pd.worst_hold_slack, pdp.second.hold_slack);
dp.worst_hold_slack = std::min(dp.worst_hold_slack, pdp.second.hold_slack);
+ }
}
}
}
@@ -615,7 +620,6 @@ struct CriticalPath
};
typedef std::unordered_map<ClockPair, CriticalPath> CriticalPathMap;
-typedef std::unordered_map<IdString, NetCriticalityInfo> NetCriticalityMap;
struct Timing
{
@@ -625,7 +629,6 @@ struct Timing
delay_t min_slack;
CriticalPathMap *crit_path;
DelayFrequency *slack_histogram;
- NetCriticalityMap *net_crit;
IdString async_clock;
struct TimingData
@@ -641,10 +644,9 @@ struct Timing
};
Timing(Context *ctx, bool net_delays, bool update, CriticalPathMap *crit_path = nullptr,
- DelayFrequency *slack_histogram = nullptr, NetCriticalityMap *net_crit = nullptr)
+ DelayFrequency *slack_histogram = nullptr)
: ctx(ctx), net_delays(net_delays), update(update), min_slack(1.0e12 / ctx->setting<float>("target_freq")),
- crit_path(crit_path), slack_histogram(slack_histogram), net_crit(net_crit),
- async_clock(ctx->id("$async$"))
+ crit_path(crit_path), slack_histogram(slack_histogram), async_clock(ctx->id("$async$"))
{
}
@@ -1025,156 +1027,6 @@ struct Timing
std::reverse(cp_ports.begin(), cp_ports.end());
}
}
-
- if (net_crit) {
- NPNR_ASSERT(crit_path);
- // Go through in reverse topological order to set required times
- for (auto net : boost::adaptors::reverse(topological_order)) {
- if (!net_data.count(net))
- continue;
- auto &nd_map = net_data.at(net);
- for (auto &startdomain : nd_map) {
- auto &nd = startdomain.second;
- if (nd.false_startpoint)
- continue;
- if (startdomain.first.clock == async_clock)
- continue;
- if (nd.min_required.empty())
- nd.min_required.resize(net->users.size(), std::numeric_limits<delay_t>::max());
- delay_t net_min_required = std::numeric_limits<delay_t>::max();
- for (size_t i = 0; i < net->users.size(); i++) {
- auto &usr = net->users.at(i);
- auto net_delay = ctx->getNetinfoRouteDelay(net, usr);
- int port_clocks;
- TimingPortClass portClass = ctx->getPortTimingClass(usr.cell, usr.port, port_clocks);
- if (portClass == TMG_REGISTER_INPUT || portClass == TMG_ENDPOINT) {
- auto process_endpoint = [&](IdString clksig, ClockEdge edge, delay_t setup) {
- delay_t period;
- // Set default period
- if (edge == startdomain.first.edge) {
- period = clk_period;
- } else {
- period = clk_period / 2;
- }
- if (clksig != async_clock) {
- if (ctx->nets.at(clksig)->clkconstr) {
- if (edge == startdomain.first.edge) {
- // same edge
- period = ctx->nets.at(clksig)->clkconstr->period.minDelay();
- } else if (edge == RISING_EDGE) {
- // falling -> rising
- period = ctx->nets.at(clksig)->clkconstr->low.minDelay();
- } else if (edge == FALLING_EDGE) {
- // rising -> falling
- period = ctx->nets.at(clksig)->clkconstr->high.minDelay();
- }
- }
- }
- nd.min_required.at(i) = std::min(period - setup, nd.min_required.at(i));
- };
- if (portClass == TMG_REGISTER_INPUT) {
- for (int j = 0; j < port_clocks; j++) {
- TimingClockingInfo clkInfo = ctx->getPortClockingInfo(usr.cell, usr.port, j);
- const NetInfo *clknet = get_net_or_empty(usr.cell, clkInfo.clock_port);
- IdString clksig = clknet ? clknet->name : async_clock;
- process_endpoint(clksig, clknet ? clkInfo.edge : RISING_EDGE,
- clkInfo.setup.maxDelay());
- }
- } else {
- process_endpoint(async_clock, RISING_EDGE, 0);
- }
- }
- net_min_required = std::min(net_min_required, nd.min_required.at(i) - net_delay);
- }
- PortRef &drv = net->driver;
- if (drv.cell == nullptr)
- continue;
- for (const auto &port : drv.cell->ports) {
- if (port.second.type != PORT_IN || !port.second.net)
- continue;
- DelayQuad comb_delay;
- bool is_path = ctx->getCellDelay(drv.cell, port.first, drv.port, comb_delay);
- if (!is_path)
- continue;
- int cc;
- auto pclass = ctx->getPortTimingClass(drv.cell, port.first, cc);
- if (pclass != TMG_COMB_INPUT)
- continue;
- NetInfo *sink_net = port.second.net;
- if (net_data.count(sink_net) && net_data.at(sink_net).count(startdomain.first)) {
- auto &sink_nd = net_data.at(sink_net).at(startdomain.first);
- if (sink_nd.min_required.empty())
- sink_nd.min_required.resize(sink_net->users.size(),
- std::numeric_limits<delay_t>::max());
- for (size_t i = 0; i < sink_net->users.size(); i++) {
- auto &user = sink_net->users.at(i);
- if (user.cell == drv.cell && user.port == port.first) {
- sink_nd.min_required.at(i) = std::min(sink_nd.min_required.at(i),
- net_min_required - comb_delay.maxDelay());
- break;
- }
- }
- }
- }
- }
- }
- std::unordered_map<ClockEvent, delay_t> worst_slack;
-
- // Assign slack values
- for (auto &net_entry : net_data) {
- const NetInfo *net = net_entry.first;
- for (auto &startdomain : net_entry.second) {
- auto &nd = startdomain.second;
- if (startdomain.first.clock == async_clock)
- continue;
- if (nd.min_required.empty())
- continue;
- auto &nc = (*net_crit)[net->name];
- if (nc.slack.empty())
- nc.slack.resize(net->users.size(), std::numeric_limits<delay_t>::max());
-
- for (size_t i = 0; i < net->users.size(); i++) {
- delay_t slack = nd.min_required.at(i) -
- (nd.max_arrival + ctx->getNetinfoRouteDelay(net, net->users.at(i)));
-
- if (worst_slack.count(startdomain.first))
- worst_slack.at(startdomain.first) = std::min(worst_slack.at(startdomain.first), slack);
- else
- worst_slack[startdomain.first] = slack;
- nc.slack.at(i) = slack;
- }
- if (ctx->debug)
- log_break();
- }
- }
- // Assign criticality values
- for (auto &net_entry : net_data) {
- const NetInfo *net = net_entry.first;
- for (auto &startdomain : net_entry.second) {
- if (startdomain.first.clock == async_clock)
- continue;
- auto &nd = startdomain.second;
- if (nd.min_required.empty())
- continue;
- auto &nc = (*net_crit)[net->name];
- if (nc.slack.empty())
- continue;
- if (nc.criticality.empty())
- nc.criticality.resize(net->users.size(), 0);
- // Only consider intra-clock paths for criticality
- if (!crit_path->count(ClockPair{startdomain.first, startdomain.first}))
- continue;
- delay_t dmax = crit_path->at(ClockPair{startdomain.first, startdomain.first}).path_delay;
- for (size_t i = 0; i < net->users.size(); i++) {
- float criticality =
- 1.0f - ((float(nc.slack.at(i)) - float(worst_slack.at(startdomain.first))) / dmax);
- nc.criticality.at(i) = std::min<double>(1.0, std::max<double>(0.0, criticality));
- }
- nc.max_path_length = nd.max_path_length;
- nc.cd_worst_slack = worst_slack.at(startdomain.first);
- }
- }
- }
return min_slack;
}
@@ -1528,16 +1380,4 @@ 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();
-
- // Test the new timing analyser, too
- TimingAnalyser sta_v2(ctx);
- sta_v2.setup();
-}
-
NEXTPNR_NAMESPACE_END