Skip to content

Commit 964a578

Browse files
authored
Merge pull request #1489 from Bill-hbrhbr/IpinOveruseInfo
Added block information for the IPIN/OPIN grid location in the overuse report
2 parents 35cdc29 + 6ef581f commit 964a578

File tree

3 files changed

+200
-42
lines changed

3 files changed

+200
-42
lines changed

vpr/src/base/vpr_types.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -706,8 +706,25 @@ struct t_block_loc {
706706

707707
///@brief Stores the clustered blocks placed at a particular grid location
708708
struct t_grid_blocks {
709-
int usage; ///<How many valid blocks are in use at this location
710-
std::vector<ClusterBlockId> blocks; ///<The clustered blocks associated with this grid location
709+
int usage; ///<How many valid blocks are in use at this location
710+
711+
/**
712+
* @brief The clustered blocks associated with this grid location.
713+
*
714+
* Index range: [0..device_ctx.grid[x_loc][y_loc].type->capacity]
715+
*/
716+
std::vector<ClusterBlockId> blocks;
717+
718+
/**
719+
* @brief Test if a subtile at a grid location is occupied by a block.
720+
*
721+
* Returns true if the subtile corresponds to the passed-in id is not
722+
* occupied by a block at this grid location. The subtile id serves
723+
* as the z-dimensional offset in the grid indexing.
724+
*/
725+
inline bool subtile_empty(size_t isubtile) const {
726+
return blocks[isubtile] == EMPTY_BLOCK_ID;
727+
}
711728
};
712729

713730
///@brief Names of various files

vpr/src/route/overuse_report.cpp

Lines changed: 162 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,28 @@
44
#include "globals.h"
55
#include "vtr_log.h"
66

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+
720
static void log_overused_nodes_header();
821
static void log_single_overused_node_status(int overuse_index, RRNodeId inode);
922

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+
*/
1029
void log_overused_nodes_status(int max_logged_overused_rr_nodes) {
1130
const auto& device_ctx = g_vpr_ctx.device();
1231
const auto& route_ctx = g_vpr_ctx.routing();
@@ -31,77 +50,83 @@ void log_overused_nodes_status(int max_logged_overused_rr_nodes) {
3150
}
3251
}
3352

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+
*/
3461
void report_overused_nodes() {
3562
const auto& device_ctx = g_vpr_ctx.device();
3663
const auto& route_ctx = g_vpr_ctx.routing();
37-
const auto& clb_nlist = g_vpr_ctx.clustering().clb_nlist;
3864

39-
//Generate overuse infor lookup table
65+
/* Generate overuse info lookup table */
4066
std::map<RRNodeId, std::set<ClusterNetId>> nodes_to_nets_lookup;
4167
generate_overused_nodes_to_congested_net_lookup(nodes_to_nets_lookup);
4268

43-
//Open the report file
69+
/* Open the report file and print header info */
4470
std::ofstream os("report_overused_nodes.rpt");
4571
os << "Overused nodes information report on the final failed routing attempt" << '\n';
4672
os << "Total number of overused nodes = " << nodes_to_nets_lookup.size() << '\n';
4773

48-
int inode = 0;
49-
74+
/* Go through each rr node and the nets that pass through it */
75+
size_t inode = 0;
5076
for (const auto& lookup_pair : nodes_to_nets_lookup) {
5177
const RRNodeId node_id = lookup_pair.first;
5278
const auto& congested_nets = lookup_pair.second;
5379

54-
os << "************************************************\n\n"; //RR Node Separation line
80+
os << "************************************************\n\n"; //Separation line
5581

56-
//Report Basic info
82+
/* Report basic rr node info */
5783
os << "Overused RR node #" << inode << '\n';
5884
os << "Node id = " << size_t(node_id) << '\n';
5985
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";
6787

68-
//Report Selective info
88+
/* Report selective info based on the rr node type */
6989
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';
7091

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;
78108
}
79109

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);
88114

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';
99115
++inode;
100116
}
101117

102118
os.close();
103119
}
104120

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+
*/
105130
void generate_overused_nodes_to_congested_net_lookup(std::map<RRNodeId, std::set<ClusterNetId>>& nodes_to_nets_lookup) {
106131
const auto& device_ctx = g_vpr_ctx.device();
107132
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
121146
}
122147
}
123148

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
124245
static void log_overused_nodes_header() {
125246
VTR_LOG("Routing Failure Diagnostics: Printing Overused Nodes Information\n");
126247
VTR_LOG("------ ------- ---------- --------- -------- ------------ ------- ------- ------- ------- ------- -------\n");
@@ -129,6 +250,7 @@ static void log_overused_nodes_header() {
129250
VTR_LOG("------ ------- ---------- --------- -------- ------------ ------- ------- ------- ------- ------- -------\n");
130251
}
131252

253+
///@brief Print out a single-line info that corresponds to a single overused rr node in the logfile
132254
static void log_single_overused_node_status(int overuse_index, RRNodeId node_id) {
133255
const auto& device_ctx = g_vpr_ctx.device();
134256
const auto& route_ctx = g_vpr_ctx.routing();

vpr/src/route/overuse_report.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,25 @@
33
#include "rr_graph_storage.h"
44
#include <map>
55

6+
/**
7+
* @brief Global routines related to displaying RR node overuse info.
8+
*
9+
* This file contains all the routines that print out the information on overused RR nodes
10+
* and congested nets. The main purpose of these routines is to aid the debugging process
11+
* should the VPR fail to implement the circuit. Functionalities that resolve these circuit
12+
* issues should NOT be included here or in overuse_report.cpp
13+
*
14+
* An RR node is overused when the number of nets passing through it exceed the node's
15+
* routing net capacity. A successfully routed circuit is void of these overused nodes.
16+
*
17+
* All the nets passing through an overused RR node are flagged as congested nets.
18+
*/
19+
20+
///@brief Print out RR node overuse info in the VPR logfile.
621
void log_overused_nodes_status(int max_logged_overused_rr_nodes);
22+
23+
///@brief Print out RR node overuse info in a post-VPR report file.
724
void report_overused_nodes();
25+
26+
///@brief Generate a overused RR nodes to congested nets lookup table.
827
void generate_overused_nodes_to_congested_net_lookup(std::map<RRNodeId, std::set<ClusterNetId>>& nodes_to_nets_lookup);

0 commit comments

Comments
 (0)