refactored RRGraph builder
This commit is contained in:
parent
4fb6d7e3ae
commit
fc6389b5c0
|
@ -65,10 +65,22 @@ short RRGraph::node_ylow(const RRNodeId& node) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
short RRGraph::node_xhigh(const RRNodeId& node) const {
|
short RRGraph::node_xhigh(const RRNodeId& node) const {
|
||||||
|
/* Special for SOURCE and SINK node, we always return the xlow
|
||||||
|
* This is due to the convention in creating RRGraph
|
||||||
|
* so that we can guarantee unique SOURCE/SINK nodes searching
|
||||||
|
*/
|
||||||
|
if ( (SOURCE == node_type(node)
|
||||||
|
|| (SINK == node_type(node)) {
|
||||||
|
return node_bounding_box(node).xmin();
|
||||||
|
}
|
||||||
return node_bounding_box(node).xmax();
|
return node_bounding_box(node).xmax();
|
||||||
}
|
}
|
||||||
|
|
||||||
short RRGraph::node_yhigh(const RRNodeId& node) const {
|
short RRGraph::node_yhigh(const RRNodeId& node) const {
|
||||||
|
if ( (SOURCE == node_type(node)
|
||||||
|
|| (SINK == node_type(node)) {
|
||||||
|
return node_bounding_box(node).ymin();
|
||||||
|
}
|
||||||
return node_bounding_box(node).ymax();
|
return node_bounding_box(node).ymax();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1200,8 +1212,28 @@ void RRGraph::build_fast_node_lookup() const {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
RRNodeId node = RRNodeId(id);
|
RRNodeId node = RRNodeId(id);
|
||||||
size_t x = node_xlow(node);
|
/* Special for SOURCE and SINK, we should annotate in the look-up
|
||||||
size_t y = node_ylow(node);
|
* for all the (x,y) upto (xhigh, yhigh)
|
||||||
|
*/
|
||||||
|
std::vector<size_t> xlows;
|
||||||
|
std::vector<size_t> ylows;
|
||||||
|
|
||||||
|
if ( (SOURCE == node_type(node)
|
||||||
|
|| (SINK == node_type(node)) {
|
||||||
|
xlows.resize(node_bounding_boxes_[node].xmax() - node_bounding_boxes_[node].xmin() + 1);
|
||||||
|
ylows.resize(node_bounding_boxes_[node].ymax() - node_bounding_boxes_[node].ymin() + 1);
|
||||||
|
std::iota(xlows.begin(), xlows.end(), node_xlow(node));
|
||||||
|
std::iota(ylows.begin(), ylows.end(), node_ylow(node));
|
||||||
|
/* Sanity check */
|
||||||
|
VTR_ASSERT(node_bounding_boxes_[node].xmax() == xlows.back());
|
||||||
|
VTR_ASSERT(node_bounding_boxes_[node].ymax() == ylows.back());
|
||||||
|
} else {
|
||||||
|
xlows.push_back(node_xlow(node));
|
||||||
|
ylows.push_back(node_ylow(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t x : xlows) {
|
||||||
|
for (size_t y : ylows) {
|
||||||
size_t itype = node_type(node);
|
size_t itype = node_type(node);
|
||||||
|
|
||||||
size_t ptc = node_ptc_num(node);
|
size_t ptc = node_ptc_num(node);
|
||||||
|
@ -1224,6 +1256,8 @@ void RRGraph::build_fast_node_lookup() const {
|
||||||
node_lookup_[x][y][itype][ptc][iside] = node;
|
node_lookup_[x][y][itype][ptc][iside] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RRGraph::invalidate_fast_node_lookup() const {
|
void RRGraph::invalidate_fast_node_lookup() const {
|
||||||
node_lookup_.clear();
|
node_lookup_.clear();
|
||||||
|
|
|
@ -591,13 +591,11 @@ static void build_rr_graph(const t_graph_type graph_type,
|
||||||
/* Alloc node lookups, count nodes, alloc rr nodes */
|
/* Alloc node lookups, count nodes, alloc rr nodes */
|
||||||
int num_rr_nodes = 0;
|
int num_rr_nodes = 0;
|
||||||
|
|
||||||
/* Xifan Tang - Keep the node indices here since it counts the number of rr_nodes
|
/* Xifan Tang -
|
||||||
* We will simplify this function as indices will be built inside the RRGraph object
|
* We create all the nodes in the RRGraph object here
|
||||||
*/
|
*/
|
||||||
device_ctx.rr_node_indices = alloc_and_load_rr_node_indices(max_chan_width, grid,
|
device_ctx.rr_graph = alloc_and_load_rr_node_indices(max_chan_width, grid,
|
||||||
&num_rr_nodes, chan_details_x, chan_details_y);
|
&num_rr_nodes, chan_details_x, chan_details_y);
|
||||||
/* Reserve the node for the RRGraph object */
|
|
||||||
device_ctx.rr_graph.reserve_node(num_rr_nodes);
|
|
||||||
|
|
||||||
/* These are data structures used by the the unidir opin mapping. They are used
|
/* These are data structures used by the the unidir opin mapping. They are used
|
||||||
* to spread connections evenly for each segment type among the available
|
* to spread connections evenly for each segment type among the available
|
||||||
|
|
|
@ -31,11 +31,11 @@ static void load_chan_rr_indices(const int max_chan_width,
|
||||||
const int num_chans,
|
const int num_chans,
|
||||||
const t_rr_type type,
|
const t_rr_type type,
|
||||||
const t_chan_details& chan_details,
|
const t_chan_details& chan_details,
|
||||||
t_rr_node_indices& indices,
|
RRGraph& rr_graph,
|
||||||
int* index);
|
int* index);
|
||||||
|
|
||||||
static void load_block_rr_indices(const DeviceGrid& grid,
|
static void load_block_rr_indices(const DeviceGrid& grid,
|
||||||
t_rr_node_indices& indices,
|
RRGraph& rr_graph,
|
||||||
int* index);
|
int* index);
|
||||||
|
|
||||||
static int get_bidir_track_to_chan_seg(const std::vector<int> conn_tracks,
|
static int get_bidir_track_to_chan_seg(const std::vector<int> conn_tracks,
|
||||||
|
@ -1024,25 +1024,43 @@ void dump_sblock_pattern(const t_sblock_pattern& sblock_pattern,
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Create all the nodes for routing tracks
|
||||||
|
* num_chans : number of routing channels to be created
|
||||||
|
* chan_len : maximum length of routing channels
|
||||||
|
*
|
||||||
|
* X-direction channel
|
||||||
|
* |<-------chan_len-------->|
|
||||||
|
* -----+--------------------------
|
||||||
|
* ^ |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* num_chans | FPGA
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* v |
|
||||||
|
* -----+--------------------------
|
||||||
|
*
|
||||||
|
* Y-direction channel
|
||||||
|
* |<-------num_chans-------->|
|
||||||
|
* -----+--------------------------
|
||||||
|
* ^ |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* chan_len | FPGA
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* v |
|
||||||
|
* -----+--------------------------
|
||||||
|
*
|
||||||
|
*******************************************************************/
|
||||||
static void load_chan_rr_indices(const int max_chan_width,
|
static void load_chan_rr_indices(const int max_chan_width,
|
||||||
const int chan_len,
|
const int chan_len,
|
||||||
const int num_chans,
|
const int num_chans,
|
||||||
const t_rr_type type,
|
const t_rr_type type,
|
||||||
const t_chan_details& chan_details,
|
const t_chan_details& chan_details,
|
||||||
t_rr_node_indices& indices,
|
RRGraph& rr_graph,
|
||||||
int* index) {
|
int* index) {
|
||||||
VTR_ASSERT(indices[type].size() == size_t(num_chans));
|
|
||||||
for (int chan = 0; chan < num_chans - 1; ++chan) {
|
|
||||||
VTR_ASSERT(indices[type][chan].size() == size_t(chan_len));
|
|
||||||
|
|
||||||
for (int seg = 1; seg < chan_len - 1; ++seg) {
|
|
||||||
VTR_ASSERT(indices[type][chan][seg].size() == NUM_SIDES);
|
|
||||||
|
|
||||||
/* Alloc the track inode lookup list */
|
|
||||||
//Since channels have no side, we just use the first side
|
|
||||||
indices[type][chan][seg][0].resize(max_chan_width, OPEN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int chan = 0; chan < num_chans - 1; ++chan) {
|
for (int chan = 0; chan < num_chans - 1; ++chan) {
|
||||||
for (int seg = 1; seg < chan_len - 1; ++seg) {
|
for (int seg = 1; seg < chan_len - 1; ++seg) {
|
||||||
|
@ -1051,31 +1069,31 @@ static void load_chan_rr_indices(const int max_chan_width,
|
||||||
int y = (type == CHANX ? chan : seg);
|
int y = (type == CHANX ? chan : seg);
|
||||||
const t_chan_seg_details* seg_details = chan_details[x][y].data();
|
const t_chan_seg_details* seg_details = chan_details[x][y].data();
|
||||||
|
|
||||||
for (unsigned track = 0; track < indices[type][chan][seg][0].size(); ++track) {
|
for (unsigned track = 0; track < num_chans - 1; ++track) {
|
||||||
if (seg_details[track].length() <= 0)
|
if (seg_details[track].length() <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int start = get_seg_start(seg_details, track, chan, seg);
|
int start = get_seg_start(seg_details, track, chan, seg);
|
||||||
|
|
||||||
/* If the start of the wire doesn't have a inode,
|
/* If this segment does not start from the current position, we do not allocate any nodes */
|
||||||
* assign one to it. */
|
if (start != seg) {
|
||||||
int inode = indices[type][chan][start][0][track];
|
continue;
|
||||||
if (OPEN == inode) {
|
|
||||||
inode = *index;
|
|
||||||
++(*index);
|
|
||||||
|
|
||||||
indices[type][chan][start][0][track] = inode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assign inode of start of wire to current position */
|
RRNodeId node = rr_graph.create_node(type);
|
||||||
indices[type][chan][seg][0][track] = inode;
|
short xlow = x;
|
||||||
|
short ylow = y;
|
||||||
|
short xhigh = (type == CHANX ? xlow + seg_details[track].length() - 1 : xlow);
|
||||||
|
short yhigh = (type == CHANY ? ylow + seg_details[track].length() - 1 : ylow);
|
||||||
|
rr_graph.set_node_bounding_box(node, vtr::Rect<short>(xlow, ylow, xhigh, yhigh));
|
||||||
|
rr_graph.set_node_track_num(node, track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_block_rr_indices(const DeviceGrid& grid,
|
static void load_block_rr_indices(const DeviceGrid& grid,
|
||||||
t_rr_node_indices& indices,
|
RRGraph& rr_graph,
|
||||||
int* index) {
|
int* index) {
|
||||||
//Walk through the grid assigning indices to SOURCE/SINK IPIN/OPIN
|
//Walk through the grid assigning indices to SOURCE/SINK IPIN/OPIN
|
||||||
for (size_t x = 0; x < grid.width(); x++) {
|
for (size_t x = 0; x < grid.width(); x++) {
|
||||||
|
@ -1089,17 +1107,17 @@ static void load_block_rr_indices(const DeviceGrid& grid,
|
||||||
for (int iclass = 0; iclass < type->num_class; ++iclass) {
|
for (int iclass = 0; iclass < type->num_class; ++iclass) {
|
||||||
auto class_type = type->class_inf[iclass].type;
|
auto class_type = type->class_inf[iclass].type;
|
||||||
if (class_type == DRIVER) {
|
if (class_type == DRIVER) {
|
||||||
indices[SOURCE][x][y][0].push_back(*index);
|
RRNodeId node = rr_graph.create_node(SOURCE);
|
||||||
indices[SINK][x][y][0].push_back(OPEN);
|
rr_graph.set_node_bounding_box(node, vtr::Rect<size_t>(x, y, x, y));
|
||||||
|
rr_graph.set_node_class_num(iclass);
|
||||||
} else {
|
} else {
|
||||||
VTR_ASSERT(class_type == RECEIVER);
|
VTR_ASSERT(class_type == RECEIVER);
|
||||||
indices[SINK][x][y][0].push_back(*index);
|
RRNodeId node = rr_graph.create_node(SINK);
|
||||||
indices[SOURCE][x][y][0].push_back(OPEN);
|
rr_graph.set_node_bounding_box(node, vtr::Rect<size_t>(x, y, x, y));
|
||||||
|
rr_graph.set_node_class_num(iclass);
|
||||||
}
|
}
|
||||||
++(*index);
|
++(*index);
|
||||||
}
|
}
|
||||||
VTR_ASSERT(indices[SOURCE][x][y][0].size() == size_t(type->num_class));
|
|
||||||
VTR_ASSERT(indices[SINK][x][y][0].size() == size_t(type->num_class));
|
|
||||||
|
|
||||||
//Assign indicies for IPINs and OPINs at all offsets from root
|
//Assign indicies for IPINs and OPINs at all offsets from root
|
||||||
for (int ipin = 0; ipin < type->num_pins; ++ipin) {
|
for (int ipin = 0; ipin < type->num_pins; ++ipin) {
|
||||||
|
@ -1113,34 +1131,23 @@ static void load_block_rr_indices(const DeviceGrid& grid,
|
||||||
auto class_type = type->class_inf[iclass].type;
|
auto class_type = type->class_inf[iclass].type;
|
||||||
|
|
||||||
if (class_type == DRIVER) {
|
if (class_type == DRIVER) {
|
||||||
indices[OPIN][x_tile][y_tile][side].push_back(*index);
|
RRNodeId node = rr_graph.create_node(OPIN);
|
||||||
indices[IPIN][x_tile][y_tile][side].push_back(OPEN);
|
rr_graph.set_node_bounding_box(node, vtr::Rect<size_t>(xtile, ytile, xtile, ytile));
|
||||||
|
rr_graph.set_node_pin_num(ipin);
|
||||||
|
rr_graph.set_node_side(side);
|
||||||
} else {
|
} else {
|
||||||
VTR_ASSERT(class_type == RECEIVER);
|
VTR_ASSERT(class_type == RECEIVER);
|
||||||
indices[IPIN][x_tile][y_tile][side].push_back(*index);
|
RRNodeId node = rr_graph.create_node(IPIN);
|
||||||
indices[OPIN][x_tile][y_tile][side].push_back(OPEN);
|
rr_graph.set_node_bounding_box(node, vtr::Rect<size_t>(xtile, ytile, xtile, ytile));
|
||||||
|
rr_graph.set_node_pin_num(ipin);
|
||||||
|
rr_graph.set_node_side(side);
|
||||||
}
|
}
|
||||||
++(*index);
|
++(*index);
|
||||||
} else {
|
|
||||||
indices[IPIN][x_tile][y_tile][side].push_back(OPEN);
|
|
||||||
indices[OPIN][x_tile][y_tile][side].push_back(OPEN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sanity check
|
|
||||||
for (int width_offset = 0; width_offset < type->width; ++width_offset) {
|
|
||||||
int x_tile = x + width_offset;
|
|
||||||
for (int height_offset = 0; height_offset < type->height; ++height_offset) {
|
|
||||||
int y_tile = y + height_offset;
|
|
||||||
for (e_side side : SIDES) {
|
|
||||||
VTR_ASSERT(indices[IPIN][x_tile][y_tile][side].size() == size_t(type->num_pins));
|
|
||||||
VTR_ASSERT(indices[OPIN][x_tile][y_tile][side].size() == size_t(type->num_pins));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1151,59 +1158,54 @@ static void load_block_rr_indices(const DeviceGrid& grid,
|
||||||
for (size_t y = 0; y < grid.height(); y++) {
|
for (size_t y = 0; y < grid.height(); y++) {
|
||||||
int width_offset = grid[x][y].width_offset;
|
int width_offset = grid[x][y].width_offset;
|
||||||
int height_offset = grid[x][y].height_offset;
|
int height_offset = grid[x][y].height_offset;
|
||||||
if (width_offset != 0 || height_offset != 0) {
|
/* We only care the largest offset in both x and y direction
|
||||||
|
* this can avoid runtime cost to rebuild the fast look-up inside RRGraph object
|
||||||
|
*/
|
||||||
|
if ( (grid[x][y].type->height == height_offset && grid[x][y].type->width == width_offset)
|
||||||
|
&& (0 != height_offset && 0 != width_offset) ) {
|
||||||
int root_x = x - width_offset;
|
int root_x = x - width_offset;
|
||||||
int root_y = y - height_offset;
|
int root_y = y - height_offset;
|
||||||
|
|
||||||
indices[SOURCE][x][y] = indices[SOURCE][root_x][root_y];
|
//Process each block from it's root location
|
||||||
indices[SINK][x][y] = indices[SINK][root_x][root_y];
|
auto type = grid[x][y].type;
|
||||||
|
|
||||||
|
//Assign indicies for SINKs and SOURCEs
|
||||||
|
// Note that SINKS/SOURCES have no side, so we always use side 0
|
||||||
|
for (int iclass = 0; iclass < type->num_class; ++iclass) {
|
||||||
|
auto class_type = type->class_inf[iclass].type;
|
||||||
|
if (class_type == DRIVER) {
|
||||||
|
RRNodeId node = rr_graph.find_node(root_x, root_y, SOURCE, iclass);
|
||||||
|
/* Update the internal look-up so that we can find the SOURCE/SINK node using their offset coordinates */
|
||||||
|
rr_graph.set_node_bounding_box(node, vtr::Rect<size_t>(root_x, root_y, x, y));
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT(class_type == RECEIVER);
|
||||||
|
RRNodeId node = rr_graph.find_node(root_x, root_y, SINK, iclass);
|
||||||
|
/* Update the internal look-up so that we can find the SOURCE/SINK node using their offset coordinates */
|
||||||
|
rr_graph.set_node_bounding_box(node, vtr::Rect<size_t>(root_x, root_y, x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t_rr_node_indices alloc_and_load_rr_node_indices(const int max_chan_width,
|
RRGraph alloc_and_load_rr_node_indices(const int max_chan_width,
|
||||||
const DeviceGrid& grid,
|
const DeviceGrid& grid,
|
||||||
int* index,
|
int* index,
|
||||||
const t_chan_details& chan_details_x,
|
const t_chan_details& chan_details_x,
|
||||||
const t_chan_details& chan_details_y) {
|
const t_chan_details& chan_details_y) {
|
||||||
/* Allocates and loads all the structures needed for fast lookups of the *
|
/* Allocates and loads all the nodes in a RRGraph object */
|
||||||
* index of an rr_node. rr_node_indices is a matrix containing the index *
|
RRGraph rr_graph;
|
||||||
* of the *first* rr_node at a given (i,j) location. */
|
|
||||||
|
|
||||||
t_rr_node_indices indices;
|
|
||||||
|
|
||||||
/* Alloc the lookup table */
|
|
||||||
indices.resize(NUM_RR_TYPES);
|
|
||||||
for (t_rr_type rr_type : RR_TYPES) {
|
|
||||||
if (rr_type == CHANX) {
|
|
||||||
indices[rr_type].resize(grid.height());
|
|
||||||
for (size_t y = 0; y < grid.height(); ++y) {
|
|
||||||
indices[rr_type][y].resize(grid.width());
|
|
||||||
for (size_t x = 0; x < grid.width(); ++x) {
|
|
||||||
indices[rr_type][y][x].resize(NUM_SIDES);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
indices[rr_type].resize(grid.width());
|
|
||||||
for (size_t x = 0; x < grid.width(); ++x) {
|
|
||||||
indices[rr_type][x].resize(grid.height());
|
|
||||||
for (size_t y = 0; y < grid.height(); ++y) {
|
|
||||||
indices[rr_type][x][y].resize(NUM_SIDES);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assign indices for block nodes */
|
/* Assign indices for block nodes */
|
||||||
load_block_rr_indices(grid, indices, index);
|
load_block_rr_indices(grid, rr_graph, index);
|
||||||
|
|
||||||
/* Load the data for x and y channels */
|
/* Load the data for x and y channels */
|
||||||
load_chan_rr_indices(max_chan_width, grid.width(), grid.height(),
|
load_chan_rr_indices(max_chan_width, grid.width(), grid.height(),
|
||||||
CHANX, chan_details_x, indices, index);
|
CHANX, chan_details_x, rr_graph, index);
|
||||||
load_chan_rr_indices(max_chan_width, grid.height(), grid.width(),
|
load_chan_rr_indices(max_chan_width, grid.height(), grid.width(),
|
||||||
CHANY, chan_details_y, indices, index);
|
CHANY, chan_details_y, rr_graph, index);
|
||||||
return indices;
|
return rr_graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> get_rr_node_chan_wires_at_location(const t_rr_node_indices& L_rr_node_indices,
|
std::vector<int> get_rr_node_chan_wires_at_location(const t_rr_node_indices& L_rr_node_indices,
|
||||||
|
|
|
@ -39,7 +39,7 @@ typedef vtr::NdMatrix<short, 6> t_sblock_pattern;
|
||||||
|
|
||||||
/******************* Subroutines exported by rr_graph2.c *********************/
|
/******************* Subroutines exported by rr_graph2.c *********************/
|
||||||
|
|
||||||
t_rr_node_indices alloc_and_load_rr_node_indices(const int max_chan_width,
|
RRGraph alloc_and_load_rr_node_indices(const int max_chan_width,
|
||||||
const DeviceGrid& grid,
|
const DeviceGrid& grid,
|
||||||
int* index,
|
int* index,
|
||||||
const t_chan_details& chan_details_x,
|
const t_chan_details& chan_details_x,
|
||||||
|
|
Loading…
Reference in New Issue