implemented an native way in finding rotable Switch blocks
This commit is contained in:
parent
ae0248fbc6
commit
d3eae80e64
|
@ -150,7 +150,8 @@
|
|||
<!-- ODIN II specific config ends -->
|
||||
|
||||
<!-- Physical descriptions begin -->
|
||||
<layout auto="1.0"/>
|
||||
<!--layout auto="1.0"/-->
|
||||
<layout height="20" width="20"/>
|
||||
<spice_settings>
|
||||
<parameters>
|
||||
<options sim_temp="25" post="off" captab="off" fast="on"/>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<enum PORTS> 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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<enum PORTS> 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;
|
||||
|
|
|
@ -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<enum PORTS> 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<RRChan> chan_node_;
|
||||
std::vector< std::vector<enum PORTS> > chan_node_direction_;
|
||||
std::vector< std::vector<t_rr_node*> > chan_node_;
|
||||
std::vector< std::vector<t_rr_node*> > ipin_node_;
|
||||
std::vector< std::vector<enum e_side> > ipin_node_grid_side_;
|
||||
std::vector< std::vector<t_rr_node*> > opin_node_;
|
||||
|
|
Loading…
Reference in New Issue