Skip to content

Commit c18b2f2

Browse files
authored
Merge pull request #1747 from verilog-to-routing/rr_graph_builder
Deploy RRGraphBuilder in place of rr_node_indices in routing resource graph builder functions
2 parents d10c8e2 + 5878473 commit c18b2f2

File tree

7 files changed

+138
-93
lines changed

7 files changed

+138
-93
lines changed

vpr/src/device/rr_spatial_lookup.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,33 @@ void RRSpatialLookup::add_node(RRNodeId node,
8080
t_rr_type type,
8181
int ptc,
8282
e_side side) {
83+
VTR_ASSERT(node); /* Must have a valid node id to be added */
8384
VTR_ASSERT_SAFE(3 == rr_node_indices_[type].ndims());
8485

86+
resize_nodes(x, y, type, side);
87+
88+
if (size_t(ptc) >= rr_node_indices_[type][x][y][side].size()) {
89+
/* Deposit invalid ids to newly allocated elements while original elements are untouched */
90+
rr_node_indices_[type][x][y][side].resize(ptc + 1, int(size_t(RRNodeId::INVALID())));
91+
}
92+
93+
/* Resize on demand finished; Register the node */
94+
rr_node_indices_[type][x][y][side][ptc] = int(size_t(node));
95+
}
96+
97+
void RRSpatialLookup::mirror_nodes(const vtr::Point<int>& src_coord,
98+
const vtr::Point<int>& des_coord,
99+
t_rr_type type,
100+
e_side side) {
101+
VTR_ASSERT(SOURCE == type || SINK == type);
102+
resize_nodes(des_coord.x(), des_coord.y(), type, side);
103+
rr_node_indices_[type][des_coord.x()][des_coord.y()][side] = rr_node_indices_[type][src_coord.x()][src_coord.y()][side];
104+
}
105+
106+
void RRSpatialLookup::resize_nodes(int x,
107+
int y,
108+
t_rr_type type,
109+
e_side side) {
85110
/* Expand the fast look-up if the new node is out-of-range
86111
* This may seldom happen because the rr_graph building function
87112
* should ensure the fast look-up well organized
@@ -97,11 +122,4 @@ void RRSpatialLookup::add_node(RRNodeId node,
97122
std::max(rr_node_indices_[type].dim_size(1), size_t(y) + 1),
98123
std::max(rr_node_indices_[type].dim_size(2), size_t(side) + 1)});
99124
}
100-
101-
if (size_t(ptc) >= rr_node_indices_[type][x][y][side].size()) {
102-
rr_node_indices_[type][x][y][side].resize(ptc + 1);
103-
}
104-
105-
/* Resize on demand finished; Register the node */
106-
rr_node_indices_[type][x][y][side][ptc] = int(size_t(node));
107125
}

vpr/src/device/rr_spatial_lookup.h

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef RR_SPATIAL_LOOKUP_H
22
#define RR_SPATIAL_LOOKUP_H
33

4+
#include "vtr_geometry.h"
45
#include "vpr_types.h"
56

