From d3eae80e64de06cbeff1d78aaf7c77c16f4dbad3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 May 2019 19:37:18 -0600 Subject: [PATCH] implemented an native way in finding rotable Switch blocks --- .../ARCH/k6_N10_sram_chain_HC_template.xml | 3 +- .../vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c | 2 +- .../SRC/fpga_x2p/base/fpga_x2p_timing_utils.c | 2 + .../fpga_x2p/base/fpga_x2p_unique_routing.c | 86 ++++---- .../fpga_x2p/base/fpga_x2p_unique_routing.h | 6 +- vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp | 198 +++++++++++++++--- vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h | 12 +- 7 files changed, 234 insertions(+), 75 deletions(-) diff --git a/vpr7_x2p/vpr/ARCH/k6_N10_sram_chain_HC_template.xml b/vpr7_x2p/vpr/ARCH/k6_N10_sram_chain_HC_template.xml index 6c5f95307..49bce7594 100644 --- a/vpr7_x2p/vpr/ARCH/k6_N10_sram_chain_HC_template.xml +++ b/vpr7_x2p/vpr/ARCH/k6_N10_sram_chain_HC_template.xml @@ -150,7 +150,8 @@ - + + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c index fd1857e0e..1553018a0 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c @@ -1400,7 +1400,7 @@ void fpga_x2p_setup(t_vpr_setup vpr_setup, /* Assign Gobal variable: build the Routing Resource Channels */ device_rr_chan = build_device_rr_chan(num_rr_nodes, rr_node, rr_node_indices, Arch->num_segments, rr_indexed_data); - device_rr_switch_block = build_device_rr_switch_blocks(num_rr_nodes, rr_node, rr_node_indices); + device_rr_switch_block = build_device_rr_switch_blocks(num_rr_nodes, rr_node, rr_node_indices, Arch->num_segments, rr_indexed_data); /* Rotatable will be done in the next step identify_rotatable_switch_blocks(); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_timing_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_timing_utils.c index 64955faa2..9682bf120 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_timing_utils.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_timing_utils.c @@ -31,6 +31,8 @@ #include "fpga_x2p_globals.h" #include "fpga_x2p_utils.h" +#include "fpga_x2p_timing_utils.h" + /* Build the list of spice_model_ports provided in the cur_spice_model delay_info */ t_spice_model_port** get_spice_model_delay_info_ports(t_spice_model* cur_spice_model, char* port_list, diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c index ee681c73f..2ab031cc1 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c @@ -82,9 +82,9 @@ void print_device_rr_chan_stats(DeviceRRChan& device_rr_chan); static RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, - int LL_num_rr_nodes, - t_rr_node* LL_rr_node, - t_ivec*** LL_rr_node_indices); + int LL_num_rr_nodes, t_rr_node* LL_rr_node, + t_ivec*** LL_rr_node_indices, int num_segments, + t_rr_indexed_data* LL_rr_indexed_data); /***** subroutines *****/ void assign_switch_block_mirror(t_sb* src, t_sb* des) { @@ -272,16 +272,18 @@ boolean is_two_switch_blocks_mirror(t_sb* src, t_sb* des) { /* check the numbers of opin_rr_nodes */ for (int side = 0; side < src->num_sides; ++side) { - if (src->num_ipin_rr_nodes[side] != des->num_ipin_rr_nodes[side]) { + if (src->num_opin_rr_nodes[side] != des->num_opin_rr_nodes[side]) { return FALSE; } } - /* Make sure the number of conf bits are the same */ + /* Make sure the number of conf bits are the same + * TODO: the check should be done when conf_bits are initialized when creating SBs if ( (src->conf_bits_msb - src->conf_bits_lsb) != (des->conf_bits_msb - des->conf_bits_lsb)) { return FALSE; } + */ return TRUE; } @@ -845,9 +847,9 @@ DeviceRRChan build_device_rr_chan(int LL_num_rr_nodes, t_rr_node* LL_rr_node, */ static RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, - int LL_num_rr_nodes, - t_rr_node* LL_rr_node, - t_ivec*** LL_rr_node_indices) { + int LL_num_rr_nodes, t_rr_node* LL_rr_node, + t_ivec*** LL_rr_node_indices, int num_segments, + t_rr_indexed_data* LL_rr_indexed_data) { /* Create an object to return */ RRSwitchBlock rr_switch_block; @@ -868,8 +870,7 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, Side side_manager(side); int ix = 0; int iy = 0; - int chan_width = 0; - t_rr_node** chan_rr_node = NULL; + RRChan rr_chan; int temp_num_opin_rr_nodes[2] = {0,0}; t_rr_node** temp_opin_rr_node[2] = {NULL, NULL}; enum e_side opin_grid_side[2] = {NUM_SIDES, NUM_SIDES}; @@ -884,11 +885,11 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, /* Routing channels*/ ix = sb_x; iy = sb_y + 1; - /* Channel width */ - chan_width = chan_width_y[ix]; /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - chan_rr_node = get_chan_rr_nodes(&chan_width, CHANY, ix, iy, - LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_rr_chan(CHANY, ix, iy, + LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices, + num_segments, LL_rr_indexed_data); chan_dir_to_port_dir_mapping[0] = OUT_PORT; chan_dir_to_port_dir_mapping[1] = IN_PORT; @@ -916,12 +917,12 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, /* Routing channels*/ ix = sb_x + 1; iy = sb_y; - /* Channel width */ - chan_width = chan_width_x[iy]; /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ /* Collect rr_nodes for Tracks for top: chany[x][y+1] */ - chan_rr_node = get_chan_rr_nodes(&chan_width, CHANX, ix, iy, - LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_rr_chan(CHANX, ix, iy, + LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices, + num_segments, LL_rr_indexed_data); chan_dir_to_port_dir_mapping[0] = OUT_PORT; chan_dir_to_port_dir_mapping[1] = IN_PORT; @@ -948,12 +949,12 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, /* Routing channels*/ ix = sb_x; iy = sb_y; - /* Channel width */ - chan_width = chan_width_y[ix]; /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ /* Collect rr_nodes for Tracks for bottom: chany[x][y] */ - chan_rr_node = get_chan_rr_nodes(&chan_width, CHANY, ix, iy, - LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_rr_chan(CHANY, ix, iy, + LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices, + num_segments, LL_rr_indexed_data); chan_dir_to_port_dir_mapping[0] = IN_PORT; chan_dir_to_port_dir_mapping[1] = OUT_PORT; @@ -980,12 +981,12 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, /* Routing channels*/ ix = sb_x; iy = sb_y; - /* Channel width */ - chan_width = chan_width_x[iy]; /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ /* Collect rr_nodes for Tracks for left: chanx[x][y] */ - chan_rr_node = get_chan_rr_nodes(&chan_width, CHANX, ix, iy, - LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_rr_chan(CHANX, ix, iy, + LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices, + num_segments, LL_rr_indexed_data); chan_dir_to_port_dir_mapping[0] = IN_PORT; chan_dir_to_port_dir_mapping[1] = OUT_PORT; @@ -1010,15 +1011,21 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, exit(1); } - /* Fill chan_rr_nodes */ - for (int itrack = 0; itrack < chan_width; ++itrack) { - /* Identify the directionality, record it in rr_node_direction */ - if (INC_DIRECTION == chan_rr_node[itrack]->direction) { - rr_switch_block.add_chan_node(chan_rr_node[itrack], side_manager.get_side(), chan_dir_to_port_dir_mapping[0]); - } else { - assert (DEC_DIRECTION == chan_rr_node[itrack]->direction); - rr_switch_block.add_chan_node(chan_rr_node[itrack], side_manager.get_side(), chan_dir_to_port_dir_mapping[1]); + /* Organize a vector of port direction */ + if (0 < rr_chan.get_chan_width()) { + std::vector rr_chan_dir; + rr_chan_dir.resize(rr_chan.get_chan_width()); + for (size_t itrack = 0; itrack < rr_chan.get_chan_width(); ++itrack) { + /* Identify the directionality, record it in rr_node_direction */ + if (INC_DIRECTION == rr_chan.get_node(itrack)->direction) { + rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[0]; + } else { + assert (DEC_DIRECTION == rr_chan.get_node(itrack)->direction); + rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[1]; + } } + /* Fill chan_rr_nodes */ + rr_switch_block.add_chan_node(side_manager.get_side(), rr_chan, rr_chan_dir); } /* Fill opin_rr_nodes */ @@ -1037,7 +1044,6 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, rr_switch_block.clear_ipin_nodes(side_manager.get_side()); /* Free */ - my_free(chan_rr_node); temp_num_opin_rr_nodes[0] = 0; my_free(temp_opin_rr_node[0]); temp_num_opin_rr_nodes[1] = 0; @@ -1058,9 +1064,9 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, * Each switch block in the FPGA fabric will be an instance of these modules. * We maintain a map from each instance to each module */ -DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes, - t_rr_node* LL_rr_node, - t_ivec*** LL_rr_node_indices) { +DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes, t_rr_node* LL_rr_node, + t_ivec*** LL_rr_node_indices, int num_segments, + t_rr_indexed_data* LL_rr_indexed_data) { /* Create an object */ DeviceRRSwitchBlock LL_device_rr_switch_block; @@ -1072,7 +1078,9 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes, for (int ix = 0; ix < nx + 1; ++ix) { for (int iy = 0; iy < ny + 1; ++iy) { RRSwitchBlock rr_switch_block = build_rr_switch_block(ix, iy, - LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); + LL_num_rr_nodes, LL_rr_node, + LL_rr_node_indices, + num_segments, LL_rr_indexed_data); DeviceCoordinator sb_coordinator((size_t)ix, (size_t)iy); LL_device_rr_switch_block.add_rr_switch_block(sb_coordinator, rr_switch_block); } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.h index 5c011e4ee..18a825e60 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.h @@ -14,9 +14,9 @@ DeviceRRChan build_device_rr_chan(int LL_num_rr_nodes, t_rr_node* LL_rr_node, * Each switch block in the FPGA fabric will be an instance of these modules. * We maintain a map from each instance to each module */ -DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes, - t_rr_node* LL_rr_node, - t_ivec*** LL_rr_node_indices); +DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes, t_rr_node* LL_rr_node, + t_ivec*** LL_rr_node_indices, int num_segments, + t_rr_indexed_data* LL_rr_indexed_data); /* Rotatable will be done in the next step identify_rotatable_switch_blocks(); 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 e56832b46..8c6e10aec 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp @@ -6,6 +6,13 @@ /* Member Functions of Class RRChan */ +/* Constructors */ +RRChan::RRChan() { + type_ = NUM_RR_TYPES; + nodes_.resize(0); + node_segments_.resize(0); +} + /* Accessors */ t_rr_type RRChan::get_type() const { return type_; @@ -112,9 +119,18 @@ void RRChan::add_node(t_rr_node* node, size_t node_segment) { nodes_[node->ptc_num] = node; node_segments_[node->ptc_num] = node_segment; + assert(valid_node_type(node)); + return; } +/* rotate the nodes and node_segments with a given offset */ +void RRChan::rotate(size_t rotate_begin, size_t rotate_end, size_t offset) { + std::rotate(nodes_.begin() + rotate_begin, nodes_.begin() + rotate_begin + offset, nodes_.begin() + rotate_end); + std::rotate(node_segments_.begin() + rotate_begin, node_segments_.begin() + rotate_begin + offset, node_segments_.begin() + rotate_end); + return; +} + /* Clear content */ void RRChan::clear() { nodes_.clear(); @@ -133,6 +149,19 @@ bool RRChan::valid_type(t_rr_type type) const { return false; } +/* Check each node, see if the node type is consistent with the type */ +bool RRChan::valid_node_type(t_rr_node* node) const { + valid_type(node->type); + if (NUM_RR_TYPES == type_) { + return true; + } + valid_type(type_); + if (type_ != node->type) { + return false; + } + return true; +} + /* check if the node id is valid */ bool RRChan::valid_node_id(size_t node_id) const { if (node_id < nodes_.size()) { @@ -333,7 +362,7 @@ size_t RRSwitchBlock::get_num_sides() const { size_t RRSwitchBlock::get_chan_width(enum e_side side) const { Side side_manager(side); assert(side_manager.validate()); - return chan_node_[side_manager.to_size_t()].size(); + return chan_node_[side_manager.to_size_t()].get_chan_width(); } /* Get the maximum number of routing tracks on all sides */ @@ -371,9 +400,24 @@ t_rr_node* RRSwitchBlock::get_chan_node(enum e_side side, size_t track_id) const /* Ensure the track is valid in the context of this switch block at a specific side */ assert( validate_track_id(side, track_id) ); - return chan_node_[side_manager.to_size_t()][track_id]; + return chan_node_[side_manager.to_size_t()].get_node(track_id); } +/* get the segment id of a channel rr_node */ +size_t RRSwitchBlock::get_chan_node_segment(enum e_side side, size_t track_id) const { + Side side_manager(side); + assert(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + assert( validate_side(side) ); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + assert( validate_track_id(side, track_id) ); + + return chan_node_[side_manager.to_size_t()].get_node_segment(track_id); +} + + /* Get the number of IPIN rr_nodes on a side */ size_t RRSwitchBlock::get_num_ipin_nodes(enum e_side side) const { Side side_manager(side); @@ -443,8 +487,8 @@ int RRSwitchBlock::get_node_index(t_rr_node* node, switch (node->type) { case CHANX: case CHANY: - for (size_t inode = 0; inode < get_chan_width(node_side); ++inode) { - if ((node == chan_node_[side_manager.to_size_t()][inode]) + for (size_t inode = 0; inode < get_chan_width(node_side); ++inode){ + if ((node == chan_node_[side_manager.to_size_t()].get_node(inode)) /* Check if direction meets specification */ &&(node_direction == chan_node_direction_[side_manager.to_size_t()][inode])) { cnt++; @@ -580,6 +624,83 @@ bool RRSwitchBlock::is_node_imply_short_connection(t_rr_node* src_node) const { return false; } +/* check if the candidate SB satisfy the basic requirements on being a mirror of the current one */ +/* Idenify mirror Switch blocks + * Check each two switch blocks: + * Number of channel/opin/ipin rr_nodes are same + * If all above are satisfied, the two switch blocks may be mirrors ! + */ +bool RRSwitchBlock::is_mirrorable(RRSwitchBlock& cand) const { + /* check the numbers of sides */ + if (get_num_sides() != cand.get_num_sides()) { + return false; + } + + /* check the numbers/directionality of channel rr_nodes */ + for (size_t side = 0; side < get_num_sides(); ++side) { + Side side_manager(side); + + /* Ensure we have the same channel width on this side */ + if (get_chan_width(side_manager.get_side()) != cand.get_chan_width(side_manager.get_side())) { + return false; + } + + if ( ((size_t(-1) == get_track_id_first_short_connection(side_manager.get_side())) + && (size_t(-1) != cand.get_track_id_first_short_connection(side_manager.get_side()))) + || ((size_t(-1) != get_track_id_first_short_connection(side_manager.get_side()) ) + && ( size_t(-1) == cand.get_track_id_first_short_connection(side_manager.get_side()))) ) { + return false; + } + } + + /* check the numbers of opin_rr_nodes */ + for (size_t side = 0; side < get_num_sides(); ++side) { + Side side_manager(side); + + if (get_num_opin_nodes(side_manager.get_side()) != cand.get_num_opin_nodes(side_manager.get_side())) { + return false; + } + } + + /* Make sure the number of conf bits are the same */ + /* TODO: recover this check when the SB conf bits are allocated during setup stage!!! + if ( ( get_num_conf_bits() != cand.get_num_conf_bits() ) + || ( get_num_reserved_conf_bits() != cand.get_num_reserved_conf_bits() ) ) { + return false; + } + */ + + return true; +} + +/* Determine an initial offset in rotating the candidate Switch Block to find a mirror matching + * We try to find the offset in track_id where the two Switch Blocks have their first short connections + */ +size_t RRSwitchBlock::get_hint_rotate_offset(RRSwitchBlock& cand) const { + size_t offset_hint = size_t(-1); + + assert (get_num_sides() == cand.get_num_sides()); + + /* check the numbers/directionality of channel rr_nodes */ + for (size_t side = 0; side < get_num_sides(); ++side) { + Side side_manager(side); + + /* Ensure we have the same channel width on this side */ + assert (get_chan_width(side_manager.get_side()) == cand.get_chan_width(side_manager.get_side())); + + /* Find the track id of the first short connection */ + size_t src_offset = get_track_id_first_short_connection(side_manager.get_side()); + size_t des_offset = cand.get_track_id_first_short_connection(side_manager.get_side()); + if ( size_t(-1) == src_offset || size_t(-1) == des_offset ) { + return 0; /* default we give zero */ + } + size_t temp_hint = abs( (int)(src_offset - des_offset)); + offset_hint = std::min(temp_hint, offset_hint); + } + return offset_hint; +} + + /* check if the candidate SB is a mirror of the current one */ /* Idenify mirror Switch blocks * Check each two switch blocks: @@ -630,16 +751,18 @@ bool RRSwitchBlock::is_mirror(RRSwitchBlock& cand) const { for (size_t side = 0; side < get_num_sides(); ++side) { Side side_manager(side); - if (get_num_ipin_nodes(side_manager.get_side()) != cand.get_num_ipin_nodes(side_manager.get_side())) { + if (get_num_opin_nodes(side_manager.get_side()) != cand.get_num_opin_nodes(side_manager.get_side())) { return false; } } /* Make sure the number of conf bits are the same */ + /* TODO: the num conf bits will be fixed when allocate the SBs if ( ( get_num_conf_bits() != cand.get_num_conf_bits() ) || ( get_num_reserved_conf_bits() != cand.get_num_reserved_conf_bits() ) ) { return false; } + */ return true; } @@ -732,17 +855,14 @@ void RRSwitchBlock::init_num_sides(size_t num_sides) { } /* Add a node to the chan_node_ list and also assign its direction in chan_node_direction_ */ -void RRSwitchBlock::add_chan_node(t_rr_node* node, enum e_side node_side, enum PORTS node_direction) { +void RRSwitchBlock::add_chan_node(enum e_side node_side, RRChan rr_chan, std::vector rr_chan_dir) { Side side_manager(node_side); + /* Validate: 1. side is valid, the type of node is valid */ assert(validate_side(node_side)); - /* resize the array if needed, node is placed in the sequence of node->ptc_num */ - if (size_t(node->ptc_num + 1) > chan_node_[side_manager.to_size_t()].size()) { - chan_node_[side_manager.to_size_t()].resize(node->ptc_num + 1); /* resize to the maximum */ - chan_node_direction_[side_manager.to_size_t()].resize(node->ptc_num + 1); /* resize to the maximum */ - } + /* fill the dedicated element in the vector */ - chan_node_[side_manager.to_size_t()][node->ptc_num] = node; - chan_node_direction_[side_manager.to_size_t()][node->ptc_num] = node_direction; + chan_node_[side_manager.to_size_t()] = rr_chan; + chan_node_direction_[side_manager.to_size_t()] = rr_chan_dir; return; } @@ -798,7 +918,7 @@ void RRSwitchBlock::rotate_chan_node(size_t offset) { continue; } for (size_t inode = 0; inode < get_chan_width(side_manager.get_side()) - 1; ++inode) { - if ( ( abs(chan_node_[side][inode]->yhigh - chan_node_[side][inode]->ylow + chan_node_[side][inode]->xhigh - chan_node_[side][inode]->xlow) != abs(chan_node_[side][inode + 1]->yhigh - chan_node_[side][inode + 1]->ylow + chan_node_[side][inode + 1]->xhigh - chan_node_[side][inode + 1]->xlow)) + if ( (get_chan_node_segment(side_manager.get_side(), inode) != get_chan_node_segment(side_manager.get_side(), inode + 1)) || ( inode == get_chan_width(side_manager.get_side()) - 2) ) { /* Record the upper bound */ if ( inode == get_chan_width(side_manager.get_side()) - 2) { @@ -815,12 +935,10 @@ void RRSwitchBlock::rotate_chan_node(size_t offset) { } assert(offset < rotate_end - rotate_begin + 1); /* Find a group split, rotate */ - std::rotate(chan_node_.begin() + rotate_begin, - chan_node_.begin() + rotate_begin + offset, - chan_node_.begin() + rotate_end); - std::rotate(chan_node_direction_.begin() + rotate_begin, - chan_node_direction_.begin() + rotate_begin + offset, - chan_node_direction_.begin() + rotate_end); + chan_node_[side].rotate(rotate_begin, rotate_end, offset); + std::rotate(chan_node_direction_[side].begin() + rotate_begin, + chan_node_direction_[side].begin() + rotate_begin + offset, + chan_node_direction_[side].begin() + rotate_end); /* Update the lower bound */ rotate_begin = inode + 1; } @@ -865,12 +983,12 @@ void RRSwitchBlock::rotate_opin_node(size_t offset) { /* Make sure offset is in range */ assert (offset < rotate_end - rotate_begin + 1); /* Find a group split, rotate */ - std::rotate(opin_node_.begin() + rotate_begin, - opin_node_.begin() + rotate_begin + offset, - opin_node_.begin() + rotate_end); - std::rotate(opin_node_grid_side_.begin() + rotate_begin, - opin_node_grid_side_.begin() + rotate_begin + offset, - opin_node_grid_side_.begin() + rotate_end); + std::rotate(opin_node_[side].begin() + rotate_begin, + opin_node_[side].begin() + rotate_begin + 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 + offset, + opin_node_grid_side_[side].begin() + rotate_end); /* Update the lower bound */ rotate_begin = inode + 1; } @@ -971,6 +1089,7 @@ bool RRSwitchBlock::is_node_mirror(RRSwitchBlock& cand, t_rr_node* node = this->get_chan_node(node_side, track_id); t_rr_node* cand_node = cand.get_chan_node(node_side, track_id); bool is_short_conkt = this->is_node_imply_short_connection(node); + if (is_short_conkt != cand.is_node_imply_short_connection(cand_node)) { return false; } @@ -1012,6 +1131,19 @@ bool RRSwitchBlock::is_node_mirror(RRSwitchBlock& cand, return true; } +size_t RRSwitchBlock::get_track_id_first_short_connection(enum e_side node_side) const { + assert(validate_side(node_side)); + + /* Walk through chan_nodes and find the first short connection */ + for (size_t inode = 0; inode < get_chan_width(node_side); ++inode) { + if (true == is_node_imply_short_connection(get_chan_node(node_side, inode))) { + return inode; + } + } + + return size_t(-1); +} + /* Validate if the number of sides are consistent among internal data arrays ! */ bool RRSwitchBlock::validate_num_sides() const { size_t num_sides = chan_node_direction_.size(); @@ -1055,7 +1187,7 @@ bool RRSwitchBlock::validate_track_id(enum e_side side, size_t track_id) const { if (false == validate_side(side)) { return false; } - if ( ( track_id < chan_node_[side_manager.to_size_t()].size()) + if ( ( track_id < chan_node_[side_manager.to_size_t()].get_chan_width()) && ( track_id < chan_node_direction_[side_manager.to_size_t()].size()) ) { return true; } @@ -1238,18 +1370,26 @@ void DeviceRRSwitchBlock::add_rr_switch_block(DeviceCoordinator& coordinator, /* add rotatable mirror support */ for (size_t mirror_id = 0; mirror_id < get_num_rotatable_mirror(); ++mirror_id) { RRSwitchBlock rotate_mirror = rr_switch_block; + is_rotatable_mirror = true; /* Try to rotate as many times as the maximum channel width in this switch block * This may not fully cover all the rotation possibility but may be enough now */ + /* Skip if these may never match as a mirror (violation in basic requirements */ + if (false == get_switch_block(rotatable_mirror_[mirror_id]).is_mirrorable(rotate_mirror)) { + continue; + } + /* Give an initial rotation to accelerate the prediction */ + size_t hint_offset = get_switch_block(rotatable_mirror_[mirror_id]).get_hint_rotate_offset(rotate_mirror); + rotate_mirror.rotate_chan_node(hint_offset); for (size_t offset = 0; offset < rr_switch_block.get_max_chan_width(); ++offset) { - rotate_mirror.rotate(1); - if (true == get_switch_block(unique_mirror_[mirror_id]).is_mirror(rotate_mirror)) { + if (true == get_switch_block(rotatable_mirror_[mirror_id]).is_mirror(rotate_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_mirror.rotate_chan_node(1); } if (false == is_rotatable_mirror) { break; 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 aba328fa8..20050bbc0 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h @@ -36,6 +36,8 @@ * ------------- */ class RRChan { + public: /* Constructors */ + RRChan(); public: /* Accessors */ t_rr_type get_type() const; size_t get_chan_width() const; /* get the number of tracks in this channel */ @@ -48,9 +50,11 @@ class RRChan { void set_type(t_rr_type type); /* modify type */ void reserve_node(size_t node_size); /* reseve a number of nodes to the array */ void add_node(t_rr_node* node, size_t node_segment); /* add a node to the array */ + void rotate(size_t rotate_begin, size_t rotate_end, size_t offset); /* rotate the nodes and node_segments with a given offset */ void clear(); /* clear the content */ private: /* internal functions */ bool valid_type(t_rr_type type) const; + bool valid_node_type(t_rr_node* node) const; bool valid_node_id(size_t node_id) const; private: /* Internal Data */ t_rr_type type_; /* channel type: CHANX or CHANY */ @@ -129,6 +133,7 @@ class RRSwitchBlock { size_t get_max_chan_width() const; /* Get the maximum number of routing tracks on all sides */ enum PORTS get_chan_node_direction(enum e_side side, size_t track_id) const; /* Get the direction of a rr_node at a given side and track_id */ t_rr_node* get_chan_node(enum e_side side, size_t track_id) const; /* get a rr_node at a given side and track_id */ + size_t get_chan_node_segment(enum e_side side, size_t track_id) const; /* get the segment id of a channel rr_node */ size_t get_num_ipin_nodes(enum e_side side) const; /* Get the number of IPIN rr_nodes on a side */ size_t get_num_opin_nodes(enum e_side side) const; /* Get the number of OPIN rr_nodes on a side */ t_rr_node* get_opin_node(enum e_side side, size_t node_id) const; /* get a rr_node at a given side and track_id */ @@ -145,6 +150,8 @@ class RRSwitchBlock { size_t get_conf_bits_msb() const; bool is_node_imply_short_connection(t_rr_node* src_node) const; /* Check if the node imply a short connection inside the SB, which happens to long wires across a FPGA fabric */ bool is_mirror(RRSwitchBlock& cand) const; /* check if the candidate SB is a mirror of the current one */ + bool is_mirrorable(RRSwitchBlock& cand) const; /* check if the candidate SB satisfy the basic requirements on being a mirror of the current one */ + size_t get_hint_rotate_offset(RRSwitchBlock& cand) const; /* Determine an initial offset in rotating the candidate Switch Block to find a mirror matching*/ public: /* Cooridinator conversion */ DeviceCoordinator get_side_block_coordinator(enum e_side side) const; public: /* Verilog writer */ @@ -153,7 +160,7 @@ class RRSwitchBlock { public: /* Mutators */ void set_coordinator(size_t x, size_t y); void init_num_sides(size_t num_sides); /* Allocate the vectors with the given number of sides */ - void add_chan_node(t_rr_node* node, enum e_side node_side, enum PORTS node_direction); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ + void add_chan_node(enum e_side node_side, RRChan rr_chan, std::vector rr_chan_dir); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ void add_ipin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ void add_opin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ void set_num_reserved_conf_bits(size_t num_reserved_conf_bits); @@ -170,6 +177,7 @@ class RRSwitchBlock { private: /* Internal Mutators */ private: /* internal functions */ bool is_node_mirror (RRSwitchBlock& cand, enum e_side node_side, size_t track_id) const; + size_t get_track_id_first_short_connection(enum e_side node_side) const; bool validate_num_sides() const; bool validate_side(enum e_side side) const; bool validate_track_id(enum e_side side, size_t track_id) const; @@ -178,8 +186,8 @@ class RRSwitchBlock { bool validate_num_conf_bits() const; private: /* Internal Data */ DeviceCoordinator coordinator_; + std::vector chan_node_; std::vector< std::vector > chan_node_direction_; - std::vector< std::vector > chan_node_; std::vector< std::vector > ipin_node_; std::vector< std::vector > ipin_node_grid_side_; std::vector< std::vector > opin_node_;