From e275a82d12c333c5306c5584f562fb38ad47fd02 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 2 May 2025 11:33:49 -0400 Subject: [PATCH 01/29] [vpr][CLI] add generate_net_timing_report --- vpr/src/base/read_options.cpp | 5 +++++ vpr/src/base/read_options.h | 1 + 2 files changed, 6 insertions(+) diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 41d1af3380..00d926dd15 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -3010,6 +3010,11 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio analysis_grp.add_argument(args.write_timing_summary, "--write_timing_summary") .help("Writes implemented design final timing summary to the specified JSON, XML or TXT file.") .show_in(argparse::ShowIn::HELP_ONLY); + + analysis_grp.add_argument(args.generate_net_timing_report, "--generate_net_timing_report") + .help("Generates a net timing report for each net in the design.") + .default_value("off") + .show_in(argparse::ShowIn::HELP_ONLY); auto& power_grp = parser.add_argument_group("power analysis options"); diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index 13c0d93f3f..e7c4b3a0df 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -267,6 +267,7 @@ struct t_options { argparse::ArgValue post_synth_netlist_unconn_output_handling; argparse::ArgValue post_synth_netlist_module_parameters; argparse::ArgValue write_timing_summary; + argparse::ArgValue generate_net_timing_report; }; argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_options& args); From 333de67ba946a02d2643fd86f3ecb45c4df8c11c Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 2 May 2025 18:27:04 -0400 Subject: [PATCH 02/29] [vpr][analysis] add generate_net_timing_report --- vpr/src/analysis/timing_reports.h | 6 ++++++ vpr/src/base/SetupVPR.cpp | 1 + vpr/src/base/read_options.cpp | 2 +- vpr/src/base/vpr_api.cpp | 5 +++++ vpr/src/base/vpr_types.h | 1 + 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/vpr/src/analysis/timing_reports.h b/vpr/src/analysis/timing_reports.h index 72e1013dec..6b094809d6 100644 --- a/vpr/src/analysis/timing_reports.h +++ b/vpr/src/analysis/timing_reports.h @@ -21,4 +21,10 @@ void generate_hold_timing_stats(const std::string& prefix, bool is_flat, const BlkLocRegistry& blk_loc_registry); +void generate_net_timing_report(const std::string& prefix, + const SetupHoldTimingInfo& timing_info, + const AnalysisDelayCalculator& delay_calc, + const t_analysis_opts& analysis_opts, + const BlkLocRegistry& blk_loc_registry); + #endif diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index f911039c18..417b7bbf65 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -715,6 +715,7 @@ static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysi analysis_opts.timing_update_type = Options.timing_update_type; analysis_opts.write_timing_summary = Options.write_timing_summary; + analysis_opts.generate_net_timing_report = Options.generate_net_timing_report; } static void SetupPowerOpts(const t_options& Options, t_power_opts* power_opts, t_arch* Arch) { diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 00d926dd15..6e6578ce38 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -3011,7 +3011,7 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio .help("Writes implemented design final timing summary to the specified JSON, XML or TXT file.") .show_in(argparse::ShowIn::HELP_ONLY); - analysis_grp.add_argument(args.generate_net_timing_report, "--generate_net_timing_report") + analysis_grp.add_argument(args.generate_net_timing_report, "--generate_net_timing_report") .help("Generates a net timing report for each net in the design.") .default_value("off") .show_in(argparse::ShowIn::HELP_ONLY); diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 2c84a6a768..fe1d8437c1 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1476,6 +1476,11 @@ void vpr_analysis(const Netlist<>& net_list, merged_netlist_writer(atom_ctx.netlist().netlist_name(), analysis_delay_calc, Arch.models, vpr_setup.AnalysisOpts); } + if (vpr_setup.AnalysisOpts.generate_net_timing_report) { + generate_net_timing_report(/*prefix=*/"", *timing_info, *analysis_delay_calc, + vpr_setup.AnalysisOpts, blk_loc_registry); + } + //Do power analysis // TODO: Still assumes that cluster net list is used if (vpr_setup.PowerOpts.do_power) { diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 106070c4c9..4330f8c0e6 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1285,6 +1285,7 @@ struct t_analysis_opts { bool timing_report_skew; std::string echo_dot_timing_graph_node; std::string write_timing_summary; + bool generate_net_timing_report; e_timing_update_type timing_update_type; }; From 8aebd6a1e7497050abc0848fb22659efe93d12f6 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 5 May 2025 14:08:33 -0400 Subject: [PATCH 03/29] [vpr][analysis] add comments --- vpr/src/analysis/timing_reports.cpp | 58 +++++++++++++++++++++++++++++ vpr/src/analysis/timing_reports.h | 11 ++++-- vpr/src/base/vpr_api.cpp | 3 +- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 281a40b67a..fae53e90e2 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "timing_reports.h" #include "tatum/TimingReporter.hpp" @@ -61,3 +64,58 @@ void generate_hold_timing_stats(const std::string& prefix, timing_reporter.report_unconstrained_hold(prefix + "report_unconstrained_timing.hold.rpt", *timing_info.hold_analyzer()); } + +void generate_net_timing_report(const std::string& prefix, + const SetupHoldTimingInfo& timing_info, + const AnalysisDelayCalculator& delay_calc) { + /* Create a report file for net timing information */ + std::ofstream os(prefix + "report_net_timing.rpt"); + const auto& atom_netlist = g_vpr_ctx.atom().netlist(); + const auto& atom_lookup = g_vpr_ctx.atom().lookup(); + + const auto& timing_ctx = g_vpr_ctx.timing(); + const auto& timing_graph = timing_ctx.graph; + + for (const auto& net : atom_netlist.nets()) { + /* Skip constant nets */ + if (atom_netlist.net_is_constant(net)) { + continue; + } + + const auto& net_name = atom_netlist.net_name(net); + + /* Get source pin and its timing information */ + const auto& source_pin = *atom_netlist.net_pins(net).begin(); + auto source_pin_slack = timing_info.setup_pin_slack(source_pin); + /* Timing graph node id corresponding to the net's source pin */ + auto tg_source_node = atom_lookup.atom_pin_tnode(source_pin); + VTR_ASSERT(tg_source_node.is_valid()); + + const size_t fanout = atom_netlist.net_sinks(net).size(); + os << net_name << " : " << fanout << " : " << atom_netlist.pin_name(source_pin).c_str() << " " << source_pin_slack << " : "; + + /* Iterate over all fanout pins and print their timing information */ + for (size_t net_pin_index = 1; net_pin_index <= fanout; ++net_pin_index) { + const auto& pin = *(atom_netlist.net_pins(net).begin() + net_pin_index); + + /* Get timing graph node id corresponding to the fanout pin */ + const auto& tg_sink_node = atom_lookup.atom_pin_tnode(pin); + VTR_ASSERT(tg_sink_node.is_valid()); + + /* Get timing graph edge id between atom pins */ + const auto& tg_edge_id = timing_graph->find_edge(tg_source_node, tg_sink_node); + VTR_ASSERT(tg_edge_id.is_valid()); + + /* Get timing information for the fanout pin */ + const auto& pin_setup_slack = timing_info.setup_pin_slack(pin); + const auto& pin_delay = delay_calc.max_edge_delay(*timing_graph, tg_edge_id); + + const auto& pin_name = atom_netlist.pin_name(pin); + os << pin_name << " " << std::scientific << pin_setup_slack << " " << pin_delay; + if (net_pin_index < fanout) { + os << " : "; + } + } + os << "," << std::endl; + } +} diff --git a/vpr/src/analysis/timing_reports.h b/vpr/src/analysis/timing_reports.h index 6b094809d6..a9735d8391 100644 --- a/vpr/src/analysis/timing_reports.h +++ b/vpr/src/analysis/timing_reports.h @@ -21,10 +21,15 @@ void generate_hold_timing_stats(const std::string& prefix, bool is_flat, const BlkLocRegistry& blk_loc_registry); +/** + * @brief Generates timing information for each net in atom netlist + * + * @param prefix The prefix for the report file to be added to filename: report_net_timing.rpt + * @param timing_info Updated timing information + * @param delay_calc Delay calculator + */ void generate_net_timing_report(const std::string& prefix, const SetupHoldTimingInfo& timing_info, - const AnalysisDelayCalculator& delay_calc, - const t_analysis_opts& analysis_opts, - const BlkLocRegistry& blk_loc_registry); + const AnalysisDelayCalculator& delay_calc); #endif diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index fe1d8437c1..310a3798b1 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1477,8 +1477,7 @@ void vpr_analysis(const Netlist<>& net_list, } if (vpr_setup.AnalysisOpts.generate_net_timing_report) { - generate_net_timing_report(/*prefix=*/"", *timing_info, *analysis_delay_calc, - vpr_setup.AnalysisOpts, blk_loc_registry); + generate_net_timing_report(/*prefix=*/"", *timing_info, *analysis_delay_calc); } //Do power analysis From 010144e9fc9d0e4f57f4453271eedec4d1e77bb2 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 5 May 2025 14:09:09 -0400 Subject: [PATCH 04/29] make format --- vpr/src/analysis/timing_reports.cpp | 2 +- vpr/src/base/read_options.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index fae53e90e2..77e06a560e 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -90,7 +90,7 @@ void generate_net_timing_report(const std::string& prefix, /* Timing graph node id corresponding to the net's source pin */ auto tg_source_node = atom_lookup.atom_pin_tnode(source_pin); VTR_ASSERT(tg_source_node.is_valid()); - + const size_t fanout = atom_netlist.net_sinks(net).size(); os << net_name << " : " << fanout << " : " << atom_netlist.pin_name(source_pin).c_str() << " " << source_pin_slack << " : "; diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 6e6578ce38..6afb0d3b42 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -3010,7 +3010,7 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio analysis_grp.add_argument(args.write_timing_summary, "--write_timing_summary") .help("Writes implemented design final timing summary to the specified JSON, XML or TXT file.") .show_in(argparse::ShowIn::HELP_ONLY); - + analysis_grp.add_argument(args.generate_net_timing_report, "--generate_net_timing_report") .help("Generates a net timing report for each net in the design.") .default_value("off") From b8289db3ed811a9b831dbb036b91929e6b2737fc Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 5 May 2025 14:45:19 -0400 Subject: [PATCH 05/29] [vpr][CLI] remove generate net timing from CLI parameters and generate the report by default --- vpr/src/base/SetupVPR.cpp | 1 - vpr/src/base/read_options.cpp | 5 ----- vpr/src/base/read_options.h | 1 - vpr/src/base/vpr_api.cpp | 5 +---- vpr/src/base/vpr_types.h | 1 - 5 files changed, 1 insertion(+), 12 deletions(-) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index 417b7bbf65..f911039c18 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -715,7 +715,6 @@ static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysi analysis_opts.timing_update_type = Options.timing_update_type; analysis_opts.write_timing_summary = Options.write_timing_summary; - analysis_opts.generate_net_timing_report = Options.generate_net_timing_report; } static void SetupPowerOpts(const t_options& Options, t_power_opts* power_opts, t_arch* Arch) { diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 6afb0d3b42..41d1af3380 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -3011,11 +3011,6 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio .help("Writes implemented design final timing summary to the specified JSON, XML or TXT file.") .show_in(argparse::ShowIn::HELP_ONLY); - analysis_grp.add_argument(args.generate_net_timing_report, "--generate_net_timing_report") - .help("Generates a net timing report for each net in the design.") - .default_value("off") - .show_in(argparse::ShowIn::HELP_ONLY); - auto& power_grp = parser.add_argument_group("power analysis options"); power_grp.add_argument(args.do_power, "--power") diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index e7c4b3a0df..13c0d93f3f 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -267,7 +267,6 @@ struct t_options { argparse::ArgValue post_synth_netlist_unconn_output_handling; argparse::ArgValue post_synth_netlist_module_parameters; argparse::ArgValue write_timing_summary; - argparse::ArgValue generate_net_timing_report; }; argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_options& args); diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 310a3798b1..6aa0acffbe 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1464,6 +1464,7 @@ void vpr_analysis(const Netlist<>& net_list, vpr_setup.AnalysisOpts, vpr_setup.RouterOpts.flat_routing, blk_loc_registry); generate_setup_timing_stats(/*prefix=*/"", *timing_info, *analysis_delay_calc, vpr_setup.AnalysisOpts, vpr_setup.RouterOpts.flat_routing, blk_loc_registry); + generate_net_timing_report(/*prefix=*/"", *timing_info, *analysis_delay_calc); //Write the post-synthesis netlist if (vpr_setup.AnalysisOpts.gen_post_synthesis_netlist) { @@ -1476,10 +1477,6 @@ void vpr_analysis(const Netlist<>& net_list, merged_netlist_writer(atom_ctx.netlist().netlist_name(), analysis_delay_calc, Arch.models, vpr_setup.AnalysisOpts); } - if (vpr_setup.AnalysisOpts.generate_net_timing_report) { - generate_net_timing_report(/*prefix=*/"", *timing_info, *analysis_delay_calc); - } - //Do power analysis // TODO: Still assumes that cluster net list is used if (vpr_setup.PowerOpts.do_power) { diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 4330f8c0e6..106070c4c9 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1285,7 +1285,6 @@ struct t_analysis_opts { bool timing_report_skew; std::string echo_dot_timing_graph_node; std::string write_timing_summary; - bool generate_net_timing_report; e_timing_update_type timing_update_type; }; From 25bcd43586065528c7192f55a1381f5a9b7c0bb5 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 6 May 2025 11:43:38 -0400 Subject: [PATCH 06/29] [vpr][analysis] add header for net timing report --- vpr/src/analysis/timing_reports.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 77e06a560e..29cfe2603a 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -1,3 +1,5 @@ +#include "timing_reports.h" + #include #include @@ -5,6 +7,7 @@ #include "tatum/TimingReporter.hpp" +#include "vtr_version.h" #include "vpr_types.h" #include "globals.h" @@ -76,6 +79,15 @@ void generate_net_timing_report(const std::string& prefix, const auto& timing_ctx = g_vpr_ctx.timing(); const auto& timing_graph = timing_ctx.graph; + os << "# This file is generated by VTR" << std::endl; + os << "# Version: " << vtr::VERSION << std::endl; + os << "# Revision: " << vtr::VCS_REVISION << std::endl; + os << "# For each net, the timing information is reported in the following format:" << std::endl; + os << "# netname : Fanout : source_instance : " + << " : " + << " : ..." + << std::endl; + for (const auto& net : atom_netlist.nets()) { /* Skip constant nets */ if (atom_netlist.net_is_constant(net)) { From e7df9ea59e1cd43740d47df1fbe226a0d28f256c Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 6 May 2025 11:50:13 -0400 Subject: [PATCH 07/29] [vpr][analysis] add timing format to comments --- vpr/src/analysis/timing_reports.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vpr/src/analysis/timing_reports.h b/vpr/src/analysis/timing_reports.h index a9735d8391..e127335849 100644 --- a/vpr/src/analysis/timing_reports.h +++ b/vpr/src/analysis/timing_reports.h @@ -22,7 +22,11 @@ void generate_hold_timing_stats(const std::string& prefix, const BlkLocRegistry& blk_loc_registry); /** - * @brief Generates timing information for each net in atom netlist + * @brief Generates timing information for each net in atom netlist. For each net, the timing information + * is reported in the following format: + * netname : Fanout : source_instance : + * : + * : ... * * @param prefix The prefix for the report file to be added to filename: report_net_timing.rpt * @param timing_info Updated timing information From 1d50ca126cb9f367f210266503461f7b89ea500a Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 6 May 2025 12:31:27 -0400 Subject: [PATCH 08/29] formatting fix --- vpr/src/analysis/timing_reports.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 29cfe2603a..1467b9e28a 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -87,6 +87,8 @@ void generate_net_timing_report(const std::string& prefix, << " : " << " : ..." << std::endl; + + os << std::endl; for (const auto& net : atom_netlist.nets()) { /* Skip constant nets */ From 310ecac66cb6a723324f0bf13c44a6505d271908 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 6 May 2025 12:32:04 -0400 Subject: [PATCH 09/29] Revert "[vpr][CLI] remove generate net timing from CLI parameters and generate the report by default" This reverts commit b8289db3ed811a9b831dbb036b91929e6b2737fc. --- vpr/src/base/SetupVPR.cpp | 1 + vpr/src/base/read_options.cpp | 5 +++++ vpr/src/base/read_options.h | 1 + vpr/src/base/vpr_api.cpp | 5 ++++- vpr/src/base/vpr_types.h | 1 + 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index f911039c18..417b7bbf65 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -715,6 +715,7 @@ static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysi analysis_opts.timing_update_type = Options.timing_update_type; analysis_opts.write_timing_summary = Options.write_timing_summary; + analysis_opts.generate_net_timing_report = Options.generate_net_timing_report; } static void SetupPowerOpts(const t_options& Options, t_power_opts* power_opts, t_arch* Arch) { diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 41d1af3380..6afb0d3b42 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -3011,6 +3011,11 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio .help("Writes implemented design final timing summary to the specified JSON, XML or TXT file.") .show_in(argparse::ShowIn::HELP_ONLY); + analysis_grp.add_argument(args.generate_net_timing_report, "--generate_net_timing_report") + .help("Generates a net timing report for each net in the design.") + .default_value("off") + .show_in(argparse::ShowIn::HELP_ONLY); + auto& power_grp = parser.add_argument_group("power analysis options"); power_grp.add_argument(args.do_power, "--power") diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index 13c0d93f3f..e7c4b3a0df 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -267,6 +267,7 @@ struct t_options { argparse::ArgValue post_synth_netlist_unconn_output_handling; argparse::ArgValue post_synth_netlist_module_parameters; argparse::ArgValue write_timing_summary; + argparse::ArgValue generate_net_timing_report; }; argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_options& args); diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 6aa0acffbe..310a3798b1 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1464,7 +1464,6 @@ void vpr_analysis(const Netlist<>& net_list, vpr_setup.AnalysisOpts, vpr_setup.RouterOpts.flat_routing, blk_loc_registry); generate_setup_timing_stats(/*prefix=*/"", *timing_info, *analysis_delay_calc, vpr_setup.AnalysisOpts, vpr_setup.RouterOpts.flat_routing, blk_loc_registry); - generate_net_timing_report(/*prefix=*/"", *timing_info, *analysis_delay_calc); //Write the post-synthesis netlist if (vpr_setup.AnalysisOpts.gen_post_synthesis_netlist) { @@ -1477,6 +1476,10 @@ void vpr_analysis(const Netlist<>& net_list, merged_netlist_writer(atom_ctx.netlist().netlist_name(), analysis_delay_calc, Arch.models, vpr_setup.AnalysisOpts); } + if (vpr_setup.AnalysisOpts.generate_net_timing_report) { + generate_net_timing_report(/*prefix=*/"", *timing_info, *analysis_delay_calc); + } + //Do power analysis // TODO: Still assumes that cluster net list is used if (vpr_setup.PowerOpts.do_power) { diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 106070c4c9..4330f8c0e6 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1285,6 +1285,7 @@ struct t_analysis_opts { bool timing_report_skew; std::string echo_dot_timing_graph_node; std::string write_timing_summary; + bool generate_net_timing_report; e_timing_update_type timing_update_type; }; From 2265ce89087cfe05bc4332f865b58ab025b6483c Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 6 May 2025 12:54:48 -0400 Subject: [PATCH 10/29] make format --- vpr/src/analysis/timing_reports.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 1467b9e28a..0062aff5d8 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -83,11 +83,11 @@ void generate_net_timing_report(const std::string& prefix, os << "# Version: " << vtr::VERSION << std::endl; os << "# Revision: " << vtr::VCS_REVISION << std::endl; os << "# For each net, the timing information is reported in the following format:" << std::endl; - os << "# netname : Fanout : source_instance : " + os << "# netname : Fanout : source_instance : " << " : " - << " : ..." + << " : ..." << std::endl; - + os << std::endl; for (const auto& net : atom_netlist.nets()) { From 909e3f22551e38f52f4c0fca29dc263c58f785d0 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 06:02:05 -0400 Subject: [PATCH 11/29] [task] add generate_net_timing_report to timing report strong test --- .../strong_timing_report_detail/config/config.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/config.txt index 79ab5b2246..2ea1502528 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/config.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/config.txt @@ -24,7 +24,7 @@ qor_parse_file=qor_standard.txt pass_requirements_file=pass_requirements.txt # Script parameters -script_params_common = -starting_stage vpr +script_params_common = -starting_stage vpr --generate_net_timing_report on script_params_list_add=--timing_report_detail netlist script_params_list_add=--timing_report_detail aggregated script_params_list_add=--timing_report_detail detailed From 616cc8d7ad35b2fcf3f67ca600c430f74eb149c0 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 06:12:52 -0400 Subject: [PATCH 12/29] [doc] add doc for generating _net_timing_report command line option --- doc/src/vpr/command_line_usage.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index 61dd775abb..cc6ef935b0 100644 --- a/doc/src/vpr/command_line_usage.rst +++ b/doc/src/vpr/command_line_usage.rst @@ -1517,6 +1517,19 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout * `swns` - setup Worst Negative Slack (sWNS) [ns] * `stns` - Setup Total Negative Slack (sTNS) [ns] + +.. option:: --generate_net_timing_report {on | off} + + Generates a net timing report for each net in the design. For each net, the timing information written in the following format: + + .. code-block:: none + + netname : Fanout : bounding_box_xmin,bounding_box_ymin,bounding_box_xmax,bounding_box_ymax : source_instance : + : + : ... + + **Default:** ``off`` + .. option:: --route_verbosity Controls the verbosity of routing output. From ebcf74bf921707b638f10d0bb3beae87fa692fb5 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 06:14:38 -0400 Subject: [PATCH 13/29] [vpr][timing] update generate_net_timing_report comment --- vpr/src/analysis/timing_reports.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vpr/src/analysis/timing_reports.h b/vpr/src/analysis/timing_reports.h index e127335849..e5ed5f307d 100644 --- a/vpr/src/analysis/timing_reports.h +++ b/vpr/src/analysis/timing_reports.h @@ -24,7 +24,8 @@ void generate_hold_timing_stats(const std::string& prefix, /** * @brief Generates timing information for each net in atom netlist. For each net, the timing information * is reported in the following format: - * netname : Fanout : source_instance : + * netname : Fanout : bounding_box_xmin,bounding_box_ymin,bounding_box_xmax,bounding_box_ymax: + * source_instance : * : * : ... * From dcbe1b350c7441dbd879d7a4f4d5d80c7fecef3d Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 09:07:26 -0400 Subject: [PATCH 14/29] [vpr][timing] add get_net_bounding_box --- vpr/src/analysis/timing_reports.cpp | 112 +++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 0062aff5d8..1b8baaf375 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -4,6 +4,7 @@ #include #include "timing_reports.h" +#include "rr_graph.h" #include "tatum/TimingReporter.hpp" @@ -16,6 +17,113 @@ #include "VprTimingGraphResolver.h" +/** + * @brief Get the bounding box of a net. + * If the net is completely absorbed into a cluster block, return the bounding box of the cluster block. + * Otherwise, return the bounding box of the net's route tree. + * If a net is not routed, bounding box is returned with default values (OPEN). + * + * @param atom_net_id The id of the atom net to get the bounding box of. + */ +static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { + const auto& route_trees = g_vpr_ctx.routing().route_trees; + const auto& rr_graph = g_vpr_ctx.device().rr_graph; + const bool flat_router = g_vpr_ctx.routing().is_flat; + + // Lambda to get the bounding box of a route tree + auto route_tree_bb = [](const RRGraphView& rr_graph, const RouteTree& route_tree) { + t_bb bb; + + // Set the initial bounding box to the root node's location + RRNodeId route_tree_root = route_tree.root().inode; + bb.xmin = rr_graph.node_xlow(route_tree_root); + bb.xmax = rr_graph.node_xhigh(route_tree_root); + bb.ymin = rr_graph.node_ylow(route_tree_root); + bb.ymax = rr_graph.node_yhigh(route_tree_root); + bb.layer_min = rr_graph.node_layer(route_tree_root); + bb.layer_max = rr_graph.node_layer(route_tree_root); + + // Iterate over all nodes in the route tree and update the bounding box + for (auto& rt_node : route_tree.all_nodes()) { + RRNodeId inode = rt_node.inode; + if (rr_graph.node_xlow(inode) < bb.xmin) + bb.xmin = rr_graph.node_xlow(inode); + if (rr_graph.node_xhigh(inode) > bb.xmax) + bb.xmax = rr_graph.node_xhigh(inode); + if (rr_graph.node_ylow(inode) < bb.ymin) + bb.ymin = rr_graph.node_ylow(inode); + if (rr_graph.node_layer(inode) > bb.layer_min) + bb.layer_min = rr_graph.node_layer(inode); + if (rr_graph.node_layer(inode) > bb.layer_max) + bb.layer_max = rr_graph.node_layer(inode); + } + return bb; + }; + + if (flat_router) { + // If flat router is used, route tree data structure can be used + // directly to get the bounding box of the net + const auto& route_tree = route_trees[atom_net_id]; + if (!route_tree) + return t_bb(); + return route_tree_bb(rr_graph, *route_tree); + } else { + // If two-stage router is used, we need to first get the cluster net id + // corresponding to the atom net and then get the bounding box of the net + // from the route tree. If the net is completely absorbed into a cluster block, + const auto& atom_lookup = g_vpr_ctx.atom().lookup(); + const auto& cluster_net_id = atom_lookup.clb_nets(atom_net_id); + std::vector bbs; + t_bb max_bb; + // There maybe multiple cluster nets corresponding to a single atom net. + // We iterate over all cluster nets and the final bounding box is the union + // of all cluster net bounding boxes + if (cluster_net_id != vtr::nullopt) { + for (const auto& clb_net_id : *cluster_net_id) { + const auto& route_tree = route_trees[clb_net_id]; + if (!route_tree) + continue; + bbs.push_back(route_tree_bb(rr_graph, *route_tree)); + } + // Assign the first cluster net's bounding box to the final bounding box + // and then iteratively update it with the union of bounding boxes of + // all cluster nets + max_bb = bbs[0]; + for (size_t i = 1; i < bbs.size(); ++i) { + max_bb.xmin = std::min(bbs[i].xmin, max_bb.xmin); + max_bb.xmax = std::max(bbs[i].xmax, max_bb.xmax); + max_bb.ymin = std::min(bbs[i].ymin, max_bb.ymin); + max_bb.ymax = std::max(bbs[i].ymax, max_bb.ymax); + max_bb.layer_min = std::min(bbs[i].layer_min, max_bb.layer_min); + max_bb.layer_max = std::max(bbs[i].layer_max, max_bb.layer_max); + } + } else { + // If there is no cluster net corresponding to the atom net, + // it means the net is completely absorbed into a cluster block. + // In that case, we set the bounding box the cluster block's bounding box + const auto& atom_ctx = g_vpr_ctx.atom(); + const auto& atom_nlist = atom_ctx.netlist(); + AtomPinId source_pin = atom_nlist.net_driver(atom_net_id); + + AtomBlockId atom_block = atom_nlist.pin_block(source_pin); + VTR_ASSERT(atom_block != AtomBlockId::INVALID()); + ClusterBlockId cluster_block = atom_lookup.atom_clb(atom_block); + VTR_ASSERT(cluster_block != ClusterBlockId::INVALID()); + + const t_pl_loc& cluster_block_loc = g_vpr_ctx.placement().block_locs()[cluster_block].loc; + const auto& grid = g_vpr_ctx.device().grid; + vtr::Rect tile_bb = grid.get_tile_bb({cluster_block_loc.x, cluster_block_loc.y, cluster_block_loc.layer}); + const int block_layer = cluster_block_loc.layer; + return t_bb(tile_bb.xmin(), + tile_bb.xmax(), + tile_bb.ymin(), + tile_bb.ymax(), + block_layer, + block_layer); + } + } +} + void generate_setup_timing_stats(const std::string& prefix, const SetupTimingInfo& timing_info, const AnalysisDelayCalculator& delay_calc, @@ -106,7 +214,9 @@ void generate_net_timing_report(const std::string& prefix, VTR_ASSERT(tg_source_node.is_valid()); const size_t fanout = atom_netlist.net_sinks(net).size(); - os << net_name << " : " << fanout << " : " << atom_netlist.pin_name(source_pin).c_str() << " " << source_pin_slack << " : "; + os << net_name << " : " + << fanout << " : " + << atom_netlist.pin_name(source_pin).c_str() << " " << source_pin_slack << " : "; /* Iterate over all fanout pins and print their timing information */ for (size_t net_pin_index = 1; net_pin_index <= fanout; ++net_pin_index) { From 548d53abc7280d2a12327d367d41fce0754e42b5 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 09:12:14 -0400 Subject: [PATCH 15/29] [vpr][timing] add net bounding box to the report --- vpr/src/analysis/timing_reports.cpp | 6 +++++- vpr/src/analysis/timing_reports.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 1b8baaf375..110e63f9cd 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -191,7 +191,9 @@ void generate_net_timing_report(const std::string& prefix, os << "# Version: " << vtr::VERSION << std::endl; os << "# Revision: " << vtr::VCS_REVISION << std::endl; os << "# For each net, the timing information is reported in the following format:" << std::endl; - os << "# netname : Fanout : source_instance : " + os << "# netname : Fanout : " + << "bounding_box_xmin,bounding_box_ymin,bounding_box_xmax,bounding_box_ymax : " + << "source_instance : " << " : " << " : ..." << std::endl; @@ -214,8 +216,10 @@ void generate_net_timing_report(const std::string& prefix, VTR_ASSERT(tg_source_node.is_valid()); const size_t fanout = atom_netlist.net_sinks(net).size(); + const auto& net_bb = get_net_bounding_box(net); os << net_name << " : " << fanout << " : " + << net_bb.xmin << "," << net_bb.ymin << "," << net_bb.xmax << "," << net_bb.ymax << " : " << atom_netlist.pin_name(source_pin).c_str() << " " << source_pin_slack << " : "; /* Iterate over all fanout pins and print their timing information */ diff --git a/vpr/src/analysis/timing_reports.h b/vpr/src/analysis/timing_reports.h index e5ed5f307d..44efb56343 100644 --- a/vpr/src/analysis/timing_reports.h +++ b/vpr/src/analysis/timing_reports.h @@ -24,7 +24,7 @@ void generate_hold_timing_stats(const std::string& prefix, /** * @brief Generates timing information for each net in atom netlist. For each net, the timing information * is reported in the following format: - * netname : Fanout : bounding_box_xmin,bounding_box_ymin,bounding_box_xmax,bounding_box_ymax: + * netname : Fanout : bounding_box_xmin,bounding_box_ymin,bounding_box_xmax,bounding_box_ymax : * source_instance : * : * : ... From c4b781ee3eb735a3c9e6290ffaadd40fdcfdb86d Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 11:40:18 -0400 Subject: [PATCH 16/29] [test] add test for net timing report --- .../strong_timing_report_detail/config/config.txt | 3 +++ .../config/golden_results.txt | 11 +++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/config.txt index 2ea1502528..ae8e519b4a 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/config.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/config.txt @@ -28,3 +28,6 @@ script_params_common = -starting_stage vpr --generate_net_timing_report on script_params_list_add=--timing_report_detail netlist script_params_list_add=--timing_report_detail aggregated script_params_list_add=--timing_report_detail detailed +script_params_list_add=--timing_report_detail netlist --flat_routing on +script_params_list_add=--timing_report_detail aggregated --flat_routing on +script_params_list_add=--timing_report_detail detailed --flat_routing on diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/golden_results.txt index a5bee94784..f82233e245 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_timing_report_detail/config/golden_results.txt @@ -1,4 +1,7 @@ - arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est total_swap accepted_swap rejected_swap aborted_swap place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time ap_mem ap_time ap_full_legalizer_mem ap_full_legalizer_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time - k6_frac_N10_frac_chain_mem32K_40nm.xml multiclock.blif common_--timing_report_detail_netlist 0.50 vpr 67.05 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success v8.0.0-12163-g0dba7016b-dirty Release VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-51-generic x86_64 2025-02-19T17:54:19 haydar-Precision-5820-Tower /home/haydar/vtr-verilog-to-routing 68660 5 3 11 14 2 9 10 4 4 16 clb auto 28.8 MiB 0.01 21 30 9 19 2 67.1 MiB 0.00 0.00 0.620042 -3.41492 -0.620042 0.545 0.01 4.6443e-05 3.2529e-05 0.000274786 0.000214986 -1 -1 -1 -1 20 24 1 107788 107788 10441.3 652.579 0.01 0.00211509 0.0019009 750 1675 -1 23 1 7 7 146 95 0.563256 0.545 -3.71515 -0.563256 0 0 13752.8 859.551 0.00 0.00 0.00 -1 -1 0.00 0.0017763 0.00169895 - k6_frac_N10_frac_chain_mem32K_40nm.xml multiclock.blif common_--timing_report_detail_aggregated 0.49 vpr 67.07 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success v8.0.0-12163-g0dba7016b-dirty Release VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-51-generic x86_64 2025-02-19T17:54:19 haydar-Precision-5820-Tower /home/haydar/vtr-verilog-to-routing 68680 5 3 11 14 2 9 10 4 4 16 clb auto 28.8 MiB 0.01 21 30 9 19 2 67.1 MiB 0.00 0.00 0.620042 -3.41492 -0.620042 0.545 0.01 4.8016e-05 3.4218e-05 0.000283686 0.000224427 -1 -1 -1 -1 20 24 1 107788 107788 10441.3 652.579 0.01 0.0022472 0.00206472 750 1675 -1 23 1 7 7 146 95 0.563256 0.545 -3.71515 -0.563256 0 0 13752.8 859.551 0.00 0.00 0.00 -1 -1 0.00 0.00179634 0.00171755 - k6_frac_N10_frac_chain_mem32K_40nm.xml multiclock.blif common_--timing_report_detail_detailed 0.51 vpr 67.32 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success v8.0.0-12163-g0dba7016b-dirty Release VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-51-generic x86_64 2025-02-19T17:54:19 haydar-Precision-5820-Tower /home/haydar/vtr-verilog-to-routing 68932 5 3 11 14 2 9 10 4 4 16 clb auto 28.9 MiB 0.01 21 30 9 19 2 67.3 MiB 0.00 0.00 0.620042 -3.41492 -0.620042 0.545 0.01 6.2523e-05 4.6425e-05 0.000366128 0.000294026 -1 -1 -1 -1 20 24 1 107788 107788 10441.3 652.579 0.01 0.00236124 0.00216436 750 1675 -1 23 1 7 7 146 95 0.563256 0.545 -3.71515 -0.563256 0 0 13752.8 859.551 0.00 0.00 0.00 -1 -1 0.00 0.00189537 0.00181322 +arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time initial_placed_wirelength_est placed_wirelength_est total_swap accepted_swap rejected_swap aborted_swap place_mem place_time place_quench_time initial_placed_CPD_est placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time ap_mem ap_time ap_full_legalizer_mem ap_full_legalizer_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time +k6_frac_N10_frac_chain_mem32K_40nm.xml multiclock.blif common_--timing_report_detail_netlist 0.37 vpr 65.06 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success v8.0.0-12677-g548d53abc-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-05-12T11:28:52 betzgrp-wintermute /home/mohagh18/vtr-verilog-to-routing/vtr_flow/tasks 66624 5 3 11 14 2 9 10 4 4 16 clb auto 26.8 MiB 0.01 24 21 30 9 19 2 65.1 MiB 0.00 0.00 0.713166 0.620042 -3.41492 -0.620042 0.545 0.01 2.4867e-05 1.6785e-05 0.000178305 0.000138626 -1 -1 -1 -1 20 24 1 107788 107788 10441.3 652.579 0.01 0.0013303 0.00121195 750 1675 -1 23 1 7 7 146 95 0.563256 0.545 -3.71515 -0.563256 0 0 13752.8 859.551 0.00 0.00 0.00 -1 -1 0.00 0.0010544 0.00100577 +k6_frac_N10_frac_chain_mem32K_40nm.xml multiclock.blif common_--timing_report_detail_aggregated 0.38 vpr 65.07 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success v8.0.0-12677-g548d53abc-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-05-12T11:28:52 betzgrp-wintermute /home/mohagh18/vtr-verilog-to-routing/vtr_flow/tasks 66628 5 3 11 14 2 9 10 4 4 16 clb auto 26.8 MiB 0.01 24 21 30 9 19 2 65.1 MiB 0.00 0.00 0.713166 0.620042 -3.41492 -0.620042 0.545 0.01 2.5617e-05 1.7506e-05 0.000177134 0.000138581 -1 -1 -1 -1 20 24 1 107788 107788 10441.3 652.579 0.01 0.0012973 0.00118019 750 1675 -1 23 1 7 7 146 95 0.563256 0.545 -3.71515 -0.563256 0 0 13752.8 859.551 0.00 0.00 0.00 -1 -1 0.00 0.00105506 0.00100757 +k6_frac_N10_frac_chain_mem32K_40nm.xml multiclock.blif common_--timing_report_detail_detailed 0.41 vpr 65.07 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success v8.0.0-12677-g548d53abc-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-05-12T11:28:52 betzgrp-wintermute /home/mohagh18/vtr-verilog-to-routing/vtr_flow/tasks 66628 5 3 11 14 2 9 10 4 4 16 clb auto 26.8 MiB 0.00 24 21 30 9 19 2 65.1 MiB 0.00 0.00 0.713166 0.620042 -3.41492 -0.620042 0.545 0.01 2.5232e-05 1.7334e-05 0.000170999 0.000134182 -1 -1 -1 -1 20 24 1 107788 107788 10441.3 652.579 0.01 0.00125289 0.00113927 750 1675 -1 23 1 7 7 146 95 0.563256 0.545 -3.71515 -0.563256 0 0 13752.8 859.551 0.00 0.00 0.00 -1 -1 0.00 0.00129683 0.00123 +k6_frac_N10_frac_chain_mem32K_40nm.xml multiclock.blif common_--timing_report_detail_netlist_--flat_routing_on 0.81 vpr 70.42 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success v8.0.0-12677-g548d53abc-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-05-12T11:28:52 betzgrp-wintermute /home/mohagh18/vtr-verilog-to-routing/vtr_flow/tasks 72112 5 3 11 14 2 9 10 4 4 16 clb auto 30.9 MiB 0.01 24 21 30 9 19 2 70.4 MiB 0.00 0.00 0.713166 0.620042 -3.41492 -0.620042 0.545 0.00 2.5406e-05 1.7598e-05 0.000175321 0.000137685 -1 -1 -1 -1 20 25 2 107788 107788 13586.0 849.124 0.25 0.00131841 0.00118136 858 2299 78 23 2 11 15 317 166 0.605686 0.545 -3.71515 -0.605686 0 0 18030.6 1126.91 0.00 0.12 0.00 0.00 0.11 0.00 0.00103786 0.000967845 +k6_frac_N10_frac_chain_mem32K_40nm.xml multiclock.blif common_--timing_report_detail_aggregated_--flat_routing_on 0.81 vpr 70.79 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success v8.0.0-12677-g548d53abc-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-05-12T11:28:52 betzgrp-wintermute /home/mohagh18/vtr-verilog-to-routing/vtr_flow/tasks 72492 5 3 11 14 2 9 10 4 4 16 clb auto 30.9 MiB 0.01 24 21 30 9 19 2 70.8 MiB 0.00 0.00 0.713166 0.620042 -3.41492 -0.620042 0.545 0.01 2.5095e-05 1.6967e-05 0.000167727 0.000130306 -1 -1 -1 -1 20 25 2 107788 107788 13586.0 849.124 0.26 0.00127606 0.0011399 858 2299 78 23 2 11 15 317 166 0.605686 0.545 -3.71515 -0.605686 0 0 18030.6 1126.91 0.00 0.12 0.00 0.00 0.12 0.00 0.00102446 0.000963839 +k6_frac_N10_frac_chain_mem32K_40nm.xml multiclock.blif common_--timing_report_detail_detailed_--flat_routing_on 0.85 vpr 70.42 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success v8.0.0-12677-g548d53abc-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-05-12T11:28:52 betzgrp-wintermute /home/mohagh18/vtr-verilog-to-routing/vtr_flow/tasks 72112 5 3 11 14 2 9 10 4 4 16 clb auto 30.9 MiB 0.01 24 21 30 9 19 2 70.4 MiB 0.00 0.00 0.713166 0.620042 -3.41492 -0.620042 0.545 0.01 2.5982e-05 1.7909e-05 0.000172322 0.000134495 -1 -1 -1 -1 20 25 2 107788 107788 13586.0 849.124 0.26 0.00129831 0.00116036 858 2299 78 23 2 11 15 317 166 0.605686 0.545 -3.71515 -0.605686 0 0 18030.6 1126.91 0.00 0.13 0.00 0.00 0.12 0.00 0.00101752 0.000959208 From 755800528fc346f3f6db8554d9a3ab8d1a670192 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 11:41:31 -0400 Subject: [PATCH 17/29] [doc] update doc with new format to net timing report --- doc/src/vpr/command_line_usage.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index cc6ef935b0..608d0bbf1d 100644 --- a/doc/src/vpr/command_line_usage.rst +++ b/doc/src/vpr/command_line_usage.rst @@ -1524,7 +1524,9 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout .. code-block:: none - netname : Fanout : bounding_box_xmin,bounding_box_ymin,bounding_box_xmax,bounding_box_ymax : source_instance : + netname : Fanout : + (bounding_box_xmin,bounding_box_ymin,bounding_box_layer_min),(bounding_box_xmax,bounding_box_ymax,bounding_box_layer_max) : + source_instance : : : ... From b2e1530053f81db92067d1b0801af34d6cbedb92 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 11:43:23 -0400 Subject: [PATCH 18/29] [vpr][analysis] fix net timing report bugs + including layer min/max of bb --- vpr/src/analysis/timing_reports.cpp | 19 ++++++++++++++----- vpr/src/analysis/timing_reports.h | 3 ++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 110e63f9cd..fec1d9bdef 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -28,7 +28,6 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { const auto& route_trees = g_vpr_ctx.routing().route_trees; const auto& rr_graph = g_vpr_ctx.device().rr_graph; - const bool flat_router = g_vpr_ctx.routing().is_flat; // Lambda to get the bounding box of a route tree auto route_tree_bb = [](const RRGraphView& rr_graph, const RouteTree& route_tree) { @@ -46,13 +45,18 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { // Iterate over all nodes in the route tree and update the bounding box for (auto& rt_node : route_tree.all_nodes()) { RRNodeId inode = rt_node.inode; + if (rr_graph.node_xlow(inode) < bb.xmin) bb.xmin = rr_graph.node_xlow(inode); if (rr_graph.node_xhigh(inode) > bb.xmax) bb.xmax = rr_graph.node_xhigh(inode); + if (rr_graph.node_ylow(inode) < bb.ymin) bb.ymin = rr_graph.node_ylow(inode); - if (rr_graph.node_layer(inode) > bb.layer_min) + if (rr_graph.node_yhigh(inode) > bb.ymax) + bb.ymax = rr_graph.node_yhigh(inode); + + if (rr_graph.node_layer(inode) < bb.layer_min) bb.layer_min = rr_graph.node_layer(inode); if (rr_graph.node_layer(inode) > bb.layer_max) bb.layer_max = rr_graph.node_layer(inode); @@ -60,7 +64,7 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { return bb; }; - if (flat_router) { + if (g_vpr_ctx.routing().is_flat) { // If flat router is used, route tree data structure can be used // directly to get the bounding box of the net const auto& route_tree = route_trees[atom_net_id]; @@ -85,6 +89,9 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { continue; bbs.push_back(route_tree_bb(rr_graph, *route_tree)); } + if (bbs.empty()) { + return t_bb(); + } // Assign the first cluster net's bounding box to the final bounding box // and then iteratively update it with the union of bounding boxes of // all cluster nets @@ -97,6 +104,7 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { max_bb.layer_min = std::min(bbs[i].layer_min, max_bb.layer_min); max_bb.layer_max = std::max(bbs[i].layer_max, max_bb.layer_max); } + return max_bb; } else { // If there is no cluster net corresponding to the atom net, // it means the net is completely absorbed into a cluster block. @@ -192,7 +200,7 @@ void generate_net_timing_report(const std::string& prefix, os << "# Revision: " << vtr::VCS_REVISION << std::endl; os << "# For each net, the timing information is reported in the following format:" << std::endl; os << "# netname : Fanout : " - << "bounding_box_xmin,bounding_box_ymin,bounding_box_xmax,bounding_box_ymax : " + << "(bounding_box_xmin,bounding_box_ymin,bounding_box_layermin),(bounding_box_xmax,bounding_box_ymax,bounding_box_layermax) : " << "source_instance : " << " : " << " : ..." @@ -219,7 +227,8 @@ void generate_net_timing_report(const std::string& prefix, const auto& net_bb = get_net_bounding_box(net); os << net_name << " : " << fanout << " : " - << net_bb.xmin << "," << net_bb.ymin << "," << net_bb.xmax << "," << net_bb.ymax << " : " + << "(" << net_bb.xmin << "," << net_bb.ymin << "," << net_bb.layer_min << "),(" + << net_bb.xmax << "," << net_bb.ymax << "," << net_bb.layer_max << ") : " << atom_netlist.pin_name(source_pin).c_str() << " " << source_pin_slack << " : "; /* Iterate over all fanout pins and print their timing information */ diff --git a/vpr/src/analysis/timing_reports.h b/vpr/src/analysis/timing_reports.h index 44efb56343..0aec721d76 100644 --- a/vpr/src/analysis/timing_reports.h +++ b/vpr/src/analysis/timing_reports.h @@ -24,7 +24,8 @@ void generate_hold_timing_stats(const std::string& prefix, /** * @brief Generates timing information for each net in atom netlist. For each net, the timing information * is reported in the following format: - * netname : Fanout : bounding_box_xmin,bounding_box_ymin,bounding_box_xmax,bounding_box_ymax : + * netname : Fanout : + * (bounding_box_xmin,bounding_box_ymin,bounding_box_layermin),(bounding_box_xmax,bounding_box_ymax,bounding_box_layermax) : * source_instance : * : * : ... From b625d58bdd03e9541f93942504369da2a3b1e9b0 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 11:44:20 -0400 Subject: [PATCH 19/29] make format --- vpr/src/analysis/timing_reports.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index fec1d9bdef..bbd4a05608 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -72,8 +72,8 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { return t_bb(); return route_tree_bb(rr_graph, *route_tree); } else { - // If two-stage router is used, we need to first get the cluster net id - // corresponding to the atom net and then get the bounding box of the net + // If two-stage router is used, we need to first get the cluster net id + // corresponding to the atom net and then get the bounding box of the net // from the route tree. If the net is completely absorbed into a cluster block, const auto& atom_lookup = g_vpr_ctx.atom().lookup(); const auto& cluster_net_id = atom_lookup.clb_nets(atom_net_id); @@ -225,8 +225,8 @@ void generate_net_timing_report(const std::string& prefix, const size_t fanout = atom_netlist.net_sinks(net).size(); const auto& net_bb = get_net_bounding_box(net); - os << net_name << " : " - << fanout << " : " + os << net_name << " : " + << fanout << " : " << "(" << net_bb.xmin << "," << net_bb.ymin << "," << net_bb.layer_min << "),(" << net_bb.xmax << "," << net_bb.ymax << "," << net_bb.layer_max << ") : " << atom_netlist.pin_name(source_pin).c_str() << " " << source_pin_slack << " : "; From 40522e535f99fe43cb9c3ee1ffd2026b08a69bae Mon Sep 17 00:00:00 2001 From: amin1377 Date: Mon, 12 May 2025 12:24:19 -0400 Subject: [PATCH 20/29] [vpr][analysis] capture vars by reference in lambda --- vpr/src/analysis/timing_reports.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index bbd4a05608..36cb99c020 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -30,7 +30,7 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { const auto& rr_graph = g_vpr_ctx.device().rr_graph; // Lambda to get the bounding box of a route tree - auto route_tree_bb = [](const RRGraphView& rr_graph, const RouteTree& route_tree) { + auto route_tree_bb = [&](const RouteTree& route_tree) { t_bb bb; // Set the initial bounding box to the root node's location @@ -70,7 +70,7 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { const auto& route_tree = route_trees[atom_net_id]; if (!route_tree) return t_bb(); - return route_tree_bb(rr_graph, *route_tree); + return route_tree_bb(*route_tree); } else { // If two-stage router is used, we need to first get the cluster net id // corresponding to the atom net and then get the bounding box of the net @@ -87,7 +87,7 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { const auto& route_tree = route_trees[clb_net_id]; if (!route_tree) continue; - bbs.push_back(route_tree_bb(rr_graph, *route_tree)); + bbs.push_back(route_tree_bb(*route_tree)); } if (bbs.empty()) { return t_bb(); From 403b9457f39519dcfda0bfe2aba36bd4e7adbf37 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Thu, 15 May 2025 17:51:15 -0400 Subject: [PATCH 21/29] [doc] update the doc with new report format --- doc/src/vpr/command_line_usage.rst | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index 608d0bbf1d..b450b9d661 100644 --- a/doc/src/vpr/command_line_usage.rst +++ b/doc/src/vpr/command_line_usage.rst @@ -1520,15 +1520,26 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout .. option:: --generate_net_timing_report {on | off} - Generates a net timing report for each net in the design. For each net, the timing information written in the following format: + Generates a report that lists the bounding box, slack, and delay of every routed connection in a design in csv format. Fields in the report are: .. code-block:: none - - netname : Fanout : - (bounding_box_xmin,bounding_box_ymin,bounding_box_layer_min),(bounding_box_xmax,bounding_box_ymax,bounding_box_layer_max) : - source_instance : - : - : ... + netname: The name assigned to the net in atom netlist + Fanout : Net's fanout + bb_xmin: X coordinate of the net's bounding box's bottom left corner + bb_ymin: Y coordinate of the net's bounding box's bottom left corner + bb_layer_min: Lowest layer number of the net's bounding box + bb_xmax: X coordinate of the net's bounding box's top right corner + bb_ymax: Y coordinate of the net's bounding box's top right corner + bb_layer_max: Highest layer number of the net's bounding box + src_pin_name: Name of the net's source pin + src_pin_slack: Slack of the net's source pin + sink_1_pin_name: Name of the net's first sink pin + sink_1_pin_slack: Slack of the net's first sink pin + sink_1_pin_delay: Delay of the net's first sink pin + sink_2_pin_name: Name of the net's second sink pin + sink_2_pin_slack: Slack of the net's second sink pin + sink_2_pin_delay: Delay of the net's second sink pin + ... **Default:** ``off`` From 77799b6383e40cb13de4b0ccad6556ebc4339d0c Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 16 May 2025 12:13:03 -0400 Subject: [PATCH 22/29] [vpr][analysis] use std::min/max instead of if condition --- doc/src/vpr/command_line_usage.rst | 2 +- vpr/src/analysis/timing_reports.cpp | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index b450b9d661..f6e5b83147 100644 --- a/doc/src/vpr/command_line_usage.rst +++ b/doc/src/vpr/command_line_usage.rst @@ -1520,7 +1520,7 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout .. option:: --generate_net_timing_report {on | off} - Generates a report that lists the bounding box, slack, and delay of every routed connection in a design in csv format. Fields in the report are: + Generates a report that lists the bounding box, slack, and delay of every routed connection in a design in csv format (``report_net_timing.csv``). Fields in the report are: .. code-block:: none netname: The name assigned to the net in atom netlist diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 36cb99c020..4d87fa2c8f 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -18,12 +18,14 @@ #include "VprTimingGraphResolver.h" /** - * @brief Get the bounding box of a net. + * @brief Get the bounding box of a routed net. * If the net is completely absorbed into a cluster block, return the bounding box of the cluster block. * Otherwise, return the bounding box of the net's route tree. - * If a net is not routed, bounding box is returned with default values (OPEN). * * @param atom_net_id The id of the atom net to get the bounding box of. + * + * @return The bounding box of the net. If the net is not routed, a bounding box + * is returned with default values (OPEN). */ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { const auto& route_trees = g_vpr_ctx.routing().route_trees; @@ -46,20 +48,14 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { for (auto& rt_node : route_tree.all_nodes()) { RRNodeId inode = rt_node.inode; - if (rr_graph.node_xlow(inode) < bb.xmin) - bb.xmin = rr_graph.node_xlow(inode); - if (rr_graph.node_xhigh(inode) > bb.xmax) - bb.xmax = rr_graph.node_xhigh(inode); + bb.xmin = std::min(static_cast(rr_graph.node_xlow(inode)), bb.xmin); + bb.xmax = std::max(static_cast(rr_graph.node_xhigh(inode)), bb.xmax); - if (rr_graph.node_ylow(inode) < bb.ymin) - bb.ymin = rr_graph.node_ylow(inode); - if (rr_graph.node_yhigh(inode) > bb.ymax) - bb.ymax = rr_graph.node_yhigh(inode); + bb.ymin = std::min(static_cast(rr_graph.node_ylow(inode)), bb.ymin); + bb.ymax = std::max(static_cast(rr_graph.node_yhigh(inode)), bb.ymax); - if (rr_graph.node_layer(inode) < bb.layer_min) - bb.layer_min = rr_graph.node_layer(inode); - if (rr_graph.node_layer(inode) > bb.layer_max) - bb.layer_max = rr_graph.node_layer(inode); + bb.layer_min = std::min(static_cast(rr_graph.node_layer(inode)), bb.layer_min); + bb.layer_max = std::max(static_cast(rr_graph.node_layer(inode)), bb.layer_max); } return bb; }; From e03f90c568a86ee89eeb826c635eea60001b8a2e Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 16 May 2025 12:28:15 -0400 Subject: [PATCH 23/29] [vpr][analysis] change report_net_timing format to csv --- vpr/src/analysis/timing_reports.cpp | 76 +++++++++++------------------ 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 4d87fa2c8f..dcb05ea778 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -180,75 +180,55 @@ void generate_hold_timing_stats(const std::string& prefix, timing_reporter.report_unconstrained_hold(prefix + "report_unconstrained_timing.hold.rpt", *timing_info.hold_analyzer()); } -void generate_net_timing_report(const std::string& prefix, - const SetupHoldTimingInfo& timing_info, - const AnalysisDelayCalculator& delay_calc) { - /* Create a report file for net timing information */ - std::ofstream os(prefix + "report_net_timing.rpt"); +void generate_net_timing_report_csv(const std::string& prefix, + const SetupHoldTimingInfo& timing_info, + const AnalysisDelayCalculator& delay_calc) { + std::ofstream os(prefix + "report_net_timing.csv"); const auto& atom_netlist = g_vpr_ctx.atom().netlist(); const auto& atom_lookup = g_vpr_ctx.atom().lookup(); - const auto& timing_ctx = g_vpr_ctx.timing(); const auto& timing_graph = timing_ctx.graph; - os << "# This file is generated by VTR" << std::endl; - os << "# Version: " << vtr::VERSION << std::endl; - os << "# Revision: " << vtr::VCS_REVISION << std::endl; - os << "# For each net, the timing information is reported in the following format:" << std::endl; - os << "# netname : Fanout : " - << "(bounding_box_xmin,bounding_box_ymin,bounding_box_layermin),(bounding_box_xmax,bounding_box_ymax,bounding_box_layermax) : " - << "source_instance : " - << " : " - << " : ..." - << std::endl; - - os << std::endl; + // Write CSV header + os << "netname,Fanout,bb_xmin,bb_ymin,bb_layer_min," + << "bb_xmax,bb_ymax,bb_layer_max," + << "src_pin_name,src_pin_slack,sinks" << std::endl; for (const auto& net : atom_netlist.nets()) { - /* Skip constant nets */ - if (atom_netlist.net_is_constant(net)) { - continue; - } + if (atom_netlist.net_is_constant(net)) continue; const auto& net_name = atom_netlist.net_name(net); - - /* Get source pin and its timing information */ const auto& source_pin = *atom_netlist.net_pins(net).begin(); auto source_pin_slack = timing_info.setup_pin_slack(source_pin); - /* Timing graph node id corresponding to the net's source pin */ auto tg_source_node = atom_lookup.atom_pin_tnode(source_pin); VTR_ASSERT(tg_source_node.is_valid()); const size_t fanout = atom_netlist.net_sinks(net).size(); const auto& net_bb = get_net_bounding_box(net); - os << net_name << " : " - << fanout << " : " - << "(" << net_bb.xmin << "," << net_bb.ymin << "," << net_bb.layer_min << "),(" - << net_bb.xmax << "," << net_bb.ymax << "," << net_bb.layer_max << ") : " - << atom_netlist.pin_name(source_pin).c_str() << " " << source_pin_slack << " : "; - - /* Iterate over all fanout pins and print their timing information */ - for (size_t net_pin_index = 1; net_pin_index <= fanout; ++net_pin_index) { - const auto& pin = *(atom_netlist.net_pins(net).begin() + net_pin_index); - - /* Get timing graph node id corresponding to the fanout pin */ - const auto& tg_sink_node = atom_lookup.atom_pin_tnode(pin); + + os << "\"" << net_name << "\"," // netname (quoted for safety) + << fanout << "," + << net_bb.xmin << "," << net_bb.ymin << "," << net_bb.layer_min << "," + << net_bb.xmax << "," << net_bb.ymax << "," << net_bb.layer_max << "," + << "\"" << atom_netlist.pin_name(source_pin) << "\"," << source_pin_slack << ","; + + // Write sinks column (quoted, semicolon-delimited, each sink: name,slack,delay) + os << "\""; + for (size_t i = 0; i < fanout; ++i) { + const auto& pin = *(atom_netlist.net_pins(net).begin() + i + 1); + auto tg_sink_node = atom_lookup.atom_pin_tnode(pin); VTR_ASSERT(tg_sink_node.is_valid()); - /* Get timing graph edge id between atom pins */ - const auto& tg_edge_id = timing_graph->find_edge(tg_source_node, tg_sink_node); + auto tg_edge_id = timing_graph->find_edge(tg_source_node, tg_sink_node); VTR_ASSERT(tg_edge_id.is_valid()); - /* Get timing information for the fanout pin */ - const auto& pin_setup_slack = timing_info.setup_pin_slack(pin); - const auto& pin_delay = delay_calc.max_edge_delay(*timing_graph, tg_edge_id); - + auto pin_setup_slack = timing_info.setup_pin_slack(pin); + auto pin_delay = delay_calc.max_edge_delay(*timing_graph, tg_edge_id); const auto& pin_name = atom_netlist.pin_name(pin); - os << pin_name << " " << std::scientific << pin_setup_slack << " " << pin_delay; - if (net_pin_index < fanout) { - os << " : "; - } + + os << pin_name << "," << pin_setup_slack << "," << pin_delay; + if (i != fanout - 1) os << ";"; } - os << "," << std::endl; + os << "\"" << std::endl; // Close quoted sinks field and finish the row } } From b8a60ea636faf99a996fa6880c94b89d799f18c9 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 16 May 2025 13:08:58 -0400 Subject: [PATCH 24/29] [vpr][analysis] update comments --- doc/src/vpr/command_line_usage.rst | 36 +++++++++++++++--------------- vpr/src/analysis/timing_reports.h | 28 ++++++++++++++--------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index f6e5b83147..40fc5de381 100644 --- a/doc/src/vpr/command_line_usage.rst +++ b/doc/src/vpr/command_line_usage.rst @@ -1520,26 +1520,26 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout .. option:: --generate_net_timing_report {on | off} - Generates a report that lists the bounding box, slack, and delay of every routed connection in a design in csv format (``report_net_timing.csv``). Fields in the report are: + Generates a report that lists the bounding box, slack, and delay of every routed connection in a design in CSV format (``report_net_timing.csv``). Each row in the CSV corresponds to a single net. + + Fields in the report are: .. code-block:: none - netname: The name assigned to the net in atom netlist - Fanout : Net's fanout - bb_xmin: X coordinate of the net's bounding box's bottom left corner - bb_ymin: Y coordinate of the net's bounding box's bottom left corner - bb_layer_min: Lowest layer number of the net's bounding box - bb_xmax: X coordinate of the net's bounding box's top right corner - bb_ymax: Y coordinate of the net's bounding box's top right corner - bb_layer_max: Highest layer number of the net's bounding box - src_pin_name: Name of the net's source pin - src_pin_slack: Slack of the net's source pin - sink_1_pin_name: Name of the net's first sink pin - sink_1_pin_slack: Slack of the net's first sink pin - sink_1_pin_delay: Delay of the net's first sink pin - sink_2_pin_name: Name of the net's second sink pin - sink_2_pin_slack: Slack of the net's second sink pin - sink_2_pin_delay: Delay of the net's second sink pin - ... + netname : The name assigned to the net in the atom netlist + Fanout : Net's fanout (number of sinks) + bb_xmin : X coordinate of the net's bounding box's bottom-left corner + bb_ymin : Y coordinate of the net's bounding box's bottom-left corner + bb_layer_min : Lowest layer number of the net's bounding box + bb_xmax : X coordinate of the net's bounding box's top-right corner + bb_ymax : Y coordinate of the net's bounding box's top-right corner + bb_layer_max : Highest layer number of the net's bounding box + src_pin_name : Name of the net's source pin + src_pin_slack : Setup slack of the net's source pin + sinks : A semicolon-separated list of sink pin entries, each in the format: + ,, + + Example value for the ``sinks`` field: + ``"U2.B,0.12,0.5;U3.C,0.10,0.6;U4.D,0.08,0.7"`` **Default:** ``off`` diff --git a/vpr/src/analysis/timing_reports.h b/vpr/src/analysis/timing_reports.h index 0aec721d76..f8ae0c6fc6 100644 --- a/vpr/src/analysis/timing_reports.h +++ b/vpr/src/analysis/timing_reports.h @@ -22,17 +22,25 @@ void generate_hold_timing_stats(const std::string& prefix, const BlkLocRegistry& blk_loc_registry); /** - * @brief Generates timing information for each net in atom netlist. For each net, the timing information - * is reported in the following format: - * netname : Fanout : - * (bounding_box_xmin,bounding_box_ymin,bounding_box_layermin),(bounding_box_xmax,bounding_box_ymax,bounding_box_layermax) : - * source_instance : - * : - * : ... + * @brief Generates a CSV report of timing information for each net in the atom netlist. * - * @param prefix The prefix for the report file to be added to filename: report_net_timing.rpt - * @param timing_info Updated timing information - * @param delay_calc Delay calculator + * Each row in the CSV corresponds to a single net and includes: + * - Net name + * - Fanout count + * - Bounding box (xmin, ymin, layer_min, xmax, ymax, layer_max) + * - Source pin name and slack + * - A single "sinks" field that encodes information for all sink pins + * + * The "sinks" field is a semicolon-separated list of all sink pins. + * Each sink pin is represented as a comma-separated triple: + * ,, + * + * Example row: + * netA,2,0,0,0,5,5,1,U1.A,0.25,"U2.B,0.12,0.5;U3.C,0.10,0.6" + * + * @param prefix Prefix for the output file name (report will be saved as report_net_timing.csv) + * @param timing_info Timing analysis results (slacks) + * @param delay_calc Delay calculator used to extract delay between nodes */ void generate_net_timing_report(const std::string& prefix, const SetupHoldTimingInfo& timing_info, From 87d161ca5d6e2ec9b2d88e07d8700e558ffac9c7 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 16 May 2025 13:12:31 -0400 Subject: [PATCH 25/29] [vpr][analysis] print constant nets in the net timing report --- vpr/src/analysis/timing_reports.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index dcb05ea778..5a0180672d 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -195,8 +195,6 @@ void generate_net_timing_report_csv(const std::string& prefix, << "src_pin_name,src_pin_slack,sinks" << std::endl; for (const auto& net : atom_netlist.nets()) { - if (atom_netlist.net_is_constant(net)) continue; - const auto& net_name = atom_netlist.net_name(net); const auto& source_pin = *atom_netlist.net_pins(net).begin(); auto source_pin_slack = timing_info.setup_pin_slack(source_pin); From 7649fdd81cd30db9017ef30f759c125b3fadddfc Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 16 May 2025 13:16:07 -0400 Subject: [PATCH 26/29] [vpr][analysis] apply comments --- vpr/src/analysis/timing_reports.cpp | 1 + vpr/src/base/read_options.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 5a0180672d..ce90e501fd 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -197,6 +197,7 @@ void generate_net_timing_report_csv(const std::string& prefix, for (const auto& net : atom_netlist.nets()) { const auto& net_name = atom_netlist.net_name(net); const auto& source_pin = *atom_netlist.net_pins(net).begin(); + // for the driver/source, this is the worst slack to any fanout. auto source_pin_slack = timing_info.setup_pin_slack(source_pin); auto tg_source_node = atom_lookup.atom_pin_tnode(source_pin); VTR_ASSERT(tg_source_node.is_valid()); diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index f092f77ae0..6b73aa5238 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -3089,7 +3089,10 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio .show_in(argparse::ShowIn::HELP_ONLY); analysis_grp.add_argument(args.generate_net_timing_report, "--generate_net_timing_report") - .help("Generates a net timing report for each net in the design.") + .help( + "Generates a net timing report in CSV format, reporting the delay and slack\n" + "for every routed connection in the design.\n" + "The report is saved as 'report_net_timing.csv'.") .default_value("off") .show_in(argparse::ShowIn::HELP_ONLY); From f699b3011d67704a562fff8b39ddba389e6d569f Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 16 May 2025 13:25:53 -0400 Subject: [PATCH 27/29] [vpr][analysis] fix function name --- vpr/src/analysis/timing_reports.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index ce90e501fd..eeffe27e01 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -180,9 +180,9 @@ void generate_hold_timing_stats(const std::string& prefix, timing_reporter.report_unconstrained_hold(prefix + "report_unconstrained_timing.hold.rpt", *timing_info.hold_analyzer()); } -void generate_net_timing_report_csv(const std::string& prefix, - const SetupHoldTimingInfo& timing_info, - const AnalysisDelayCalculator& delay_calc) { +void generate_net_timing_report(const std::string& prefix, + const SetupHoldTimingInfo& timing_info, + const AnalysisDelayCalculator& delay_calc) { std::ofstream os(prefix + "report_net_timing.csv"); const auto& atom_netlist = g_vpr_ctx.atom().netlist(); const auto& atom_lookup = g_vpr_ctx.atom().lookup(); From aaf2569de4ce34f770f0dd8215859771068cbdd6 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 16 May 2025 13:33:27 -0400 Subject: [PATCH 28/29] [doc] add net timing report use case --- doc/src/vpr/command_line_usage.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index 40fc5de381..1f15da623f 100644 --- a/doc/src/vpr/command_line_usage.rst +++ b/doc/src/vpr/command_line_usage.rst @@ -1522,6 +1522,8 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout Generates a report that lists the bounding box, slack, and delay of every routed connection in a design in CSV format (``report_net_timing.csv``). Each row in the CSV corresponds to a single net. + The report can later be used by other tools to enable further optimizations. For example, the Synopsys synthesis tool (Synplify) can use this information to re-synthesize the design and improve the Quality of Results (QoR). + Fields in the report are: .. code-block:: none From 33291d362cad9383d9f8125329fd22370a891b01 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 16 May 2025 15:17:11 -0400 Subject: [PATCH 29/29] fix a typo --- doc/src/vpr/command_line_usage.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index 1f15da623f..94c4a4f6d7 100644 --- a/doc/src/vpr/command_line_usage.rst +++ b/doc/src/vpr/command_line_usage.rst @@ -1527,6 +1527,7 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout Fields in the report are: .. code-block:: none + netname : The name assigned to the net in the atom netlist Fanout : Net's fanout (number of sinks) bb_xmin : X coordinate of the net's bounding box's bottom-left corner