From 22e71f5847b80c43855c69f5c0f51e21c8f2d08e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 May 2019 22:48:07 -0600 Subject: [PATCH] Add rotate one side of switch block functionality --- vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp | 180 +++++++++++++------ vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h | 7 +- 2 files changed, 126 insertions(+), 61 deletions(-) diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp index 25e29fda7..34107fd42 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp @@ -916,33 +916,40 @@ void RRSwitchBlock::set_conf_bits_msb(size_t conf_bits_msb) { } /* rotate all the channel nodes by a given offset */ -void RRSwitchBlock::rotate_full_chan_node(size_t offset) { +void RRSwitchBlock::rotate_side_chan_node(enum e_side side, size_t offset) { + Side side_manager(side); + /* Partition the chan nodes on this side, depending on its length */ + /* skip this side if there is no nodes */ + if (0 == get_chan_width(side)) { + return; + } + size_t adapt_offset = offset % get_chan_width(side); + assert(adapt_offset < get_chan_width(side)); + /* Find a group split, rotate */ + chan_node_[side_manager.to_size_t()].rotate(adapt_offset); + std::rotate(chan_node_direction_[side_manager.to_size_t()].begin(), + chan_node_direction_[side_manager.to_size_t()].begin() + adapt_offset, + chan_node_direction_[side_manager.to_size_t()].end()); + return; +} + + +/* rotate all the channel nodes by a given offset */ +void RRSwitchBlock::rotate_chan_node(size_t offset) { /* Rotate chan nodes on each side */ for (size_t side = 0; side < get_num_sides(); ++side) { Side side_manager(side); - /* Partition the chan nodes on this side, depending on its length */ - /* skip this side if there is no nodes */ - if (0 == get_chan_width(side_manager.get_side())) { - continue; - } - size_t adapt_offset = offset % get_chan_width(side_manager.get_side()); - assert(adapt_offset < get_chan_width(side_manager.get_side())); - /* Find a group split, rotate */ - chan_node_[side].rotate(adapt_offset); - std::rotate(chan_node_direction_[side].begin(), - chan_node_direction_[side].begin() + adapt_offset, - chan_node_direction_[side].end()); + rotate_side_chan_node(side_manager.get_side(), offset); } return; } - /* rotate all the channel nodes by a given offset: * Routing Channel nodes are divided into different groups using segment ids * each group is rotated separatedly */ -void RRSwitchBlock::rotate_chan_node(size_t offset) { +void RRSwitchBlock::rotate_chan_node_in_group(size_t offset) { /* Rotate chan nodes on each side */ for (size_t side = 0; side < get_num_sides(); ++side) { Side side_manager(side); @@ -985,51 +992,67 @@ void RRSwitchBlock::rotate_chan_node(size_t offset) { return; } -/* rotate all the opin nodes by a given offset */ -void RRSwitchBlock::rotate_opin_node(size_t offset) { +/* rotate one side of the opin nodes by a given offset + * OPIN nodes are divided into different groups depending on their grid + * each group is rotated separatedly + */ +void RRSwitchBlock::rotate_side_opin_node_in_group(enum e_side side, size_t offset) { + /* Rotate opin nodes on each side */ + Side side_manager(side); + size_t rotate_begin = 0; + size_t rotate_end = 0; + /* skip this side if there is no nodes */ + if (0 == get_num_opin_nodes(side)) { + return; + } + /* Partition the opin nodes on this side, depending on grids */ + for (size_t inode = 0; inode < get_num_opin_nodes(side) - 1; ++inode) { + if ( ( (opin_node_[side_manager.to_size_t()][inode]->xlow != opin_node_[side_manager.to_size_t()][inode + 1]->xlow) + || (opin_node_[side_manager.to_size_t()][inode]->ylow != opin_node_[side_manager.to_size_t()][inode + 1]->ylow) + || (opin_node_[side_manager.to_size_t()][inode]->xhigh != opin_node_[side_manager.to_size_t()][inode + 1]->xhigh) + || (opin_node_[side_manager.to_size_t()][inode]->yhigh != opin_node_[side_manager.to_size_t()][inode + 1]->yhigh) + || (opin_node_grid_side_[side_manager.to_size_t()][inode] != opin_node_grid_side_[side_manager.to_size_t()][inode + 1])) + || ( inode == get_num_opin_nodes(side) - 2) ) { + /* Record the upper bound */ + if ( inode == get_num_opin_nodes(side) - 2) { + rotate_end = get_num_opin_nodes(side) - 1; + } else { + rotate_end = inode; + } + /* skip this side if there is no nodes */ + if (0 >= rotate_end - rotate_begin) { + /* Update the lower bound */ + rotate_begin = inode + 1; + continue; + } + size_t adapt_offset = offset % (rotate_end - rotate_begin + 1); + /* Make sure offset is in range */ + assert (adapt_offset < rotate_end - rotate_begin + 1); + /* Find a group split, rotate */ + std::rotate(opin_node_[side_manager.to_size_t()].begin() + rotate_begin, + opin_node_[side_manager.to_size_t()].begin() + rotate_begin + adapt_offset, + opin_node_[side_manager.to_size_t()].begin() + rotate_end); + std::rotate(opin_node_grid_side_[side_manager.to_size_t()].begin() + rotate_begin, + opin_node_grid_side_[side_manager.to_size_t()].begin() + rotate_begin + adapt_offset, + opin_node_grid_side_[side_manager.to_size_t()].begin() + rotate_end); + /* Update the lower bound */ + rotate_begin = inode + 1; + } + } + + return; +} + + +/* rotate all the opin nodes by a given offset + * OPIN nodes are divided into different groups depending on their grid + * each group is rotated separatedly + */ +void RRSwitchBlock::rotate_opin_node_in_group(size_t offset) { /* Rotate opin nodes on each side */ for (size_t side = 0; side < get_num_sides(); ++side) { Side side_manager(side); - size_t rotate_begin = 0; - size_t rotate_end = 0; - /* skip this side if there is no nodes */ - if (0 == get_num_opin_nodes(side_manager.get_side())) { - continue; - } - /* Partition the opin nodes on this side, depending on grids */ - for (size_t inode = 0; inode < get_num_opin_nodes(side_manager.get_side()) - 1; ++inode) { - if ( ( (opin_node_[side][inode]->xlow != opin_node_[side][inode + 1]->xlow) - || (opin_node_[side][inode]->ylow != opin_node_[side][inode + 1]->ylow) - || (opin_node_[side][inode]->xhigh != opin_node_[side][inode + 1]->xhigh) - || (opin_node_[side][inode]->yhigh != opin_node_[side][inode + 1]->yhigh) - || (opin_node_grid_side_[side][inode] != opin_node_grid_side_[side][inode + 1])) - || ( inode == get_num_opin_nodes(side_manager.get_side()) - 2) ) { - /* Record the upper bound */ - if ( inode == get_num_opin_nodes(side_manager.get_side()) - 2) { - rotate_end = get_num_opin_nodes(side_manager.get_side()) - 1; - } else { - rotate_end = inode; - } - /* skip this side if there is no nodes */ - if (0 >= rotate_end - rotate_begin) { - /* Update the lower bound */ - rotate_begin = inode + 1; - continue; - } - size_t adapt_offset = offset % (rotate_end - rotate_begin + 1); - /* Make sure offset is in range */ - assert (adapt_offset < rotate_end - rotate_begin + 1); - /* Find a group split, rotate */ - std::rotate(opin_node_[side].begin() + rotate_begin, - opin_node_[side].begin() + rotate_begin + adapt_offset, - opin_node_[side].begin() + rotate_end); - std::rotate(opin_node_grid_side_[side].begin() + rotate_begin, - opin_node_grid_side_[side].begin() + rotate_begin + adapt_offset, - opin_node_grid_side_[side].begin() + rotate_end); - /* Update the lower bound */ - rotate_begin = inode + 1; - } - } + rotate_side_opin_node_in_group(side_manager.get_side(), offset); } return; @@ -1037,8 +1060,15 @@ void RRSwitchBlock::rotate_opin_node(size_t offset) { /* rotate all the channel and opin nodes by a given offset */ void RRSwitchBlock::rotate(size_t offset) { - rotate_full_chan_node(offset); - rotate_opin_node(offset); + rotate_chan_node(offset); + rotate_opin_node_in_group(offset); + return; +} + +/* rotate one side of the channel and opin nodes by a given offset */ +void RRSwitchBlock::rotate_side(enum e_side side, size_t offset) { + rotate_side_chan_node(side, offset); + rotate_side_opin_node_in_group(side, offset); return; } @@ -1426,6 +1456,38 @@ void DeviceRRSwitchBlock::add_rr_switch_block(DeviceCoordinator& coordinator, rr_switch_block_rotatable_mirror_id_[coordinator.get_x()][coordinator.get_y()] = mirror_id; break; } + /* For the copy, try 3 types of rotation and examine is_mirror + * Rotate only the X-direction nodes: LEFT and RIGHT + * Rotate only the Y-direction nodes: TOP and BOTTOM + * Rotate both X- and Y-direction nodes + */ + + /* Rotate LEFT and RIGHT only */ + RRSwitchBlock rotate_x_mirror = rotate_mirror; + rotate_x_mirror.rotate_side(LEFT, 1); + rotate_x_mirror.rotate_side(RIGHT, 1); + if (true == get_switch_block(rotatable_mirror_[mirror_id]).is_mirror(rotate_x_mirror)) { + /* This is a mirror, raise the flag and we finish */ + is_rotatable_mirror = false; + /* Record the id of unique mirror */ + rr_switch_block_rotatable_mirror_id_[coordinator.get_x()][coordinator.get_y()] = mirror_id; + break; + } + + /* Rotate TOP and BOTTOM only */ + RRSwitchBlock rotate_y_mirror = rotate_mirror; + rotate_y_mirror.rotate_side(TOP, 1); + rotate_y_mirror.rotate_side(BOTTOM, 1); + + if (true == get_switch_block(rotatable_mirror_[mirror_id]).is_mirror(rotate_y_mirror)) { + /* This is a mirror, raise the flag and we finish */ + is_rotatable_mirror = false; + /* Record the id of unique mirror */ + rr_switch_block_rotatable_mirror_id_[coordinator.get_x()][coordinator.get_y()] = mirror_id; + break; + } + + /* Rotate all sides */ rotate_mirror.rotate(1); } if (false == is_rotatable_mirror) { diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h index 2f58f2427..072daad0f 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h @@ -167,9 +167,12 @@ class RRSwitchBlock { void set_num_reserved_conf_bits(size_t num_reserved_conf_bits); void set_conf_bits_lsb(size_t conf_bits_lsb); void set_conf_bits_msb(size_t conf_bits_msb); - void rotate_full_chan_node(size_t offset); /* rotate all the channel nodes by a given offset */ + void rotate_side_chan_node(enum e_side side, size_t offset); /* rotate all the channel nodes by a given offset */ void rotate_chan_node(size_t offset); /* rotate all the channel nodes by a given offset */ - void rotate_opin_node(size_t offset); /* rotate all the opin nodes by a given offset */ + void rotate_chan_node_in_group(size_t offset); /* rotate all the channel nodes by a given offset */ + void rotate_side_opin_node_in_group(enum e_side side, size_t offset); /* rotate all the opin nodes by a given offset */ + void rotate_opin_node_in_group(size_t offset); /* rotate all the opin nodes by a given offset */ + void rotate_side(enum e_side side, size_t offset); /* rotate all the channel and opin nodes by a given offset */ void rotate(size_t offset); /* rotate all the channel and opin nodes by a given offset */ void clear(); void clear_chan_nodes(enum e_side node_side); /* Clean the chan_width of a side */