Skip to content

Commit 62ede3a

Browse files
committed
add create rr_graph_obj function which loads rr_nodes to the object
1 parent 68877d9 commit 62ede3a

11 files changed

+407
-20
lines changed

libs/libvtrutil/src/vtr_geometry.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ template<class T>
4848
class Point {
4949
public: //Constructors
5050
Point(T x_val, T y_val) noexcept;
51+
Point();
5152

5253
public: //Accessors
5354
//Coordinates

libs/libvtrutil/src/vtr_geometry.tpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ Point<T>::Point(T x_val, T y_val) noexcept
1010
//pass
1111
}
1212

13+
template<class T>
14+
Point<T>::Point() {
15+
//pass
16+
}
17+
1318
template<class T>
1419
T Point<T>::x() const {
1520
return x_;
@@ -74,6 +79,11 @@ Rect<T>::Rect(Point<T> bottom_left_val, Point<T> top_right_val)
7479
//pass
7580
}
7681

82+
template<class T>
83+
Rect<T>::Rect() {
84+
//pass
85+
}
86+
7787
template<class T>
7888
T Rect<T>::xmin() const {
7989
return bottom_left_.x();

vpr/src/base/vpr_context.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "router_lookahead.h"
2222
#include "place_macro.h"
2323
#include "compressed_grid.h"
24+
#include "rr_graph_obj.h"
2425

2526
//A Context is collection of state relating to a particular part of VPR
2627
//
@@ -136,6 +137,9 @@ struct DeviceContext : public Context {
136137
/* chan_width is for x|y-directed channels; i.e. between rows */
137138
t_chan_width chan_width;
138139

140+
/* Object to define routing resources */
141+
RRGraph rr_graph;
142+
139143
/* Structures to define the routing architecture of the FPGA. */
140144
std::vector<t_rr_node> rr_nodes; /* autogenerated in build_rr_graph */
141145

vpr/src/device/check_rr_graph_obj.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ static bool check_rr_graph_source_nodes(const RRGraph& rr_graph) {
107107
}
108108
}
109109

110-
return invalid_sources;
110+
return !invalid_sources;
111111
}
112112

113113
/***********************************************************************
@@ -136,7 +136,7 @@ static bool check_rr_graph_sink_nodes(const RRGraph& rr_graph) {
136136
}
137137
}
138138

139-
return invalid_sinks;
139+
return !invalid_sinks;
140140
}
141141

142142
/***********************************************************************
@@ -153,48 +153,43 @@ static bool check_rr_graph_sink_nodes(const RRGraph& rr_graph) {
153153
* will work properly.
154154
**********************************************************************/
155155
bool check_rr_graph(const RRGraph& rr_graph) {
156-
bool check_flag = true;
157156
size_t num_err = 0;
158157

159158
if (false == check_rr_graph_duplicated_edges(rr_graph)) {
160159
VTR_LOG_WARN("Fail in checking duplicated edges !\n");
161-
check_flag = false;
162160
num_err++;
163161
}
164162

165163
if (false == check_rr_graph_dangling_nodes(rr_graph)) {
166164
VTR_LOG_WARN("Fail in checking dangling nodes !\n");
167-
check_flag = false;
168165
num_err++;
169166
}
170167

171168
if (false == check_rr_graph_source_nodes(rr_graph)) {
172169
VTR_LOG_WARN("Fail in checking source nodes!\n");
173-
check_flag = false;
174170
num_err++;
175171
}
176172

177173
if (false == check_rr_graph_sink_nodes(rr_graph)) {
178174
VTR_LOG_WARN("Fail in checking sink nodes!\n");
179-
check_flag = false;
180175
num_err++;
181176
}
182177

183178
if (false == check_rr_graph_source_nodes(rr_graph)) {
184179
VTR_LOG_WARN("Fail in checking source nodes!\n");
185-
check_flag = false;
186180
num_err++;
187181
}
188182

189183
if (false == check_rr_graph_sink_nodes(rr_graph)) {
190184
VTR_LOG_WARN("Fail in checking sink nodes!\n");
191-
check_flag = false;
192185
num_err++;
193186
}
194187

195188
/* Error out if there is any fatal errors found */
196-
VTR_LOG_WARN("Checked Routing Resource graph with %d errors !\n",
197-
num_err);
189+
if (0 < num_err) {
190+
VTR_LOG_WARN("Checked Routing Resource graph with %d errors !\n",
191+
num_err);
192+
}
198193

199-
return check_flag;
194+
return (0 == num_err);
200195
}

