diff --git a/common/kernel/timing.cc b/common/kernel/timing.cc index 6d53594a..bf3420bc 100644 --- a/common/kernel/timing.cc +++ b/common/kernel/timing.cc @@ -25,7 +25,6 @@ #include #include #include -#include "log.h" #include "util.h" NEXTPNR_NAMESPACE_BEGIN @@ -75,7 +74,6 @@ void TimingAnalyser::run(bool update_route_delays, bool update_net_timings, bool } if (update_crit_paths) { - get_min_delay_violations(); build_crit_path_reports(); } } @@ -575,8 +573,6 @@ void TimingAnalyser::walk_forward() for (auto &fanin : pd.cell_arcs) { if (fanin.type == CellArc::CLK_TO_Q && fanin.other_port == sp.second) { init_arrival = init_arrival + fanin.value.delayPair(); - // printf("walk_forward %s.%s: init_arrival to %d - %d\n", sp.first.cell.c_str(ctx), - // sp.first.port.c_str(ctx), init_arrival.min_delay, init_arrival.max_delay); break; } } @@ -597,10 +593,6 @@ void TimingAnalyser::walk_forward() CellPortKey usr_key(usr); auto &usr_pd = ports.at(usr_key); auto next_arr = arr.second.value + usr_pd.route_delay; - printf("walk_forward: propagate routing from %s.%s to %s.%s, %d - %d\n", p.cell.c_str(ctx), - p.port.c_str(ctx), usr_key.cell.c_str(ctx), usr_key.port.c_str(ctx), next_arr.min_delay, - next_arr.max_delay); - set_arrival_time(usr_key, arr.first, next_arr, arr.second.path_length, p); } } else if (pd.type == PORT_IN) { @@ -610,10 +602,6 @@ void TimingAnalyser::walk_forward() continue; auto next_arr = arr.second.value + fanout.value.delayPair(); - - printf("walk_forward: propagate through cell from %s.%s to %s.%s, %d - %d\n", p.cell.c_str(ctx), - p.port.c_str(ctx), p.cell.c_str(ctx), fanout.other_port.c_str(ctx), next_arr.min_delay, - next_arr.max_delay); set_arrival_time(CellPortKey(p.cell, fanout.other_port), arr.first, next_arr, arr.second.path_length + 1, p); } @@ -730,13 +718,6 @@ void TimingAnalyser::compute_slack() 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); } - // printf("max arr: %d, min req: %d, c2c: %d, setup slack: %d\n", arr.value.maxDelay(), - // req.value.minDelay(), - // clock_to_clock, pdp.second.setup_slack); - // if (!setup_only) { - // printf("min arr: %d, max req: %d, c2c: %d, hold slack: %d\n", arr.value.minDelay(), - // req.value.maxDelay(), clock_to_clock, pdp.second.hold_slack); - // } } } } @@ -869,13 +850,6 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair, std::vector crit_path_rev; auto cursor = endpoint; - auto next_cursor = [longest_path](ArrivReqTime &arrival) { - if (longest_path) { - return arrival.bwd_max; - } - return arrival.bwd_min; - }; - while (cursor != CellPortKey()) { auto cell = cell_info(cursor); auto &port = port_info(cursor); @@ -892,7 +866,11 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair, if (!ports.at(cursor).arrival.count(dp.key.launch)) break; - cursor = next_cursor(ports.at(cursor).arrival.at(dp.key.launch)); + if (longest_path) { + cursor = ports.at(cursor).arrival.at(dp.key.launch).bwd_max; + } else { + cursor = ports.at(cursor).arrival.at(dp.key.launch).bwd_min; + } } auto crit_path = boost::adaptors::reverse(crit_path_rev); @@ -989,6 +967,10 @@ void TimingAnalyser::build_crit_path_reports() auto &empty_clocks = result.empty_paths; auto &clock_delays_ctx = result.clock_delays; + if (!setup_only) { + result.min_delay_violations = get_min_delay_violations(); + } + auto delay_by_domain = max_delay_by_domain_pairs(); for (int i = 0; i < int(domains.size()); i++) { @@ -1105,26 +1087,6 @@ void TimingAnalyser::build_slack_histogram_report() } } -std::string arc_typ_to_str(TimingAnalyser::CellArc::ArcType typ) -{ - switch (typ) { - case TimingAnalyser::CellArc::COMBINATIONAL: - return "COMBINATIONAL"; - case TimingAnalyser::CellArc::SETUP: - return "SETUP"; - case TimingAnalyser::CellArc::HOLD: - return "HOLD"; - case TimingAnalyser::CellArc::CLK_TO_Q: - return "CLK_TO_Q"; - case TimingAnalyser::CellArc::STARTPOINT: - return "STARTPOINT"; - case TimingAnalyser::CellArc::ENDPOINT: - return "ENDPOINT"; - default: - return "IMPOSSIBRU"; - } -} - std::vector TimingAnalyser::get_min_delay_violations() { std::vector violations; @@ -1144,17 +1106,14 @@ std::vector TimingAnalyser::get_min_delay_violations() DelayPair period = clk_net->clkconstr->period; - printf("Clock %s.%s with period %f - %f\n", clk_net->driver.cell->name.c_str(ctx), - clk_net->driver.port.c_str(ctx), ctx->getDelayNS(period.minDelay()), ctx->getDelayNS(period.maxDelay())); - - for (auto &sp : capture.endpoints) { - CellInfo *ci = cell_info(sp.first); + for (auto &ep : capture.endpoints) { + CellInfo *ci = cell_info(ep.first); int clkInfoCount = 0; - TimingPortClass cls = ctx->getPortTimingClass(ci, sp.first.port, clkInfoCount); + TimingPortClass cls = ctx->getPortTimingClass(ci, ep.first.port, clkInfoCount); if (cls != TMG_REGISTER_INPUT) continue; - auto &port = ports.at(sp.first); + auto &port = ports.at(ep.first); auto &req = port.required.at(capture_id); @@ -1177,10 +1136,12 @@ std::vector TimingAnalyser::get_min_delay_violations() auto hold_slack = arr.value.minDelay() - req.value.maxDelay() + clock_to_clock; - printf("endpoint: %s.%s, arr: %f - %f, req: %f - %f, hold slack: %f\n", sp.first.cell.c_str(ctx), - sp.first.port.c_str(ctx), ctx->getDelayNS(arr.value.minDelay()), - ctx->getDelayNS(arr.value.maxDelay()), ctx->getDelayNS(req.value.minDelay()), - ctx->getDelayNS(req.value.maxDelay()), ctx->getDelayNS(hold_slack)); + auto violated = true; + + if (violated) { + const auto dom_pair_id = domain_pair_id(launch_id, capture_id); + violations.emplace_back(build_critical_path_report(dom_pair_id, ep.first, false)); + } } } } @@ -1222,6 +1183,26 @@ void TimingAnalyser::copy_domains(const CellPortKey &from, const CellPortKey &to } } +const std::string TimingAnalyser::arcType_to_str(CellArc::ArcType typ) +{ + switch (typ) { + case TimingAnalyser::CellArc::COMBINATIONAL: + return "COMBINATIONAL"; + case TimingAnalyser::CellArc::SETUP: + return "SETUP"; + case TimingAnalyser::CellArc::HOLD: + return "HOLD"; + case TimingAnalyser::CellArc::CLK_TO_Q: + return "CLK_TO_Q"; + case TimingAnalyser::CellArc::STARTPOINT: + return "STARTPOINT"; + case TimingAnalyser::CellArc::ENDPOINT: + return "ENDPOINT"; + default: + log_error("Impossible CellArc::ArcType\n"); + } +} + CellInfo *TimingAnalyser::cell_info(const CellPortKey &key) { return ctx->cells.at(key.cell).get(); } PortInfo &TimingAnalyser::port_info(const CellPortKey &key) { return ctx->cells.at(key.cell)->ports.at(key.port); } diff --git a/common/kernel/timing.h b/common/kernel/timing.h index 80b3079c..ac78be4b 100644 --- a/common/kernel/timing.h +++ b/common/kernel/timing.h @@ -225,6 +225,8 @@ struct TimingAnalyser void copy_domains(const CellPortKey &from, const CellPortKey &to, bool backwards); + [[maybe_unused]] static const std::string arcType_to_str(CellArc::ArcType typ); + dict ports; dict domain_to_id; dict pair_to_id; diff --git a/common/kernel/timing_log.cc b/common/kernel/timing_log.cc index 24aac665..339c0b86 100644 --- a/common/kernel/timing_log.cc +++ b/common/kernel/timing_log.cc @@ -168,7 +168,20 @@ static void log_crit_paths(const Context *ctx, TimingResult &result) log_info("Critical path report for cross-domain path '%s' -> '%s':\n", start.c_str(), end.c_str()); print_path_report(report); } -}; + + // Min delay violated paths + for (auto &report : result.min_delay_violations) { + log_break(); + std::string start = clock_event_name(ctx, report.clock_pair.start); + std::string end = clock_event_name(ctx, report.clock_pair.end); + if (report.clock_pair.start == report.clock_pair.end) { + log_info("Hold time violations for clock '%s':\n", start.c_str()); + } else { + log_info("Hold time violations for path '%s' -> '%s':\n", start.c_str(), end.c_str()); + } + print_path_report(report); + } +} static void log_fmax(Context *ctx, TimingResult &result, bool warn_on_failure) {