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 {
|
||||
/* 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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -1200,28 +1212,50 @@ void RRGraph::build_fast_node_lookup() const {
|
|||
continue;
|
||||
}
|
||||
RRNodeId node = RRNodeId(id);
|
||||
size_t x = node_xlow(node);
|
||||
size_t y = node_ylow(node);
|
||||
size_t itype = node_type(node);
|
||||
/* Special for SOURCE and SINK, we should annotate in the look-up
|
||||
* for all the (x,y) upto (xhigh, yhigh)
|
||||
*/
|
||||
std::vector<size_t> xlows;
|
||||
std::vector<size_t> ylows;
|
||||
|
||||
size_t ptc = node_ptc_num(node);
|
||||
if (ptc >= node_lookup_[x][y][itype].size()) {
|
||||
node_lookup_[x][y][itype].resize(ptc + 1);
|
||||
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));
|
||||
}
|
||||
|
||||
size_t iside = -1;
|
||||
if (node_type(node) == OPIN || node_type(node) == IPIN) {
|
||||
iside = node_side(node);
|
||||
} else {
|
||||
iside = NUM_SIDES;
|
||||
}
|
||||
for (size_t x : xlows) {
|
||||
for (size_t y : ylows) {
|
||||
size_t itype = node_type(node);
|
||||
|
||||
if (iside >= node_lookup_[x][y][itype][ptc].size()) {
|
||||
node_lookup_[x][y][itype][ptc].resize(iside + 1);
|
||||
}
|
||||
size_t ptc = node_ptc_num(node);
|
||||
if (ptc >= node_lookup_[x][y][itype].size()) {
|
||||
node_lookup_[x][y][itype].resize(ptc + 1);
|
||||
}
|
||||
|
||||
//Save node in lookup
|
||||
node_lookup_[x][y][itype][ptc][iside] = node;
|
||||
size_t iside = -1;
|
||||
if (node_type(node) == OPIN || node_type(node) == IPIN) {
|
||||
iside = node_side(node);
|
||||
} else {
|
||||
iside = NUM_SIDES;
|
||||
}
|
||||
|
||||
if (iside >= node_lookup_[x][y][itype][ptc].size()) {
|
||||
node_lookup_[x][y][itype][ptc].resize(iside + 1);
|
||||
}
|
||||
|
||||
//Save node in lookup
|
||||
node_lookup_[x][y][itype][ptc][iside] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -591,13 +591,11 @@ static void build_rr_graph(const t_graph_type graph_type,
|
|||
/* Alloc node lookups, count nodes, alloc rr nodes */
|
||||
int num_rr_nodes = 0;
|
||||
|
||||
/* Xifan Tang - Keep the node indices here since it counts the number of rr_nodes
|
||||
* We will simplify this function as indices will be built inside the RRGraph object
|
||||
/* Xifan Tang -
|
||||
* 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,
|
||||
&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);
|
||||
device_ctx.rr_graph = alloc_and_load_rr_node_indices(max_chan_width, grid,
|
||||
&num_rr_nodes, chan_details_x, chan_details_y);
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -31,11 +31,11 @@ static void load_chan_rr_indices(const int max_chan_width,
|
|||
const int num_chans,
|
||||
const t_rr_type type,
|
||||
const t_chan_details& chan_details,
|
||||
t_rr_node_indices& indices,
|
||||
RRGraph& rr_graph,
|
||||
int* index);
|
||||
|
||||
static void load_block_rr_indices(const DeviceGrid& grid,
|
||||
t_rr_node_indices& indices,
|
||||
RRGraph& rr_graph,
|
||||
int* index);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* 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,
|
||||
const int chan_len,
|
||||
const int num_chans,
|
||||
const t_rr_type type,
|
||||
const t_chan_details& chan_details,
|
||||
t_rr_node_indices& indices,
|
||||
RRGraph& rr_graph,
|
||||
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 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);
|
||||
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)
|
||||
continue;
|
||||
|
||||
int start = get_seg_start(seg_details, track, chan, seg);
|
||||
|
||||
/* If the start of the wire doesn't have a inode,
|
||||
* assign one to it. */
|
||||
int inode = indices[type][chan][start][0][track];
|
||||
if (OPEN == inode) {
|
||||
inode = *index;
|
||||
++(*index);
|
||||
|
||||
indices[type][chan][start][0][track] = inode;
|
||||
|
||||
/* If this segment does not start from the current position, we do not allocate any nodes */
|
||||
if (start != seg) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Assign inode of start of wire to current position */
|
||||
indices[type][chan][seg][0][track] = inode;
|
||||
RRNodeId node = rr_graph.create_node(type);
|
||||
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,
|
||||
t_rr_node_indices& indices,
|
||||
RRGraph& rr_graph,
|
||||
int* index) {
|
||||
//Walk through the grid assigning indices to SOURCE/SINK IPIN/OPIN
|
||||
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) {
|
||||
auto class_type = type->class_inf[iclass].type;
|
||||
if (class_type == DRIVER) {
|
||||
indices[SOURCE][x][y][0].push_back(*index);
|
||||
indices[SINK][x][y][0].push_back(OPEN);
|
||||
RRNodeId node = rr_graph.create_node(SOURCE);
|
||||
rr_graph.set_node_bounding_box(node, vtr::Rect<size_t>(x, y, x, y));
|
||||
rr_graph.set_node_class_num(iclass);
|
||||
} else {
|
||||
VTR_ASSERT(class_type == RECEIVER);
|
||||
indices[SINK][x][y][0].push_back(*index);
|
||||
indices[SOURCE][x][y][0].push_back(OPEN);
|
||||
RRNodeId node = rr_graph.create_node(SINK);
|
||||
rr_graph.set_node_bounding_box(node, vtr::Rect<size_t>(x, y, x, y));
|
||||
rr_graph.set_node_class_num(iclass);
|
||||
}
|
||||
++(*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
|
||||
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;
|
||||
|
||||
if (class_type == DRIVER) {
|
||||
indices[OPIN][x_tile][y_tile][side].push_back(*index);
|
||||
indices[IPIN][x_tile][y_tile][side].push_back(OPEN);
|
||||
RRNodeId node = rr_graph.create_node(OPIN);
|
||||
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 {
|
||||
VTR_ASSERT(class_type == RECEIVER);
|
||||
indices[IPIN][x_tile][y_tile][side].push_back(*index);
|
||||
indices[OPIN][x_tile][y_tile][side].push_back(OPEN);
|
||||
RRNodeId node = rr_graph.create_node(IPIN);
|
||||
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);
|
||||
} 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++) {
|
||||
int width_offset = grid[x][y].width_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_y = y - height_offset;
|
||||
|
||||
indices[SOURCE][x][y] = indices[SOURCE][root_x][root_y];
|
||||
indices[SINK][x][y] = indices[SINK][root_x][root_y];
|
||||
//Process each block from it's root location
|
||||
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,
|
||||
const DeviceGrid& grid,
|
||||
int* index,
|
||||
const t_chan_details& chan_details_x,
|
||||
const t_chan_details& chan_details_y) {
|
||||
/* Allocates and loads all the structures needed for fast lookups of the *
|
||||
* index of an rr_node. rr_node_indices is a matrix containing the index *
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RRGraph alloc_and_load_rr_node_indices(const int max_chan_width,
|
||||
const DeviceGrid& grid,
|
||||
int* index,
|
||||
const t_chan_details& chan_details_x,
|
||||
const t_chan_details& chan_details_y) {
|
||||
/* Allocates and loads all the nodes in a RRGraph object */
|
||||
RRGraph rr_graph;
|
||||
|
||||
/* 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_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(),
|
||||
CHANY, chan_details_y, indices, index);
|
||||
return indices;
|
||||
CHANY, chan_details_y, rr_graph, index);
|
||||
return rr_graph;
|
||||
}
|
||||
|
||||
std::vector<int> get_rr_node_chan_wires_at_location(const t_rr_node_indices& L_rr_node_indices,
|
||||
|
|
|
@ -39,11 +39,11 @@ typedef vtr::NdMatrix<short, 6> t_sblock_pattern;
|
|||
|
||||
/******************* Subroutines exported by rr_graph2.c *********************/
|
||||
|
||||
t_rr_node_indices alloc_and_load_rr_node_indices(const int max_chan_width,
|
||||
const DeviceGrid& grid,
|
||||
int* index,
|
||||
const t_chan_details& chan_details_x,
|
||||
const t_chan_details& chan_details_y);
|
||||
RRGraph alloc_and_load_rr_node_indices(const int max_chan_width,
|
||||
const DeviceGrid& grid,
|
||||
int* index,
|
||||
const t_chan_details& chan_details_x,
|
||||
const t_chan_details& chan_details_y);
|
||||
|
||||
int get_rr_node_index(int x,
|
||||
int y,
|
||||
|
|
Loading…
Reference in New Issue