Skip to content

Commit 6b8fdbe

Browse files
authored
Print out info/report on overused rr-nodes at the end of a failed routing iteration (#1455)
* Print overused info if routing fails. Formatted header and overused nodes info body * Minor fix to display format * Added option to set the limit for max reported overused RR nodes * Changed the command line option to --generate_rr_node_overuse_report. Also print a message if the # of overused nodes is too large for logging. * Added option --generate_rr_node_overuse_report on for a detailed report on overused nodes * Added congested nets to the overuse report * Moved overuse info routines to separate files * Changed the overused nodes report generation to take effect only when the final routing attempt has failed. Also fixed a bug where a single net counts a overused node for multiple times in the report * Changed indexing of the report functions from size_t to RRNodeId (strong ids). Also added new accessors for the rr_graph_storage interface * Added documentation for the two new command line options * Added detailed congested net info to the overused RR node report * Improved the logging file: will display overused nodes entries up to the threshold number if the threshold is exceeded. Add reminder for the report generation option at the end of vpr.out logfile should the router fails to implement the circuit. * Update documentation according to the latest change to the logfile
1 parent b8fcc16 commit 6b8fdbe

File tree

11 files changed

+307
-1
lines changed

11 files changed

+307
-1
lines changed

doc/src/vpr/command_line_usage.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,24 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout
10081008

10091009
**Default:** ``16``
10101010

1011+
.. option:: --max_logged_overused_rr_nodes <int>
1012+
1013+
Prints the information on overused RR nodes to the VPR log file after the each failed routing attempt.
1014+
1015+
If the number of overused nodes is above the given threshold ``N``, then only the first ``N`` entries are printed to the logfile.
1016+
1017+
**Default:** ``20``
1018+
1019+
.. option:: --generate_rr_node_overuse_report {on | off}
1020+
1021+
Generates a detailed report on the overused RR nodes' information: **report_overused_nodes.rpt**.
1022+
1023+
This report is generated only when the final routing attempt fails (i.e. the whole routing process has failed).
1024+
1025+
In addition to the information that can be seen via ``--max_logged_overused_rr_nodes``, this report prints out all the net ids that are associated with each overused RR node. Also, this report does not place a threshold upon the number of RR nodes printed.
1026+
1027+
**Default:** ``off``
1028+
10111029
.. _timing_driven_router_options:
10121030

10131031
Timing-Driven Router Options

vpr/src/base/SetupVPR.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,9 @@ static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts)
392392

393393
RouterOpts->check_route = Options.check_route;
394394
RouterOpts->timing_update_type = Options.timing_update_type;
395+
396+
RouterOpts->max_logged_overused_rr_nodes = Options.max_logged_overused_rr_nodes;
397+
RouterOpts->generate_rr_node_overuse_report = Options.generate_rr_node_overuse_report;
395398
}
396399