67
/********************************************************************
@@ -29,7 +30,8 @@ class RRSpatialLookup {
2930

3031
/* -- Accessors -- */
3132
public:
32-
/* Returns the index of the specified routing resource node.
33+
/**
34+
* Returns the index of the specified routing resource node.
3335
* - (x, y) are the grid location within the FPGA
3436
* - rr_type specifies the type of resource,
3537
* - ptc gives a unique number of resources of that type (e.g. CHANX) at that (x,y).
@@ -63,7 +65,8 @@ class RRSpatialLookup {
6365

6466
/* -- Mutators -- */
6567
public:
66-
/* Register a node in the fast look-up
68+
/**
69+
* Register a node in the fast look-up
6770
* - You must have a valid node id to register the node in the lookup
6871
* - (x, y) are the coordinate of the node to be indexable in the fast look-up
6972
* - type is the type of a node
@@ -89,7 +92,53 @@ class RRSpatialLookup {
8992
int ptc,
9093
e_side side);
9194

92-
/* TODO: Add an API remove_node() to unregister a node from the look-up */
95+
/**
96+
* Mirror the last dimension of a look-up, i.e., a list of nodes, from a source coordinate to
97+
* a destination coordinate.
98+
* This function is mostly need by SOURCE and SINK nodes which are indexable in multiple locations.
99+
* Considering a bounding box (x, y)->(x + width, y + height) of a multi-height and multi-width grid,
100+
* SOURCE and SINK nodes are indexable in any location inside the boundry.
101+
*
102+
* An example of usage:
103+
*
104+
* // Create a empty lookup
105+
* RRSpatialLookup rr_lookup;
106+
* // Adding other nodes ...
107+
* // Copy the nodes whose types are SOURCE at (1, 1) to (1, 2)
108+
* rr_lookup.mirror_nodes(vtr::Point<int>(1, 1),
109+
* vtr::Point<int>(1, 2),
110+
* SOURCE,
111+
* TOP);
112+
*
113+
* Note: currently this function only accepts SOURCE/SINK nodes. May unlock for the other types
114+
* depending on needs
115+
*
116+
* TODO: Consider to make a high-level API to duplicate the nodes for large blocks.
117+
* Then this API can become a private one
118+
* For example,
119+
* expand_nodes(source_coordinate, bounding_box_coordinate, type, side);
120+
* Alternatively, we can rework the ``find_node()`` API so that we always search the lowest (x,y)
121+
* corner when dealing with large blocks. But this may require the data structure to be dependent
122+
* on DeviceGrid information (it needs to identify if a grid has height > 1 as well as width > 1)
123+
*/
124+
void mirror_nodes(const vtr::Point<int>& src_coord,
125+
const vtr::Point<int>& des_coord,
126+
t_rr_type type,
127+
e_side side);
128+
129+
/**
130+
* Resize the given 3 dimensions (x, y, side) of the RRSpatialLookup data structure for the given type
131+
* This function will keep any existing data
132+
*
133+
* Strongly recommend to use when the sizes of dimensions are deterministic
134+
*
135+
* TODO: should have a reserve function but vtd::ndmatrix does not have such API
136+
* as a result, resize can be an internal one while reserve function is a public mutator
137+
*/
138+
void resize_nodes(int x,
139+
int y,
140+
t_rr_type type,
141+
e_side side);
93142

94143
/* -- Internal data storage -- */
95144
private:

vpr/src/route/rr_edge.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef RR_EDGE_H
2+
#define RR_EDGE_H
3+
4+
struct t_rr_edge_info {
5+
t_rr_edge_info(int from, int to, short type) noexcept
6+
: from_node(from)
7+
, to_node(to)
8+
, switch_type(type) {}
9+
10+
int from_node = OPEN;
11+
int to_node = OPEN;
12+
short switch_type = OPEN;
13+
14+
friend bool operator<(const t_rr_edge_info& lhs, const t_rr_edge_info& rhs) {
15+
return std::tie(lhs.from_node, lhs.to_node, lhs.switch_type) < std::tie(rhs.from_node, rhs.to_node, rhs.switch_type);
16+
}
17+
18+
friend bool operator==(const t_rr_edge_info& lhs, const t_rr_edge_info& rhs) {
19+
return std::tie(lhs.from_node, lhs.to_node, lhs.switch_type) == std::tie(rhs.from_node, rhs.to_node, rhs.switch_type);
20+
}
21+
};
22+
23+
typedef std::vector<t_rr_edge_info> t_rr_edge_info_set;
24+
25+
#endif /* RR_EDGE */