vpr/src/device/create_rr_graph.cpp

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/* Standard header files required go first */
2+
#include <map>
3+
4+
/* EXTERNAL library header files go second*/
5+
#include "vtr_assert.h"
6+
#include "vtr_time.h"
7+
8+
/* VPR header files go then */
9+
#include "vpr_types.h"
10+
#include "rr_graph_obj.h"
11+
#include "check_rr_graph_obj.h"
12+
#include "create_rr_graph.h"
13+
14+
/* Finally we include global variables */
15+
#include "globals.h"
16+
17+
/********************************************************************
18+
* TODO: remove when this conversion (from traditional to new data structure)
19+
* is no longer needed
20+
* This function will convert an existing rr_graph in device_ctx to the RRGraph
21+
*object
22+
* This function is used to test our RRGraph if it is acceptable in downstream
23+
*routers
24+
********************************************************************/
25+
void convert_rr_graph(std::vector<t_segment_inf>& vpr_segments) {
26+
vtr::ScopedStartFinishTimer timer("Build routing resource graph object");
27+
28+
/* IMPORTANT: to build clock tree,
29+
* vpr added segments to the original arch segments
30+
* This is why to use vpr_segments as an inputs!!!
31+
*/
32+
auto& device_ctx = g_vpr_ctx.mutable_device();
33+
34+
/* make sure we have a clean empty rr_graph */
35+
device_ctx.rr_graph.clear();
36+
37+
/* The number of switches are in general small,
38+
* reserve switches may not bring significant memory efficiency
39+
* So, we just use create_switch to push_back each time
40+
*/
41+
device_ctx.rr_graph.reserve_switches(device_ctx.rr_switch_inf.size());
42+
// Create the switches
43+
for (size_t iswitch = 0; iswitch < device_ctx.rr_switch_inf.size(); ++iswitch) {
44+
device_ctx.rr_graph.create_switch(device_ctx.rr_switch_inf[iswitch]);
45+
}
46+
47+
/* The number of segments are in general small, reserve segments may not bring
48+
* significant memory efficiency */
49+
device_ctx.rr_graph.reserve_segments(vpr_segments.size());
50+
// Create the segments
51+
for (size_t iseg = 0; iseg < vpr_segments.size(); ++iseg) {
52+
device_ctx.rr_graph.create_segment(vpr_segments[iseg]);
53+
}
54+
55+
/* Reserve list of nodes to be memory efficient */
56+
device_ctx.rr_graph.reserve_nodes(device_ctx.rr_nodes.size());
57+
58+
// Create the nodes
59+
std::map<int, RRNodeId> old_to_new_rr_node;
60+
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
61+
auto& node = device_ctx.rr_nodes[inode];
62+
RRNodeId rr_node = device_ctx.rr_graph.create_node(node.type());
63+
64+
device_ctx.rr_graph.set_node_xlow(rr_node, node.xlow());
65+
device_ctx.rr_graph.set_node_ylow(rr_node, node.ylow());
66+
device_ctx.rr_graph.set_node_xhigh(rr_node, node.xhigh());
67+
device_ctx.rr_graph.set_node_yhigh(rr_node, node.yhigh());
68+
69+
device_ctx.rr_graph.set_node_capacity(rr_node, node.capacity());
70+
71+
device_ctx.rr_graph.set_node_ptc_num(rr_node, node.ptc_num());
72+
73+
device_ctx.rr_graph.set_node_cost_index(rr_node, node.cost_index());
74+
75+
if (CHANX == node.type() || CHANY == node.type()) {
76+
device_ctx.rr_graph.set_node_direction(rr_node, node.direction());
77+
}
78+
if (IPIN == node.type() || OPIN == node.type()) {
79+
device_ctx.rr_graph.set_node_side(rr_node, node.side());
80+
}
81+
device_ctx.rr_graph.set_node_R(rr_node, node.R());
82+
device_ctx.rr_graph.set_node_C(rr_node, node.C());
83+
84+
/* Set up segment id */
85+
short irc_data = node.cost_index();
86+
short iseg = device_ctx.rr_indexed_data[irc_data].seg_index;
87+
device_ctx.rr_graph.set_node_segment(rr_node, RRSegmentId(iseg));
88+
89+
VTR_ASSERT(!old_to_new_rr_node.count(inode));
90+
old_to_new_rr_node[inode] = rr_node;
91+
}
92+
93+
/* Reserve list of edges to be memory efficient */
94+
{
95+
int num_edges_to_reserve = 0;
96+
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
97+
const auto& node = device_ctx.rr_nodes[inode];
98+
num_edges_to_reserve += node.num_edges();
99+
}
100+
device_ctx.rr_graph.reserve_edges(num_edges_to_reserve);
101+
}
102+
103+
// Create the edges
104+
std::map<std::pair<int, int>, RREdgeId> old_to_new_rr_edge; // Key:
105+
// {inode,iedge}
106+
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
107+
const auto& node = device_ctx.rr_nodes[inode];
108+
for (int iedge = 0; iedge < node.num_edges(); ++iedge) {
109+
int isink_node = node.edge_sink_node(iedge);
110+
int iswitch = node.edge_switch(iedge);
111+
112+
VTR_ASSERT(old_to_new_rr_node.count(inode));
113+
VTR_ASSERT(old_to_new_rr_node.count(isink_node));
114+
115+
RREdgeId rr_edge = device_ctx.rr_graph.create_edge(old_to_new_rr_node[inode],
116+
old_to_new_rr_node[isink_node],
117+
RRSwitchId(iswitch));
118+
119+
auto key = std::make_pair(inode, iedge);
120+
VTR_ASSERT(!old_to_new_rr_edge.count(key));
121+
old_to_new_rr_edge[key] = rr_edge;
122+
}
123+
}
124+
125+
/* Partition edges to be two class: configurable (1st part) and
126+
* non-configurable (2nd part)
127+
* See how the router will use the edges and determine the strategy
128+
* if we want to partition the edges first or depends on the routing needs
129+
*/
130+
device_ctx.rr_graph.partition_edges();
131+
132+
/* Essential check for rr_graph, build look-up and */
133+
if (false == device_ctx.rr_graph.validate()) {
134+
/* Error out if built-in validator of rr_graph fails */
135+
vpr_throw(VPR_ERROR_ROUTE,
136+
__FILE__,
137+
__LINE__,
138+
"Fundamental errors occurred when validating rr_graph object!\n");
139+
}
140+
141+
/* Error out if advanced checker of rr_graph fails */
142+
if (false == check_rr_graph(device_ctx.rr_graph)) {
143+
vpr_throw(VPR_ERROR_ROUTE,
144+
__FILE__,
145+
__LINE__,
146+
"Advanced checking rr_graph object fails! Routing may still work "
147+
"but not smooth\n");
148+
}
149+
}

