diff --git a/common/kernel/timing.cc b/common/kernel/timing.cc index 9cfc397f..f44adfa6 100644 --- a/common/kernel/timing.cc +++ b/common/kernel/timing.cc @@ -48,9 +48,12 @@ TimingAnalyser::TimingAnalyser(Context *ctx) : ctx(ctx) domain_to_id.emplace(key, 0); domains.emplace_back(key); async_clock_id = 0; + + domain_pair_id(async_clock_id, async_clock_id); }; -void TimingAnalyser::setup(bool update_net_timings, bool update_histogram, bool update_crit_paths, bool update_route_delays) +void TimingAnalyser::setup(bool update_net_timings, bool update_histogram, bool update_crit_paths, + bool update_route_delays) { init_ports(); get_cell_delays(); @@ -60,7 +63,8 @@ void TimingAnalyser::setup(bool update_net_timings, bool update_histogram, bool run(update_net_timings, update_histogram, update_crit_paths, update_route_delays); } -void TimingAnalyser::run(bool update_net_timings, bool update_histogram, bool update_crit_paths, bool update_route_delays) +void TimingAnalyser::run(bool update_net_timings, bool update_histogram, bool update_crit_paths, + bool update_route_delays) { reset_times(); if (update_route_delays) @@ -757,21 +761,11 @@ void TimingAnalyser::build_detailed_net_timing_report() auto &capture = domains.at(req.first).key; NetSinkTiming sink_timing; - sink_timing.clock_pair = ClockPair { - .start = ClockEvent { - .clock = launch.clock, - .edge = launch.edge - }, - .end = ClockEvent { - .clock = capture.clock, - .edge = capture.edge - } - }; + sink_timing.clock_pair = ClockPair{.start = ClockEvent{.clock = launch.clock, .edge = launch.edge}, + .end = ClockEvent{.clock = capture.clock, .edge = capture.edge}}; sink_timing.cell_port = std::make_pair(pd.cell_port.cell, pd.cell_port.port); sink_timing.delay = arr.second.value.max_delay; - log_info("update net_timings: %s: %f\n", net->name.c_str(ctx), (float) sink_timing.delay); - net_timings[net->name].push_back(sink_timing); } } @@ -806,6 +800,32 @@ std::vector TimingAnalyser::get_worst_eps(domain_id_t domain_pair, return worst_eps; } +static std::string tgp_to_string(TimingPortClass c) +{ + switch (c) { + case TMG_CLOCK_INPUT: + return "TMG_CLOCK_INPUT"; + case TMG_GEN_CLOCK: + return "TMG_GEN_CLOCK"; + case TMG_REGISTER_INPUT: + return "TMG_REGISTER_INPUT"; + case TMG_REGISTER_OUTPUT: + return "TMG_REGISTER_OUTPUT"; + case TMG_COMB_INPUT: + return "TMG_COMB_INPUT"; + case TMG_COMB_OUTPUT: + return "TMG_COMB_OUTPUT"; + case TMG_STARTPOINT: + return "TMG_STARTPOINT"; + case TMG_ENDPOINT: + return "TMG_ENDPOINT"; + case TMG_IGNORE: + return "TMG_IGNORE"; + } + + return "UNKNOWN"; +} + CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair, CellPortKey endpoint) { CriticalPath report; @@ -814,16 +834,8 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair, auto &launch = domains.at(dp.key.launch).key; auto &capture = domains.at(dp.key.capture).key; - report.clock_pair = ClockPair { - .start = ClockEvent { - .clock = launch.clock, - .edge = launch.edge - }, - .end = ClockEvent { - .clock = capture.clock, - .edge = capture.edge - } - }; + report.clock_pair = ClockPair{.start = ClockEvent{.clock = launch.clock, .edge = launch.edge}, + .end = ClockEvent{.clock = capture.clock, .edge = capture.edge}}; report.period = ctx->getDelayFromNS(1.0e9 / ctx->setting("target_freq")); if (launch.edge != capture.edge) { @@ -842,19 +854,20 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair, std::vector crit_path_rev; auto cursor = endpoint; + + log_info("Analyzing %s -> %s\n", clock_event_name(ctx, launch).c_str(), clock_event_name(ctx, capture).c_str()); while (cursor != CellPortKey()) { auto cell = cell_info(cursor); - auto& port = port_info(cursor); + auto &port = port_info(cursor); int port_clocks; auto portClass = ctx->getPortTimingClass(cell, port.name, port_clocks); - if (portClass != TMG_CLOCK_INPUT && - portClass != TMG_ENDPOINT && - portClass != TMG_IGNORE && - port.type == PortType::PORT_IN) - { - crit_path_rev.emplace_back(PortRef { cell, port.name }); + log_info("\tcursor at %s.%s tmg: %s, port dir: %s\n", cell->name.c_str(ctx), port.name.c_str(ctx), + tgp_to_string(portClass).c_str(), port.type == PortType::PORT_IN ? "PORT_IN" : "PORT_X"); + + if (portClass != TMG_CLOCK_INPUT && portClass != TMG_IGNORE && port.type == PortType::PORT_IN) { + crit_path_rev.emplace_back(PortRef{cell, port.name}); } if (!ports.at(cursor).arrival.count(dp.key.launch)) break; @@ -959,15 +972,8 @@ void TimingAnalyser::build_crit_path_reports() auto delay_by_domain = max_delay_by_domain_pairs(); - auto uq_doms = ctx->timing_result.empty_paths; - auto clock_pairs = std::vector>(); - - for (int i = 0; i < int(domain_pairs.size()); i++) { - auto &dp = domain_pairs.at(i); - auto &launch = domains.at(dp.key.launch).key; - auto &capture = domains.at(dp.key.capture).key; - - clock_pairs.emplace_back(std::make_pair(launch, capture)); + for (int i = 0; i < int(domains.size()); i++) { + empty_clocks.insert(domains.at(i).key.clock); } for (int i = 0; i < int(domain_pairs.size()); i++) { @@ -1005,9 +1011,15 @@ void TimingAnalyser::build_crit_path_reports() auto &launch = domains.at(dp.key.launch).key; auto &capture = domains.at(dp.key.capture).key; - if (launch.clock == capture.clock) + log_info("testin testing %s -> %s\n", clock_event_name(ctx, launch).c_str(), + clock_event_name(ctx, capture).c_str()); + + if (launch.clock == capture.clock && !launch.is_async()) continue; + log_info("testin testing2 %s -> %s\n", clock_event_name(ctx, launch).c_str(), + clock_event_name(ctx, capture).c_str()); + auto worst_endpoint = get_worst_eps(i, 1).at(0); xclock_reports.emplace_back(build_critical_path_report(i, worst_endpoint)); } @@ -1045,7 +1057,7 @@ void TimingAnalyser::build_crit_path_reports() void TimingAnalyser::build_slack_histogram_report() { - auto& slack_histogram = ctx->timing_result.slack_histogram; + auto &slack_histogram = ctx->timing_result.slack_histogram; for (domain_id_t dom_id = 0; dom_id < domain_id_t(domains.size()); ++dom_id) { for (auto &ep : domains.at(dom_id).endpoints) { diff --git a/common/kernel/timing_old.cc b/common/kernel/timing_old.cc index 5632203b..5e7232b4 100644 --- a/common/kernel/timing_old.cc +++ b/common/kernel/timing_old.cc @@ -411,8 +411,6 @@ struct Timing for (auto crit_pair : crit_nets) { NetInfo *crit_net = crit_pair.second.second; auto &cp_ports = (*crit_path)[crit_pair.first].ports; - log_info("// Walk backwards from the most critical net, start point: %s.%s\n", - cp_ports.at(0)->cell->name.c_str(ctx), cp_ports.at(0)->port.c_str(ctx)); while (crit_net) { const PortInfo *crit_ipin = nullptr; delay_t max_arrival = std::numeric_limits::min(); @@ -454,9 +452,7 @@ struct Timing break; // Now convert PortInfo* into a PortRef* for (auto &usr : crit_ipin->net->users) { - log_info("critical pin user: %s.%s\n", usr.cell->name.c_str(ctx), usr.port.c_str(ctx)); if (usr.cell->name == crit_net->driver.cell->name && usr.port == crit_ipin->name) { - log_info("Adding %s.%s to critical path\n", usr.cell->name.c_str(ctx), usr.port.c_str(ctx)); cp_ports.push_back(&usr); break; } @@ -470,32 +466,6 @@ struct Timing } }; -std::string tgp_to_string(TimingPortClass c) -{ - switch (c) { - case TMG_CLOCK_INPUT: - return "TMG_CLOCK_INPUT"; - case TMG_GEN_CLOCK: - return "TMG_GEN_CLOCK"; - case TMG_REGISTER_INPUT: - return "TMG_REGISTER_INPUT"; - case TMG_REGISTER_OUTPUT: - return "TMG_REGISTER_OUTPUT"; - case TMG_COMB_INPUT: - return "TMG_COMB_INPUT"; - case TMG_COMB_OUTPUT: - return "TMG_COMB_OUTPUT"; - case TMG_STARTPOINT: - return "TMG_STARTPOINT"; - case TMG_ENDPOINT: - return "TMG_ENDPOINT"; - case TMG_IGNORE: - return "TMG_IGNORE"; - } - - return "UNKNOWN"; -} - CriticalPath build_critical_path_report(Context *ctx, ClockPair &clocks, const PortRefVector &crit_path) { CriticalPath report; @@ -524,9 +494,6 @@ CriticalPath build_critical_path_report(Context *ctx, ClockPair &clocks, const P } } - log_info("building critical path report for clocks: %s -> %s\n", clocks.start.clock.c_str(ctx), - clocks.end.clock.c_str(ctx)); - for (auto sink : crit_path) { auto sink_cell = sink->cell; @@ -645,7 +612,6 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p const ClockEvent &b = path.first.end; empty_clocks.insert(a.clock); empty_clocks.insert(b.clock); - log_info("timing_old: clock pair: %s -> %s\n", a.clock.c_str(ctx), b.clock.c_str(ctx)); } for (auto path : crit_paths) { const ClockEvent &a = path.first.start; @@ -1018,14 +984,6 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p (bins[i] * bar_width) % max_freq > 0 ? '+' : ' '); } - log_info("segments"); - for (auto &r : clock_reports) { - log_info("clock: %s\n", r.first.c_str(ctx)); - for (const auto &segment : r.second.segments) { - log_info("processing segment %s\n", segment.net.c_str(ctx)); - } - } - // Update timing results in the context if (update_results) { auto &results = ctx->timing_result; diff --git a/common/kernel/timing_report.cc b/common/kernel/timing_report.cc index 969e848c..4956a72b 100644 --- a/common/kernel/timing_report.cc +++ b/common/kernel/timing_report.cc @@ -79,11 +79,10 @@ static void log_crit_paths(const Context *ctx) segment.type == CriticalPath::Segment::Type::SETUP) { logic_total += segment.delay; - const std::string type_name = - (segment.type == CriticalPath::Segment::Type::SETUP) ? "Setup" : "Source"; + const std::string type_name = (segment.type == CriticalPath::Segment::Type::SETUP) ? "Setup" : "Source"; log_info("%4.1f %4.1f %s %s.%s\n", ctx->getDelayNS(segment.delay), ctx->getDelayNS(total), - type_name.c_str(), segment.to.first.c_str(ctx), segment.to.second.c_str(ctx)); + type_name.c_str(), segment.to.first.c_str(ctx), segment.to.second.c_str(ctx)); } else if (segment.type == CriticalPath::Segment::Type::ROUTING) { route_total += segment.delay; @@ -94,8 +93,8 @@ static void log_crit_paths(const Context *ctx) auto sink_loc = ctx->getBelLocation(sink->bel); log_info("%4.1f %4.1f Net %s (%d,%d) -> (%d,%d)\n", ctx->getDelayNS(segment.delay), - ctx->getDelayNS(total), segment.net.c_str(ctx), - driver_loc.x, driver_loc.y, sink_loc.x, sink_loc.y); + ctx->getDelayNS(total), segment.net.c_str(ctx), driver_loc.x, driver_loc.y, sink_loc.x, + sink_loc.y); log_info(" Sink %s.%s\n", segment.to.first.c_str(ctx), segment.to.second.c_str(ctx)); const NetInfo *net = ctx->nets.at(segment.net).get(); @@ -109,8 +108,8 @@ static void log_crit_paths(const Context *ctx) auto driver_wire = ctx->getNetinfoSourceWire(net); auto sink_wire = ctx->getNetinfoSinkWire(net, sink_ref, 0); log_info(" prediction: %f ns estimate: %f ns\n", - ctx->getDelayNS(ctx->predictArcDelay(net, sink_ref)), - ctx->getDelayNS(ctx->estimateDelay(driver_wire, sink_wire))); + ctx->getDelayNS(ctx->predictArcDelay(net, sink_ref)), + ctx->getDelayNS(ctx->estimateDelay(driver_wire, sink_wire))); auto cursor = sink_wire; delay_t delay; while (driver_wire != cursor) { @@ -139,12 +138,12 @@ static void log_crit_paths(const Context *ctx) // Single domain paths for (auto &clock : ctx->timing_result.clock_paths) { log_break(); - std::string start = clock.second.clock_pair.start.edge == FALLING_EDGE ? std::string("negedge") - : std::string("posedge"); + std::string start = + clock.second.clock_pair.start.edge == FALLING_EDGE ? std::string("negedge") : std::string("posedge"); std::string end = clock.second.clock_pair.end.edge == FALLING_EDGE ? std::string("negedge") : std::string("posedge"); log_info("Critical path report for clock '%s' (%s -> %s):\n", clock.first.c_str(ctx), start.c_str(), - end.c_str()); + end.c_str()); auto &report = clock.second; print_path_report(report); } @@ -176,18 +175,17 @@ static void log_fmax(Context *ctx, bool warn_on_failure) bool passed = target < fmax; if (!warn_on_failure || passed) - log_info("Max frequency for clock %*s'%s': %.02f MHz (%s at %.02f MHz)\n", width, "", - clock_name.c_str(), fmax, passed ? "PASS" : "FAIL", target); + log_info("Max frequency for clock %*s'%s': %.02f MHz (%s at %.02f MHz)\n", width, "", clock_name.c_str(), + fmax, passed ? "PASS" : "FAIL", target); else if (bool_or_default(ctx->settings, ctx->id("timing/allowFail"), false)) - log_warning("Max frequency for clock %*s'%s': %.02f MHz (%s at %.02f MHz)\n", width, "", - clock_name.c_str(), fmax, passed ? "PASS" : "FAIL", target); + log_warning("Max frequency for clock %*s'%s': %.02f MHz (%s at %.02f MHz)\n", width, "", clock_name.c_str(), + fmax, passed ? "PASS" : "FAIL", target); else log_nonfatal_error("Max frequency for clock %*s'%s': %.02f MHz (%s at %.02f MHz)\n", width, "", - clock_name.c_str(), fmax, passed ? "PASS" : "FAIL", target); + clock_name.c_str(), fmax, passed ? "PASS" : "FAIL", target); } log_break(); - // Clock to clock delays for xpaths dict xclock_delays; for (auto &report : ctx->timing_result.xclock_paths) { @@ -256,15 +254,15 @@ static void log_fmax(Context *ctx, bool warn_on_failure) auto ev_b = clock_event_name(ctx, report.clock_pair.end, max_width_xcb); if (!warn_on_failure || passed) - log_info("Max frequency for %s -> %s: %.02f MHz (%s at %.02f MHz)\n", ev_a.c_str(), ev_b.c_str(), - fmax, passed ? "PASS" : "FAIL", target); + log_info("Max frequency for %s -> %s: %.02f MHz (%s at %.02f MHz)\n", ev_a.c_str(), ev_b.c_str(), fmax, + passed ? "PASS" : "FAIL", target); else if (bool_or_default(ctx->settings, ctx->id("timing/allowFail"), false) || - bool_or_default(ctx->settings, ctx->id("timing/ignoreRelClk"), false)) - log_warning("Max frequency for %s -> %s: %.02f MHz (%s at %.02f MHz)\n", ev_a.c_str(), - ev_b.c_str(), fmax, passed ? "PASS" : "FAIL", target); + bool_or_default(ctx->settings, ctx->id("timing/ignoreRelClk"), false)) + log_warning("Max frequency for %s -> %s: %.02f MHz (%s at %.02f MHz)\n", ev_a.c_str(), ev_b.c_str(), + fmax, passed ? "PASS" : "FAIL", target); else log_nonfatal_error("Max frequency for %s -> %s: %.02f MHz (%s at %.02f MHz)\n", ev_a.c_str(), - ev_b.c_str(), fmax, passed ? "PASS" : "FAIL", target); + ev_b.c_str(), fmax, passed ? "PASS" : "FAIL", target); } log_break(); } @@ -280,8 +278,7 @@ static void log_fmax(Context *ctx, bool warn_on_failure) delay /= 2; } - log_info("Clock to clock delay %s -> %s: %0.02f ns\n", ev_a.c_str(), ev_b.c_str(), - ctx->getDelayNS(delay)); + log_info("Clock to clock delay %s -> %s: %0.02f ns\n", ev_a.c_str(), ev_b.c_str(), ctx->getDelayNS(delay)); } log_break(); @@ -312,7 +309,16 @@ static void log_fmax(Context *ctx, bool warn_on_failure) log_break(); } -static void log_histogram(Context *ctx) { +static void log_histogram(Context *ctx) +{ + log_break(); + log_info("Slack histogram:\n"); + + if (ctx->timing_result.slack_histogram.empty()) { + log_info(" No slack figures available\n"); + return; + } + unsigned num_bins = 20; unsigned bar_width = 60; @@ -341,14 +347,12 @@ static void log_histogram(Context *ctx) { } bar_width = std::min(bar_width, max_freq); - log_break(); - log_info("Slack histogram:\n"); log_info(" legend: * represents %d endpoint(s)\n", max_freq / bar_width); log_info(" + represents [1,%d) endpoint(s)\n", max_freq / bar_width); for (unsigned i = 0; i < num_bins; ++i) log_info("[%6d, %6d) |%s%c\n", min_slack + bin_size * i, min_slack + bin_size * (i + 1), - std::string(bins[i] * bar_width / max_freq, '*').c_str(), - (bins[i] * bar_width) % max_freq > 0 ? '+' : ' '); + std::string(bins[i] * bar_width / max_freq, '*').c_str(), + (bins[i] * bar_width) % max_freq > 0 ? '+' : ' '); } void Context::log_timing_results(bool print_histogram, bool print_path, bool warn_on_failure)