vpr/src/route/rr_graph.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ static void build_rr_graph(const t_graph_type graph_type,
573573
/* Alloc node lookups, count nodes, alloc rr nodes */
574574
int num_rr_nodes = 0;
575575

576-
alloc_and_load_rr_node_indices(device_ctx.rr_node_indices,
576+
alloc_and_load_rr_node_indices(device_ctx.rr_graph_builder,
577577
max_chan_width, grid,
578578
&num_rr_nodes, chan_details_x, chan_details_y);
579579

vpr/src/route/rr_graph2.cpp

Lines changed: 32 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,10 @@ static void load_chan_rr_indices(const int max_chan_width,
3232
const int num_chans,
3333
const t_rr_type type,
3434
const t_chan_details& chan_details,
35-
t_rr_node_indices& indices,
35+
RRGraphBuilder& rr_graph_builder,
3636
int* index);
3737

3838
static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder,
39-
t_rr_node_indices& indices,
4039
const DeviceGrid& grid,
4140
int* index);
4241

@@ -928,44 +927,41 @@ static void load_chan_rr_indices(const int max_chan_width,
928927
const int num_chans,
929928
const t_rr_type type,
930929
const t_chan_details& chan_details,
931-
t_rr_node_indices& indices,
930+
RRGraphBuilder& rr_graph_builder,
932931
int* index) {
933-
VTR_ASSERT(indices[type].dim_size(0) == size_t(num_chans));
934-
VTR_ASSERT(indices[type].dim_size(1) == size_t(chan_len));
935-
VTR_ASSERT(indices[type].dim_size(2) == NUM_SIDES);
936-
for (int chan = 0; chan < num_chans - 1; ++chan) {
937-
for (int seg = 1; seg < chan_len - 1; ++seg) {
938-
/* Alloc the track inode lookup list */
939-
//Since channels have no side, we just use the first side
940-
indices[type][chan][seg][0].resize(max_chan_width, OPEN);
941-
}
942-
}
943-
944932
for (int chan = 0; chan < num_chans - 1; ++chan) {
945933
for (int seg = 1; seg < chan_len - 1; ++seg) {
946934
/* Assign an inode to the starts of tracks */
947935
int x = (type == CHANX ? seg : chan);
948936
int y = (type == CHANX ? chan : seg);
949937
const t_chan_seg_details* seg_details = chan_details[x][y].data();
950938

951-
for (unsigned track = 0; track < indices[type][chan][seg][0].size(); ++track) {
939+
for (int track = 0; track < max_chan_width; ++track) {
940+
/* TODO: May let the length() == 0 case go through, to model muxes */
952941
if (seg_details[track].length() <= 0)
953942
continue;
954943

955944
int start = get_seg_start(seg_details, track, chan, seg);
956945

946+
/* TODO: Now we still use the (y, x) convention here for CHANX. Should rework later */
947+
int node_x = chan;
948+
int node_y = start;
949+
if (CHANX == type) {
950+
std::swap(node_x, node_y);
951+
}
952+
957953
/* If the start of the wire doesn't have a inode,
958954
* assign one to it. */
959-
int inode = indices[type][chan][start][0][track];
960-
if (OPEN == inode) {
961-
inode = *index;
955+
RRNodeId inode = rr_graph_builder.node_lookup().find_node(node_x, node_y, type, track, SIDES[0]);
956+
if (!inode) {
957+
inode = RRNodeId(*index);
962958
++(*index);
963959

964-
indices[type][chan][start][0][track] = inode;
960+
rr_graph_builder.node_lookup().add_node(inode, chan, start, type, track, SIDES[0]);
965961
}
966962

967963
/* Assign inode of start of wire to current position */
968-
indices[type][chan][seg][0][track] = inode;
964+
rr_graph_builder.node_lookup().add_node(inode, chan, seg, type, track, SIDES[0]);
969965
}
970966
}
971967
}
@@ -975,7 +971,6 @@ static void load_chan_rr_indices(const int max_chan_width,
975971
* TODO: these building functions should only talk to a RRGraphBuilder object
976972
*/
977973
static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder,
978-
t_rr_node_indices& indices,
979974
const DeviceGrid& grid,
980975
int* index) {
981976
//Walk through the grid assigning indices to SOURCE/SINK IPIN/OPIN
@@ -991,16 +986,12 @@ static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder,
991986
auto class_type = type->class_inf[iclass].type;
992987
if (class_type == DRIVER) {
993988
rr_graph_builder.node_lookup().add_node(RRNodeId(*index), x, y, SOURCE, iclass, SIDES[0]);
994-
rr_graph_builder.node_lookup().add_node(RRNodeId::INVALID(), x, y, SINK, iclass, SIDES[0]);
995989
} else {
996990
VTR_ASSERT(class_type == RECEIVER);
997991
rr_graph_builder.node_lookup().add_node(RRNodeId(*index), x, y, SINK, iclass, SIDES[0]);
998-
rr_graph_builder.node_lookup().add_node(RRNodeId::INVALID(), x, y, SOURCE, iclass, SIDES[0]);
999992
}
1000993
++(*index);
1001994
}
1002-
VTR_ASSERT(indices[SOURCE][x][y][0].size() == type->class_inf.size());
1003-
VTR_ASSERT(indices[SINK][x][y][0].size() == type->class_inf.size());
1004995

1005996
/* Limited sides for grids
1006997
* The wanted side depends on the location of the grid.
@@ -1068,18 +1059,13 @@ static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder,
10681059
auto class_type = type->class_inf[iclass].type;
10691060

10701061
if (class_type == DRIVER) {
1071-
indices[OPIN][x_tile][y_tile][side].push_back(*index);
1072-
indices[IPIN][x_tile][y_tile][side].push_back(OPEN);
1062+
rr_graph_builder.node_lookup().add_node(RRNodeId(*index), x_tile, y_tile, OPIN, ipin, side);
10731063
assigned_to_rr_node = true;
10741064
} else {
10751065
VTR_ASSERT(class_type == RECEIVER);
1076-
indices[OPIN][x_tile][y_tile][side].push_back(OPEN);
1077-
indices[IPIN][x_tile][y_tile][side].push_back(*index);
1066+
rr_graph_builder.node_lookup().add_node(RRNodeId(*index), x_tile, y_tile, IPIN, ipin, side);
10781067
assigned_to_rr_node = true;
10791068
}
1080-
} else {
1081-
indices[IPIN][x_tile][y_tile][side].push_back(OPEN);
1082-
indices[OPIN][x_tile][y_tile][side].push_back(OPEN);
10831069
}
10841070
}
10851071
}
@@ -1099,25 +1085,6 @@ static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder,
10991085
++(*index);
11001086
}
11011087
}
1102-
1103-
//Sanity check
1104-
for (int width_offset = 0; width_offset < type->width; ++width_offset) {
1105-
int x_tile = x + width_offset;
1106-
for (int height_offset = 0; height_offset < type->height; ++height_offset) {
1107-
int y_tile = y + height_offset;
1108-
for (e_side side : SIDES) {
1109-
//Note that the fast look-up stores all the indices for the pins on each side
1110-
//It has a fixed size (either 0 or the number of pins)
1111-
//Case 0 pins: the side is skipped as no pins are located on it
1112-
//Case number of pins: there are pins on this side
1113-
//and data query can be applied any pin id on this side
1114-
VTR_ASSERT((indices[IPIN][x_tile][y_tile][side].size() == size_t(type->num_pins))
1115-
|| (0 == indices[IPIN][x_tile][y_tile][side].size()));
1116-
VTR_ASSERT((indices[OPIN][x_tile][y_tile][side].size() == size_t(type->num_pins))
1117-
|| (0 == indices[OPIN][x_tile][y_tile][side].size()));
1118-
}
1119-
}
1120-
}
11211088
}
11221089
}
11231090
}
@@ -1132,8 +1099,14 @@ static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder,
11321099
int root_x = x - width_offset;
11331100
int root_y = y - height_offset;
11341101

1135-
indices[SOURCE][x][y][0] = indices[SOURCE][root_x][root_y][0];
1136-
indices[SINK][x][y][0] = indices[SINK][root_x][root_y][0];
1102+
rr_graph_builder.node_lookup().mirror_nodes(vtr::Point<int>(root_x, root_y),
1103+
vtr::Point<int>(x, y),
1104+
SOURCE,
1105+
SIDES[0]);
1106+
rr_graph_builder.node_lookup().mirror_nodes(vtr::Point<int>(root_x, root_y),
1107+
vtr::Point<int>(x, y),
1108+
SINK,
1109+
SIDES[0]);
11371110
}
11381111
}
11391112
}
@@ -1149,7 +1122,7 @@ static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder,
11491122
* This will block us when putting the RRGraphBuilder object as an input arguement
11501123
* of this function
11511124
*/
1152-
void alloc_and_load_rr_node_indices(t_rr_node_indices& indices,
1125+
void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder,
11531126
const int max_chan_width,
11541127
const DeviceGrid& grid,
11551128
int* index,
@@ -1162,20 +1135,20 @@ void alloc_and_load_rr_node_indices(t_rr_node_indices& indices,
11621135
/* Alloc the lookup table */
11631136
for (t_rr_type rr_type : RR_TYPES) {
11641137
if (rr_type == CHANX) {
1165-
indices[rr_type].resize({grid.height(), grid.width(), NUM_SIDES});
1138+
rr_graph_builder.node_lookup().resize_nodes(grid.height(), grid.width(), rr_type, NUM_SIDES);
11661139
} else {
1167-
indices[rr_type].resize({grid.width(), grid.height(), NUM_SIDES});
1140+
rr_graph_builder.node_lookup().resize_nodes(grid.width(), grid.height(), rr_type, NUM_SIDES);
11681141
}
11691142
}
11701143

11711144
/* Assign indices for block nodes */
1172-
load_block_rr_indices(g_vpr_ctx.mutable_device().rr_graph_builder, indices, grid, index);
1145+
load_block_rr_indices(rr_graph_builder, grid, index);
11731146

11741147
/* Load the data for x and y channels */
11751148
load_chan_rr_indices(max_chan_width, grid.width(), grid.height(),
1176-
CHANX, chan_details_x, indices, index);
1149+
CHANX, chan_details_x, rr_graph_builder, index);
11771150
load_chan_rr_indices(max_chan_width, grid.height(), grid.width(),
1178-
CHANY, chan_details_y, indices, index);
1151+
CHANY, chan_details_y, rr_graph_builder, index);
11791152
}
11801153

11811154
bool verify_rr_node_indices(const DeviceGrid& grid, const t_rr_node_indices& rr_node_indices, const t_rr_graph_storage& rr_nodes) {

0 commit comments

Comments
 (0)