vpr/src/device/create_rr_graph.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef CREATE_RR_GRAPH_H
2+
#define CREATE_RR_GRAPH_H
3+
4+
/*
5+
* Notes in include header files in a head file
6+
* Only include the neccessary header files
7+
* that is required by the data types in the function/class declarations!
8+
*/
9+
#include "rr_graph_obj.h"
10+
11+
/* IMPORTANT: to build clock tree,
12+
* vpr added segments to the original arch segments
13+
* This is why to use vpr_segments as an inputs!!!
14+
*/
15+
void convert_rr_graph(std::vector<t_segment_inf>& vpr_segments);
16+
17+
#endif

vpr/src/device/rr_graph_obj.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,6 @@ bool RRGraph::validate_edge_sink_nodes() const {
714714
* Warnings are thrown if optional checking fails
715715
*/
716716
bool RRGraph::validate() const {
717-
bool check_flag = true;
718717
size_t num_err = 0;
719718

720719
initialize_fast_node_lookup();
@@ -724,34 +723,32 @@ bool RRGraph::validate() const {
724723
*/
725724
if (false == validate_sizes()) {
726725
VTR_LOG_WARN("Fail in validating node- and edge-related vector sizes!\n");
727-
check_flag = false;
728726
num_err++;
729727
}
730728

731729
/* Fundamental check */
732730
if (false == validate_nodes_edges()) {
733731
VTR_LOG_WARN("Fail in validating edges connected to each node!\n");
734-
check_flag = false;
735732
num_err++;
736733
}
737734

738735
if (false == validate_node_segments()) {
739736
VTR_LOG_WARN("Fail in validating segment IDs of nodes !\n");
740-
check_flag = false;
741737
num_err++;
742738
}
743739

744740
if (false == validate_edge_switches()) {
745741
VTR_LOG_WARN("Fail in validating switch IDs of edges !\n");
746-
check_flag = false;
747742
num_err++;
748743
}
749744

750745
/* Error out if there is any fatal errors found */
751-
VTR_LOG_ERROR("Routing Resource graph is not valid due to %d fatal errors !\n",
752-
num_err);
746+
if (0 < num_err) {
747+
VTR_LOG_ERROR("Routing Resource graph is not valid due to %d fatal errors !\n",
748+
num_err);
749+
}
753750

754-
return check_flag;
751+
return (0 == num_err);
755752
}
756753

757754
bool RRGraph::is_dirty() const {
@@ -827,6 +824,7 @@ RRNodeId RRGraph::create_node(const t_rr_type& type) {
827824
node_sides_.push_back(NUM_SIDES);
828825
node_Rs_.push_back(0.);
829826
node_Cs_.push_back(0.);
827+
node_segments_.push_back(RRSegmentId::INVALID());
830828

831829
node_in_edges_.emplace_back(); //Initially empty
832830
node_out_edges_.emplace_back(); //Initially empty

vpr/src/route/rr_graph.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "rr_graph_reader.h"
3434
#include "router_lookahead_map.h"
3535
#include "rr_graph_clock.h"
36+
#include "create_rr_graph.h"
3637

3738
#include "rr_types.h"
3839

@@ -375,6 +376,9 @@ void create_rr_graph(const t_graph_type graph_type,
375376

376377
print_rr_graph_stats();
377378

379+
/* Create rr_graph object: load rr_nodes to the object */
380+
convert_rr_graph(segment_inf);
381+
378382
//Write out rr graph file if needed
379383
if (!det_routing_arch->write_rr_graph_filename.empty()) {
380384
write_rr_graph(det_routing_arch->write_rr_graph_filename.c_str(), segment_inf);

vpr/src/util/rr_graph_obj_util.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/****************************************************************************
2+
* This file include most-utilized functions that manipulate on the
3+
* RRGraph object
4+
***************************************************************************/
5+
#include <tuple>
6+
#include "rr_graph_obj_util.h"
7+
8+
/****************************************************************************
9+
* Find the switches interconnecting two nodes
10+
* Return a vector of switch ids
11+
***************************************************************************/
12+
std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
13+
const RRNodeId& from_node,
14+
const RRNodeId& to_node) {
15+
std::vector<RRSwitchId> switches;
16+
std::vector<RREdgeId> edges = rr_graph.find_edges(from_node, to_node);
17+
if (true == edges.empty()) {
18+
/* edge is open, we return an empty vector of switches */
19+
return switches;
20+
}
21+
22+
/* Reach here, edge list is not empty, find switch id one by one
23+
* and update the switch list
24+
*/
25+
for (auto edge : edges) {
26+
switches.push_back(rr_graph.edge_switch(edge));
27+
}
28+
29+
return switches;
30+
}

0 commit comments

Comments
 (0)