397400
static void SetupAnnealSched(const t_options& Options,

vpr/src/base/read_options.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,6 +1855,16 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
18551855
.default_value("off")
18561856
.show_in(argparse::ShowIn::HELP_ONLY);
18571857

1858+
route_grp.add_argument(args.max_logged_overused_rr_nodes, "--max_logged_overused_rr_nodes")
1859+
.help("Maximum number of overused RR nodes logged each time the routing fails")
1860+
.default_value("20")
1861+
.show_in(argparse::ShowIn::HELP_ONLY);
1862+
1863+
route_grp.add_argument<bool, ParseOnOff>(args.generate_rr_node_overuse_report, "--generate_rr_node_overuse_report")
1864+
.help("Generate detailed reports on overused rr nodes and congested nets should the routing fails")
1865+
.default_value("off")
1866+
.show_in(argparse::ShowIn::HELP_ONLY);
1867+
18581868
auto& route_timing_grp = parser.add_argument_group("timing-driven routing options");
18591869

18601870
route_timing_grp.add_argument(args.astar_fac, "--astar_fac")

vpr/src/base/read_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ struct t_options {
150150
argparse::ArgValue<bool> read_rr_edge_metadata;
151151
argparse::ArgValue<bool> exit_after_first_routing_iteration;
152152
argparse::ArgValue<e_check_route_option> check_route;
153+
argparse::ArgValue<size_t> max_logged_overused_rr_nodes;
154+
argparse::ArgValue<bool> generate_rr_node_overuse_report;
153155

154156
/* Timing-driven router options only */
155157
argparse::ArgValue<float> astar_fac;

vpr/src/base/vpr_api.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
#include "cluster.h"
7070

7171
#include "pack_report.h"
72+
#include "overuse_report.h"
7273

7374
#include "timing_graph_builder.h"
7475
#include "timing_reports.h"
@@ -726,13 +727,24 @@ RouteStatus vpr_route_flow(t_vpr_setup& vpr_setup, const t_arch& arch) {
726727

727728
//Update status
728729
VTR_LOG("Circuit successfully routed with a channel width factor of %d.\n", route_status.chan_width());
729-
graphics_msg = vtr::string_fmt("Routing succeeded with a channel width factor of %d.", route_status.chan_width());
730+
graphics_msg = vtr::string_fmt("Routing succeeded with a channel width factor of %d.\n", route_status.chan_width());
730731
} else {
731732
//Update status
732733
VTR_LOG("Circuit is unroutable with a channel width factor of %d.\n", route_status.chan_width());
733734
graphics_msg = vtr::string_fmt("Routing failed with a channel width factor of %d. ILLEGAL routing shown.", route_status.chan_width());
735+
736+
//Generate a report on overused nodes if specified
737+
//Otherwise, remind the user of this possible report option
738+
if (router_opts.generate_rr_node_overuse_report) {
739+
VTR_LOG("See report_overused_nodes.rpt for a detailed report on the RR node overuse information.\n");
740+
report_overused_nodes();
741+
} else {
742+
VTR_LOG("For a detailed report on the RR node overuse information (report_overused_nodes.rpt), specify --generate_rr_node_overuse_report on.\n");
743+
}
734744
}
735745

746+
VTR_LOG("\n");
747+
736748
//Echo files
737749
if (vpr_setup.Timing.timing_analysis_enabled) {
738750
if (isEchoFileEnabled(E_ECHO_FINAL_ROUTING_TIMING_GRAPH)) {

vpr/src/base/vpr_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,9 @@ struct t_router_opts {
10991099

11001100
e_check_route_option check_route;
11011101
e_timing_update_type timing_update_type;
1102+
1103+
size_t max_logged_overused_rr_nodes;
1104+
bool generate_rr_node_overuse_report;
11021105
};
11031106

11041107
struct t_analysis_opts {

vpr/src/route/overuse_report.cpp

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
#include "overuse_report.h"
2+
3+
#include <fstream>
4+
#include "globals.h"
5+
#include "vtr_log.h"
6+
7+
static void log_overused_nodes_header();
8+
static void log_single_overused_node_status(int overuse_index, RRNodeId inode);
9+
10+
void log_overused_nodes_status(int max_logged_overused_rr_nodes) {
11+
const auto& device_ctx = g_vpr_ctx.device();
12+
const auto& route_ctx = g_vpr_ctx.routing();
13+
14+
//Print overuse info header
15+
log_overused_nodes_header();
16+
17+
//Print overuse info body
18+
int overuse_index = 0;
19+
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
20+
int overuse = route_ctx.rr_node_route_inf[inode].occ() - device_ctx.rr_nodes[inode].capacity();
21+
22+
if (overuse > 0) {
23+
log_single_overused_node_status(overuse_index, RRNodeId(inode));
24+
++overuse_index;
25+
26+
//Reached the logging limit
27+
if (overuse_index >= max_logged_overused_rr_nodes) {
28+
return;
29+
}
30+
}
31+
}
32+
}
33+
34+
void report_overused_nodes() {
35+
const auto& device_ctx = g_vpr_ctx.device();
36+
const auto& route_ctx = g_vpr_ctx.routing();
37+
const auto& clb_nlist = g_vpr_ctx.clustering().clb_nlist;
38+
39+
//Generate overuse infor lookup table
40+
std::map<RRNodeId, std::set<ClusterNetId>> nodes_to_nets_lookup;
41+
generate_overused_nodes_to_congested_net_lookup(nodes_to_nets_lookup);
42+
43+
//Open the report file
44+
std::ofstream os("report_overused_nodes.rpt");
45+
os << "Overused nodes information report on the final failed routing attempt" << '\n';
46+
os << "Total number of overused nodes = " << nodes_to_nets_lookup.size() << '\n';
47+
48+
int inode = 0;
49+
50+
for (const auto& lookup_pair : nodes_to_nets_lookup) {
51+
const RRNodeId node_id = lookup_pair.first;
52+
const auto& congested_nets = lookup_pair.second;
53+
54+
os << "************************************************\n\n"; //RR Node Separation line
55+
56+
//Report Basic info
57+
os << "Overused RR node #" << inode << '\n';
58+
os << "Node id = " << size_t(node_id) << '\n';
59+
os << "Occupancy = " << route_ctx.rr_node_route_inf[size_t(node_id)].occ() << '\n';
60+
os << "Capacity = " << device_ctx.rr_nodes.node_capacity(node_id) << '\n';
61+
os << "Node type = " << device_ctx.rr_nodes.node_type_string(node_id) << '\n';
62+
os << "PTC number = " << device_ctx.rr_nodes.node_ptc_num(node_id) << '\n';
63+
os << "Xlow = " << device_ctx.rr_nodes.node_xlow(node_id) << ", ";
64+
os << "Ylow = " << device_ctx.rr_nodes.node_ylow(node_id) << '\n';
65+
os << "Xhigh = " << device_ctx.rr_nodes.node_xhigh(node_id) << ", ";
66+
os << "Yhigh = " << device_ctx.rr_nodes.node_yhigh(node_id) << '\n';
67+
68+
//Report Selective info
69+
auto node_type = device_ctx.rr_nodes.node_type(node_id);
70+
71+
if (node_type == e_rr_type::CHANX || node_type == e_rr_type::CHANY) {
72+
os << "Direction = " << device_ctx.rr_nodes.node_direction_string(node_id) << '\n';
73+
74+
os << "Resistance = " << device_ctx.rr_nodes.node_R(node_id) << '\n';
75+
os << "Capacitance = " << device_ctx.rr_nodes.node_C(node_id) << '\n';
76+
} else if (node_type == e_rr_type::IPIN || node_type == e_rr_type::OPIN) {
77+
os << "Side = " << device_ctx.rr_nodes.node_side_string(node_id) << '\n';
78+
}
79+
80+
os << "-----------------------------\n"; //Node/net info separation line
81+
82+
//Reported corresponding congested nets
83+
int inet = 0;
84+
85+
os << "Number of nets passing through this RR node = " << congested_nets.size() << '\n';
86+
for (ClusterNetId net_id : congested_nets) {
87+
ClusterBlockId block_id = clb_nlist.net_driver_block(net_id);
88+
89+
os << "Net #" << inet << ": ";
90+
os << "Net ID = " << size_t(net_id) << ", ";
91+
os << "Net name = " << clb_nlist.net_name(net_id) << ", ";
92+
os << "Driving block name = " << clb_nlist.block_pb(block_id)->name << ", ";
93+
os << "Driving block type = " << clb_nlist.block_type(block_id)->name << '\n';
94+
95+
++inet;
96+
}
97+
98+
os << '\n';
99+
++inode;
100+
}
101+
102+
os.close();
103+
}
104+
105+
void generate_overused_nodes_to_congested_net_lookup(std::map<RRNodeId, std::set<ClusterNetId>>& nodes_to_nets_lookup) {
106+
const auto& device_ctx = g_vpr_ctx.device();
107+
const auto& route_ctx = g_vpr_ctx.routing();
108+
const auto& cluster_ctx = g_vpr_ctx.clustering();
109+
110+
//Create overused nodes to congested nets look up by
111+
//traversing through the net trace backs linked lists
112+
for (ClusterNetId net_id : cluster_ctx.clb_nlist.nets()) {
113+
for (t_trace* tptr = route_ctx.trace[net_id].head; tptr != nullptr; tptr = tptr->next) {
114+
int inode = tptr->index;
115+
116+
int overuse = route_ctx.rr_node_route_inf[inode].occ() - device_ctx.rr_nodes[inode].capacity();
117+
if (overuse > 0) {
118+
nodes_to_nets_lookup[RRNodeId(inode)].insert(net_id);
119+
}
120+
}
121+
}
122+
}
123+
124+
static void log_overused_nodes_header() {
125+
VTR_LOG("Routing Failure Diagnostics: Printing Overused Nodes Information\n");
126+
VTR_LOG("------ ------- ---------- --------- -------- ------------ ------- ------- ------- ------- ------- -------\n");
127+
VTR_LOG(" No. NodeId Occupancy Capacity RR Node Direction Side PTC Xlow Ylow Xhigh Yhigh\n");
128+
VTR_LOG(" type NUM \n");
129+
VTR_LOG("------ ------- ---------- --------- -------- ------------ ------- ------- ------- ------- ------- -------\n");
130+
}
131+
132+
static void log_single_overused_node_status(int overuse_index, RRNodeId node_id) {
133+
const auto& device_ctx = g_vpr_ctx.device();
134+
const auto& route_ctx = g_vpr_ctx.routing();
135+
136+
//Determines if direction or side is available for printing
137+
auto node_type = device_ctx.rr_nodes.node_type(node_id);
138+
139+
//Overuse #
140+
VTR_LOG("%6d", overuse_index);
141+
142+
//Inode
143+
VTR_LOG(" %7d", size_t(node_id));
144+
145+
//Occupancy
146+
VTR_LOG(" %10d", route_ctx.rr_node_route_inf[size_t(node_id)].occ());
147+
148+
//Capacity
149+
VTR_LOG(" %9d", device_ctx.rr_nodes.node_capacity(node_id));
150+
151+
//RR node type
152+
VTR_LOG(" %8s", device_ctx.rr_nodes.node_type_string(node_id));
153+
154+
//Direction
155+
if (node_type == e_rr_type::CHANX || node_type == e_rr_type::CHANY) {
156+
VTR_LOG(" %12s", device_ctx.rr_nodes.node_direction_string(node_id));
157+
} else {
158+
VTR_LOG(" %12s", "N/A");
159+
}
160+
161+
//Side
162+
if (node_type == e_rr_type::IPIN || node_type == e_rr_type::OPIN) {
163+
VTR_LOG(" %7s", device_ctx.rr_nodes.node_side_string(node_id));
164+
} else {
165+
VTR_LOG(" %7s", "N/A");
166+
}
167+
168+
//PTC number
169+
VTR_LOG(" %7d", device_ctx.rr_nodes.node_ptc_num(node_id));
170+
171+
//X_low
172+
VTR_LOG(" %7d", device_ctx.rr_nodes.node_xlow(node_id));
173+
174+
//Y_low
175+
VTR_LOG(" %7d", device_ctx.rr_nodes.node_ylow(node_id));
176+
177+
//X_high
178+
VTR_LOG(" %7d", device_ctx.rr_nodes.node_xhigh(node_id));
179+
180+
//Y_high
181+
VTR_LOG(" %7d", device_ctx.rr_nodes.node_yhigh(node_id));
182+
183+
VTR_LOG("\n");
184+
185+
fflush(stdout);
186+
}

vpr/src/route/overuse_report.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
3+
#include "rr_graph_storage.h"
4+
#include <map>
5+
6+
void log_overused_nodes_status(int max_logged_overused_rr_nodes);
7+
void report_overused_nodes();
8+
void generate_overused_nodes_to_congested_net_lookup(std::map<RRNodeId, std::set<ClusterNetId>>& nodes_to_nets_lookup);

vpr/src/route/route_timing.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "router_lookahead_map.h"
4040

4141
#include "tatum/TimingReporter.hpp"
42+
#include "overuse_report.h"
4243

4344
#define CONGESTED_SLOPE_VAL -0.04
4445

@@ -65,6 +66,9 @@ struct RoutingMetrics {
6566
//Note only enables debug output if compiled with VTR_ENABLE_DEBUG_LOGGING defined
6667
bool f_router_debug = false;
6768

69+
//Count the number of times the router has failed
70+
static int num_routing_failed = 0;
71+
6872
/******************** Subroutines local to route_timing.c ********************/
6973

7074
template<typename ConnectionRouter>
@@ -131,6 +135,8 @@ static void print_route_status(int itry,
131135
std::shared_ptr<const SetupHoldTimingInfo> timing_info,
132136
float est_success_iteration);
133137

138+
static void print_overused_nodes_status(const t_router_opts& router_opts, const OveruseInfo& overuse_info);
139+
134140
static void print_router_criticality_histogram(const SetupTimingInfo& timing_info,
135141
const ClusteredPinAtomPinsLookup& netlist_pin_lookup);
136142

@@ -715,6 +721,12 @@ bool try_timing_driven_route_tmpl(const t_router_opts& router_opts,
715721
VTR_LOG("Successfully routed after %d routing iterations.\n", itry);
716722
} else {
717723
VTR_LOG("Routing failed.\n");
724+
725+
//If the routing fails, print the overused info
726+
print_overused_nodes_status(router_opts, overuse_info);
727+
728+
++num_routing_failed;
729+
718730
#ifdef VTR_ENABLE_DEBUG_LOGGING
719731
if (f_router_debug) print_invalid_routing_info();
720732
#endif
@@ -1669,6 +1681,24 @@ static void print_route_status(int itry, double elapsed_sec, float pres_fac, int
16691681
fflush(stdout);
16701682
}
16711683

1684+
static void print_overused_nodes_status(const t_router_opts& router_opts, const OveruseInfo& overuse_info) {
1685+
//Print the index of this routing failure
1686+
VTR_LOG("\nFailed routing attempt #%d\n", num_routing_failed);
1687+
1688+
size_t num_overused = overuse_info.overused_nodes;
1689+
size_t max_logged_overused_rr_nodes = router_opts.max_logged_overused_rr_nodes;
1690+
1691+
//Overused nodes info logging upper limit
1692+
VTR_LOG("Total number of overused nodes: %d\n", num_overused);
1693+
if (num_overused > max_logged_overused_rr_nodes) {
1694+
VTR_LOG("Total number of overused nodes is larger than the logging limit (%d).\n", max_logged_overused_rr_nodes);
1695+
VTR_LOG("Displaying the first %d entries.\n", max_logged_overused_rr_nodes);
1696+
}
1697+
1698+
log_overused_nodes_status(max_logged_overused_rr_nodes);
1699+
VTR_LOG("\n");
1700+
}
1701+
16721702
static void print_router_criticality_histogram(const SetupTimingInfo& timing_info, const ClusteredPinAtomPinsLookup& netlist_pin_lookup) {
16731703
print_histogram(create_criticality_histogram(timing_info, netlist_pin_lookup, 10));
16741704
}

0 commit comments

Comments
 (0)