4
4
#include " globals.h"
5
5
#include " vtr_log.h"
6
6
7
+ /* *
8
+ * @brief Definitions of global and helper routines related to printing RR node overuse info.
9
+ *
10
+ * All the global routines defined here are declared in the header file overuse_report.h
11
+ * The helper routines that are called by the global routine should stay local to this file.
12
+ * They provide subroutine hierarchy to allow easier customization of the logfile/report format.
13
+ */
14
+
15
+ static void report_overused_ipin_opin (std::ostream& os, RRNodeId node_id);
16
+ static void report_overused_chanx_chany (std::ostream& os, RRNodeId node_id);
17
+ static void report_overused_source_sink (std::ostream& os, RRNodeId node_id);
18
+ static void report_congested_nets (std::ostream& os, const std::set<ClusterNetId>& congested_nets);
19
+
7
20
static void log_overused_nodes_header ();
8
21
static void log_single_overused_node_status (int overuse_index, RRNodeId inode);
9
22
23
+ /* *
24
+ * @brief Print out RR node overuse info in the VPR logfile.
25
+ *
26
+ * Print out limited amount of overused node info in the vpr.out logfile.
27
+ * The limit is specified by the VPR option --max_logged_overused_rr_nodes
28
+ */
10
29
void log_overused_nodes_status (int max_logged_overused_rr_nodes) {
11
30
const auto & device_ctx = g_vpr_ctx.device ();
12
31
const auto & route_ctx = g_vpr_ctx.routing ();
@@ -31,77 +50,83 @@ void log_overused_nodes_status(int max_logged_overused_rr_nodes) {
31
50
}
32
51
}
33
52
53
+ /* *
54
+ * @brief Print out RR node overuse info in a post-VPR report file.
55
+ *
56
+ * Print all the overused RR nodes' info in the report file report_overused_nodes.rpt.
57
+ * The report generation is turned on by the VPR option: --generate_rr_node_overuse_report on.
58
+ * This report will be generated only if the last routing attempt fails, which
59
+ * causes the whole VPR flow to fail.
60
+ */
34
61
void report_overused_nodes () {
35
62
const auto & device_ctx = g_vpr_ctx.device ();
36
63
const auto & route_ctx = g_vpr_ctx.routing ();
37
- const auto & clb_nlist = g_vpr_ctx.clustering ().clb_nlist ;
38
64
39
- // Generate overuse infor lookup table
65
+ /* Generate overuse info lookup table */
40
66
std::map<RRNodeId, std::set<ClusterNetId>> nodes_to_nets_lookup;
41
67
generate_overused_nodes_to_congested_net_lookup (nodes_to_nets_lookup);
42
68
43
- // Open the report file
69
+ /* Open the report file and print header info */
44
70
std::ofstream os (" report_overused_nodes.rpt" );
45
71
os << " Overused nodes information report on the final failed routing attempt" << ' \n ' ;
46
72
os << " Total number of overused nodes = " << nodes_to_nets_lookup.size () << ' \n ' ;
47
73
48
- int inode = 0 ;
49
-
74
+ /* Go through each rr node and the nets that pass through it */
75
+ size_t inode = 0 ;
50
76
for (const auto & lookup_pair : nodes_to_nets_lookup) {
51
77
const RRNodeId node_id = lookup_pair.first ;
52
78
const auto & congested_nets = lookup_pair.second ;
53
79
54
- os << " ************************************************\n\n " ; // RR Node Separation line
80
+ os << " ************************************************\n\n " ; // Separation line
55
81
56
- // Report Basic info
82
+ /* Report basic rr node info */
57
83
os << " Overused RR node #" << inode << ' \n ' ;
58
84
os << " Node id = " << size_t (node_id) << ' \n ' ;
59
85
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 ' ;
86
+ os << " Capacity = " << device_ctx.rr_nodes .node_capacity (node_id) << " \n\n " ;
67
87
68
- // Report Selective info
88
+ /* Report selective info based on the rr node type */
69
89
auto node_type = device_ctx.rr_nodes .node_type (node_id);
90
+ os << " Node type = " << device_ctx.rr_nodes .node_type_string (node_id) << ' \n ' ;
70
91
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 ' ;
92
+ switch (node_type) {
93
+ case IPIN:
94
+ case OPIN:
95
+ report_overused_ipin_opin (os, node_id);
96
+ break ;
97
+ case CHANX:
98
+ case CHANY:
99
+ report_overused_chanx_chany (os, node_id);
100
+ break ;
101
+ case SOURCE:
102
+ case SINK:
103
+ report_overused_source_sink (os, node_id);
104
+ break ;
105
+
106
+ default :
107
+ break ;
78
108
}
79
109
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);
110
+ /* Finished printing the node info. Now print out the *
111
+ * info on the nets passing through this overused node */
112
+ os << " -----------------------------\n " ; // Separation line
113
+ report_congested_nets (os, congested_nets);
88
114
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
115
++inode;
100
116
}
101
117
102
118
os.close ();
103
119
}
104
120
121
+ /* *
122
+ * @brief Generate a overused RR nodes to congested nets lookup table.
123
+ *
124
+ * Uses map data structure to store a lookup table that matches RR nodes
125
+ * to the nets that pass through them. Only overused nodes and congested
126
+ * nets will be recorded.
127
+ *
128
+ * This routine goes through the trace back linked list of each net.
129
+ */
105
130
void generate_overused_nodes_to_congested_net_lookup (std::map<RRNodeId, std::set<ClusterNetId>>& nodes_to_nets_lookup) {
106
131
const auto & device_ctx = g_vpr_ctx.device ();
107
132
const auto & route_ctx = g_vpr_ctx.routing ();
@@ -121,6 +146,102 @@ void generate_overused_nodes_to_congested_net_lookup(std::map<RRNodeId, std::set
121
146
}
122
147
}
123
148
149
+ // /@brief Print out information specific to IPIN/OPIN type rr nodes
150
+ static void report_overused_ipin_opin (std::ostream& os, RRNodeId node_id) {
151
+ const auto & device_ctx = g_vpr_ctx.device ();
152
+ const auto & place_ctx = g_vpr_ctx.placement ();
153
+
154
+ auto grid_x = device_ctx.rr_nodes .node_xlow (node_id);
155
+ auto grid_y = device_ctx.rr_nodes .node_ylow (node_id);
156
+ VTR_ASSERT_MSG (
157
+ grid_x == device_ctx.rr_nodes .node_xhigh (node_id) && grid_y == device_ctx.rr_nodes .node_yhigh (node_id),
158
+ " Non-track RR node should not span across multiple grid blocks." );
159
+
160
+ os << " Pin number = " << device_ctx.rr_nodes .node_pin_num (node_id) << ' \n ' ;
161
+ os << " Side = " << device_ctx.rr_nodes .node_side_string (node_id) << " \n\n " ;
162
+
163
+ // Add block type for IPINs/OPINs in overused rr-node report
164
+ const auto & clb_nlist = g_vpr_ctx.clustering ().clb_nlist ;
165
+ auto & grid_info = place_ctx.grid_blocks [grid_x][grid_y];
166
+
167
+ os << " Grid location: X = " << grid_x << " , Y = " << grid_y << ' \n ' ;
168
+ os << " Number of blocks currently occupying this grid location = " << grid_info.usage << ' \n ' ;
169
+
170
+ size_t iblock = 0 ;
171
+ for (size_t isubtile = 0 ; isubtile < grid_info.blocks .size (); ++isubtile) {
172
+ // Check if there is a valid block at this subtile location
173
+ if (grid_info.subtile_empty (isubtile)) {
174
+ continue ;
175
+ }
176
+
177
+ // Print out the block index, name and type
178
+ ClusterBlockId block_id = grid_info.blocks [isubtile];
179
+ os << " Block #" << iblock << " : " ;
180
+ os << " Block name = " << clb_nlist.block_pb (block_id)->name << " , " ;
181
+ os << " Block type = " << clb_nlist.block_type (block_id)->name << ' \n ' ;
182
+ ++iblock;
183
+ }
184
+ }
185
+
186
+ // /@brief Print out information specific to CHANX/CHANY type rr nodes
187
+ static void report_overused_chanx_chany (std::ostream& os, RRNodeId node_id) {
188
+ const auto & device_ctx = g_vpr_ctx.device ();
189
+
190
+ os << " Track number = " << device_ctx.rr_nodes .node_track_num (node_id) << ' \n ' ;
191
+ os << " Direction = " << device_ctx.rr_nodes .node_direction_string (node_id) << " \n\n " ;
192
+
193
+ // CHANX/CHANY rr nodes span across several grid locations.
194
+ // Need to print out their starting and ending locations.
195
+ os << " Grid location: " << ' \n ' ;
196
+ os << " Xlow = " << device_ctx.rr_nodes .node_xlow (node_id) << " , " ;
197
+ os << " Ylow = " << device_ctx.rr_nodes .node_ylow (node_id) << ' \n ' ;
198
+ os << " Xhigh = " << device_ctx.rr_nodes .node_xhigh (node_id) << " , " ;
199
+ os << " Yhigh = " << device_ctx.rr_nodes .node_yhigh (node_id) << ' \n ' ;
200
+
201
+ // Print out associated RC characteristics as they will be non-zero
202
+ os << " Resistance = " << device_ctx.rr_nodes .node_R (node_id) << ' \n ' ;
203
+ os << " Capacitance = " << device_ctx.rr_nodes .node_C (node_id) << ' \n ' ;
204
+ }
205
+
206
+ // /@brief Print out information specific to SOURCE/SINK type rr nodes
207
+ static void report_overused_source_sink (std::ostream& os, RRNodeId node_id) {
208
+ const auto & device_ctx = g_vpr_ctx.device ();
209
+
210
+ auto grid_x = device_ctx.rr_nodes .node_xlow (node_id);
211
+ auto grid_y = device_ctx.rr_nodes .node_ylow (node_id);
212
+ VTR_ASSERT_MSG (
213
+ grid_x == device_ctx.rr_nodes .node_xhigh (node_id) && grid_y == device_ctx.rr_nodes .node_yhigh (node_id),
214
+ " Non-track RR node should not span across multiple grid blocks." );
215
+
216
+ os << " Class number = " << device_ctx.rr_nodes .node_class_num (node_id) << ' \n ' ;
217
+ os << " Grid location: X = " << grid_x << " , Y = " << grid_y << ' \n ' ;
218
+ }
219
+
220
+ /* *
221
+ * @brief Print out info on congested nets in the router.
222
+ *
223
+ * Report information on the congested nets that pass through a specific rr node. *
224
+ * These nets are congested because the number of nets currently passing through *
225
+ * this rr node exceed the node's routing net capacity.
226
+ */
227
+ static void report_congested_nets (std::ostream& os, const std::set<ClusterNetId>& congested_nets) {
228
+ const auto & clb_nlist = g_vpr_ctx.clustering ().clb_nlist ;
229
+ os << " Number of nets passing through this RR node = " << congested_nets.size () << ' \n ' ;
230
+
231
+ size_t inet = 0 ;
232
+ for (ClusterNetId net_id : congested_nets) {
233
+ ClusterBlockId block_id = clb_nlist.net_driver_block (net_id);
234
+ os << " Net #" << inet << " : " ;
235
+ os << " Net ID = " << size_t (net_id) << " , " ;
236
+ os << " Net name = " << clb_nlist.net_name (net_id) << " , " ;
237
+ os << " Driving block name = " << clb_nlist.block_pb (block_id)->name << " , " ;
238
+ os << " Driving block type = " << clb_nlist.block_type (block_id)->name << ' \n ' ;
239
+ ++inet;
240
+ }
241
+ os << ' \n ' ;
242
+ }
243
+
244
+ // /@brief Print out the header of the overused rr node info in the logfile
124
245
static void log_overused_nodes_header () {
125
246
VTR_LOG (" Routing Failure Diagnostics: Printing Overused Nodes Information\n " );
126
247
VTR_LOG (" ------ ------- ---------- --------- -------- ------------ ------- ------- ------- ------- ------- -------\n " );
@@ -129,6 +250,7 @@ static void log_overused_nodes_header() {
129
250
VTR_LOG (" ------ ------- ---------- --------- -------- ------------ ------- ------- ------- ------- ------- -------\n " );
130
251
}
131
252
253
+ // /@brief Print out a single-line info that corresponds to a single overused rr node in the logfile
132
254
static void log_single_overused_node_status (int overuse_index, RRNodeId node_id) {
133
255
const auto & device_ctx = g_vpr_ctx.device ();
134
256
const auto & route_ctx = g_vpr_ctx.routing ();
0 commit comments