many bug fixing for tileable rr_graph generator. Still debugging

This commit is contained in:
tangxifan 2019-06-21 17:58:46 -06:00
parent d48fd959a9
commit 41954056ce
6 changed files with 318 additions and 158 deletions

View File

@ -73,6 +73,15 @@ size_t ChanNodeDetails::get_track_node_id(size_t track_id) const {
return track_node_ids_[track_id];
}
/* Return a copy of vector */
std::vector<size_t> ChanNodeDetails::get_track_node_ids() const {
std::vector<size_t> copy;
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
copy.push_back(track_node_ids_[inode]);
}
return copy;
}
e_direction ChanNodeDetails::get_track_direction(size_t track_id) const {
assert(validate_track_id(track_id));
return track_direction_[track_id];
@ -111,9 +120,6 @@ std::vector<size_t> ChanNodeDetails::get_seg_group(size_t track_id) const {
/* Make sure a clean start */
group.clear();
/* track_id is the first element */
group.push_back(track_id);
for (size_t itrack = track_id; itrack < get_chan_width(); ++itrack) {
if ( (get_track_direction(itrack) == get_track_direction(track_id) )
&& (get_track_segment_length(itrack) == get_track_segment_length(track_id)) ) {
@ -146,9 +152,13 @@ std::vector<size_t> ChanNodeDetails::get_seg_group_node_id(std::vector<size_t> s
}
/* Get the number of tracks that starts in this routing channel */
size_t ChanNodeDetails::get_num_starting_tracks() const {
size_t ChanNodeDetails::get_num_starting_tracks(enum e_direction track_direction) const {
size_t counter = 0;
for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) {
/* Bypass unmatched track_direction */
if (track_direction != get_track_direction(itrack)) {
continue;
}
if (false == is_track_start(itrack)) {
continue;
}
@ -158,9 +168,13 @@ size_t ChanNodeDetails::get_num_starting_tracks() const {
}
/* Get the number of tracks that ends in this routing channel */
size_t ChanNodeDetails::get_num_ending_tracks() const {
size_t ChanNodeDetails::get_num_ending_tracks(enum e_direction track_direction) const {
size_t counter = 0;
for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) {
/* Bypass unmatched track_direction */
if (track_direction != get_track_direction(itrack)) {
continue;
}
if (false == is_track_end(itrack)) {
continue;
}
@ -169,6 +183,7 @@ size_t ChanNodeDetails::get_num_ending_tracks() const {
return counter;
}
/************************************************************************
* Mutators
***********************************************************************/
@ -198,6 +213,15 @@ void ChanNodeDetails::set_track_node_id(size_t track_index, size_t track_node_id
track_node_ids_[track_index] = track_node_id;
}
/* Update the node_ids from a vector */
void ChanNodeDetails::set_track_node_ids(std::vector<size_t> track_node_ids) {
/* the size of vector should match chan_width */
assert ( get_chan_width() == track_node_ids.size() );
for (size_t inode = 0; inode < track_node_ids.size(); ++inode) {
track_node_ids_[inode] = track_node_ids[inode];
}
}
/* Set tracks with a given direction to start */
void ChanNodeDetails::set_tracks_start(e_direction track_direction) {
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
@ -220,6 +244,11 @@ void ChanNodeDetails::set_tracks_end(e_direction track_direction) {
/* rotate the track_node_id by an offset */
void ChanNodeDetails::rotate_track_node_id(size_t offset, e_direction track_direction, bool counter_rotate) {
/* Direct return if offset = 0*/
if (0 == offset) {
return;
}
/* Rotate the node_ids by groups
* A group begins from a track_start and ends before another track_start
*/
@ -237,11 +266,13 @@ void ChanNodeDetails::rotate_track_node_id(size_t offset, e_direction track_dire
std::vector<size_t> track_group = get_seg_group(itrack);
/* Build a vector of the node ids of the tracks */
std::vector<size_t> track_group_node_id = get_seg_group_node_id(track_group);
/* adapt offset to the range of track_group_node_id */
size_t actual_offset = offset % track_group_node_id.size();
/* Rotate or Counter rotate */
if (true == counter_rotate) {
std::rotate(track_group_node_id.begin(), track_group_node_id.end() - offset, track_group_node_id.end());
std::rotate(track_group_node_id.rbegin(), track_group_node_id.rbegin() + actual_offset, track_group_node_id.rend());
} else {
std::rotate(track_group_node_id.begin(), track_group_node_id.begin() + offset, track_group_node_id.end());
std::rotate(track_group_node_id.begin(), track_group_node_id.begin() + actual_offset, track_group_node_id.end());
}
/* Update the node_ids */
for (size_t inode = 0; inode < track_group.size(); ++inode) {

View File

@ -75,6 +75,7 @@ class ChanNodeDetails {
public: /* Accessors */
size_t get_chan_width() const;
size_t get_track_node_id(size_t track_id) const;
std::vector<size_t> get_track_node_ids() const;
e_direction get_track_direction(size_t track_id) const;
size_t get_track_segment_length(size_t track_id) const;
size_t get_track_segment_id(size_t track_id) const;
@ -82,12 +83,13 @@ class ChanNodeDetails {
bool is_track_end(size_t track_id) const;
std::vector<size_t> get_seg_group(size_t track_id) const;
std::vector<size_t> get_seg_group_node_id(std::vector<size_t> seg_group) const;
size_t get_num_starting_tracks() const;
size_t get_num_ending_tracks() const;
size_t get_num_starting_tracks(enum e_direction track_direction) const;
size_t get_num_ending_tracks(enum e_direction track_direction) const;
public: /* Mutators */
void reserve(size_t chan_width); /* Reserve the capacitcy of vectors */
void add_track(size_t track_node_id, e_direction track_direction, size_t seg_id, size_t seg_length, size_t is_start, size_t is_end);
void set_track_node_id(size_t track_index, size_t track_node_id);
void set_track_node_ids(std::vector<size_t> track_node_ids);
void set_tracks_start(e_direction track_direction);
void set_tracks_end(e_direction track_direction);
void rotate_track_node_id(size_t offset, e_direction track_direction, bool counter_rotate); /* rotate the track_node_id by an offset */

View File

@ -254,10 +254,10 @@ std::vector<size_t> get_num_tracks_per_seg_type(const size_t chan_width,
* +---------------------------------------+--------------+
* | 10 | <--------MUX | Yes | No |
* +---------------------------------------+--------------+
* | 11 | --------> | No |
* +---------------------------------+
* | 12 | <-------- | No |
* +---------------------------------+
* | 11 | -------->MUX | No | Yes |
* +------------------------------------------------------+
* | 12 | <-------- | No | No |
* +------------------------------------------------------+
*
* 3. SPECIAL for fringes: TOP|RIGHT|BOTTOM|RIGHT
* if device_side is NUM_SIDES, we assume this channel does not locate on borders
@ -383,8 +383,9 @@ std::vector<int> get_grid_side_pins(const t_grid_tile& cur_grid,
pin_list.clear();
for (int ipin = 0; ipin < cur_grid.type->num_pins; ++ipin) {
int class_id = cur_grid.type->pin_class[ipin];
if ( (1 == cur_grid.type->pinloc[pin_height][pin_side][ipin])
&& (pin_type == cur_grid.type->pin_class[ipin]) ) {
&& (pin_type == cur_grid.type->class_inf[class_id].type) ) {
pin_list.push_back(ipin);
}
}
@ -400,24 +401,52 @@ static
size_t get_grid_num_pins(const t_grid_tile& cur_grid, const enum e_pin_type pin_type, const enum e_side io_side) {
size_t num_pins = 0;
Side io_side_manager(io_side);
/* For IO_TYPE sides */
for (size_t side = 0; side < NUM_SIDES; ++side) {
Side side_manager(side);
/* skip unwanted sides */
if ( (IO_TYPE == cur_grid.type)
&& (side != io_side_manager.to_size_t()) ) {
continue;
/* Consider capacity of the grid */
for (int iblk = 0; iblk < cur_grid.type->capacity; ++iblk) {
/* For IO_TYPE sides */
for (size_t side = 0; side < NUM_SIDES; ++side) {
Side side_manager(side);
/* skip unwanted sides */
if ( (IO_TYPE == cur_grid.type)
&& (side != io_side_manager.to_size_t()) ) {
continue;
}
/* Get pin list */
for (int height = 0; height < cur_grid.type->height; ++height) {
std::vector<int> pin_list = get_grid_side_pins(cur_grid, pin_type, side_manager.get_side(), height);
num_pins += pin_list.size();
}
}
/* Get pin list */
for (int height = 0; height < cur_grid.type->height; ++height) {
std::vector<int> pin_list = get_grid_side_pins(cur_grid, pin_type, side_manager.get_side(), height);
num_pins += pin_list.size();
}
}
return num_pins;
}
/************************************************************************
* Get the number of pins for a grid (either OPIN or IPIN)
* For IO_TYPE, only one side will be used, we consider one side of pins
* For others, we consider all the sides
***********************************************************************/
static
size_t get_grid_num_classes(const t_grid_tile& cur_grid, const enum e_pin_type pin_type) {
size_t num_classes = 0;
/* Consider capacity of the grid */
for (int iblk = 0; iblk < cur_grid.type->capacity; ++iblk) {
for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) {
/* Bypass unmatched pin_type */
if (pin_type != cur_grid.type->class_inf[iclass].type) {
continue;
}
num_classes++;
}
}
return num_classes;
}
/************************************************************************
* Estimate the number of rr_nodes per category:
* CHANX, CHANY, IPIN, OPIN, SOURCE, SINK
@ -444,8 +473,8 @@ std::vector<size_t> estimate_num_rr_nodes_per_type(const DeviceCoordinator& devi
* Note that the number of SOURCE nodes are the same as OPINs
* and the number of SINK nodes are the same as IPINs
***********************************************************************/
for (size_t ix = 0; ix < grids.size(); ++ix) {
for (size_t iy = 0; iy < grids[ix].size(); ++iy) {
for (size_t ix = 0; ix < device_size.get_x(); ++ix) {
for (size_t iy = 0; iy < device_size.get_y(); ++iy) {
/* Skip EMPTY tiles */
if (EMPTY_TYPE == grids[ix][iy].type) {
continue;
@ -465,11 +494,12 @@ std::vector<size_t> estimate_num_rr_nodes_per_type(const DeviceCoordinator& devi
num_rr_nodes_per_type[OPIN] += get_grid_num_pins(grids[ix][iy], DRIVER, io_side);
/* get the number of IPINs */
num_rr_nodes_per_type[IPIN] += get_grid_num_pins(grids[ix][iy], RECEIVER, io_side);
/* SOURCE: number of classes whose type is DRIVER */
num_rr_nodes_per_type[SOURCE] += get_grid_num_classes(grid[ix][iy], DRIVER);
/* SINK: number of classes whose type is RECEIVER */
num_rr_nodes_per_type[SINK] += get_grid_num_classes(grid[ix][iy], RECEIVER);
}
}
/* SOURCE and SINK */
num_rr_nodes_per_type[SOURCE] = num_rr_nodes_per_type[OPIN];
num_rr_nodes_per_type[SINK] = num_rr_nodes_per_type[IPIN];
/************************************************************************
* 2. Assign the segments for each routing channel,
@ -491,15 +521,18 @@ std::vector<size_t> estimate_num_rr_nodes_per_type(const DeviceCoordinator& devi
for (size_t ix = 1; ix < device_size.get_x() - 1; ++ix) {
enum e_side chan_side = NUM_SIDES;
/* For LEFT side of FPGA */
if (0 == ix) {
if (1 == ix) {
chan_side = LEFT;
}
/* For RIGHT side of FPGA */
if (grids.size() - 2 == ix) {
if (device_size.get_x() - 2 == ix) {
chan_side = RIGHT;
}
ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width[0], device_size.get_x() - 2, chan_side, segment_infs);
num_rr_nodes_per_type[CHANX] += chanx_details.get_num_starting_tracks();
/* When an INC_DIRECTION CHANX starts, we need a new rr_node */
num_rr_nodes_per_type[CHANX] += chanx_details.get_num_starting_tracks(INC_DIRECTION);
/* When an DEC_DIRECTION CHANX ends, we need a new rr_node */
num_rr_nodes_per_type[CHANX] += chanx_details.get_num_ending_tracks(DEC_DIRECTION);
}
}
@ -508,18 +541,29 @@ std::vector<size_t> estimate_num_rr_nodes_per_type(const DeviceCoordinator& devi
for (size_t iy = 1; iy < device_size.get_y() - 1; ++iy) {
enum e_side chan_side = NUM_SIDES;
/* For LEFT side of FPGA */
if (0 == iy) {
if (1 == iy) {
chan_side = BOTTOM;
}
/* For RIGHT side of FPGA */
if (grids[ix].size() - 2 == iy) {
if (device_size.get_y() - 2 == iy) {
chan_side = TOP;
}
ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width[1], device_size.get_y() - 2, chan_side, segment_infs);
num_rr_nodes_per_type[CHANY] += chany_details.get_num_starting_tracks();
/* When an INC_DIRECTION CHANX starts, we need a new rr_node */
num_rr_nodes_per_type[CHANY] += chany_details.get_num_starting_tracks(INC_DIRECTION);
/* When an DEC_DIRECTION CHANX ends, we need a new rr_node */
num_rr_nodes_per_type[CHANY] += chany_details.get_num_ending_tracks(DEC_DIRECTION);
}
}
vpr_printf(TIO_MESSAGE_INFO, "Estimate %lu SOURCE nodes.\n", num_rr_nodes_per_type[SOURCE]);
vpr_printf(TIO_MESSAGE_INFO, "Estimate %lu SINK nodes.\n", num_rr_nodes_per_type[SINK] );
vpr_printf(TIO_MESSAGE_INFO, "Estimate %lu OPIN nodes.\n", num_rr_nodes_per_type[OPIN] );
vpr_printf(TIO_MESSAGE_INFO, "Estimate %lu IPIN nodes.\n", num_rr_nodes_per_type[IPIN] );
vpr_printf(TIO_MESSAGE_INFO, "Estimate %lu CHANX nodes.\n", num_rr_nodes_per_type[CHANY] );
vpr_printf(TIO_MESSAGE_INFO, "Estimate %lu CHANY nodes.\n", num_rr_nodes_per_type[CHANY] );
return num_rr_nodes_per_type;
}
@ -554,69 +598,81 @@ void load_one_grid_rr_nodes_basic_info(const DeviceCoordinator& grid_coordinator
t_rr_graph* rr_graph,
size_t* cur_node_id,
const int wire_to_ipin_switch, const int delayless_switch) {
Side io_side_manager(io_side);
/* Walk through the height of each grid,
* get pins and configure the rr_nodes */
for (int height = 0; height < cur_grid.type->height; ++height) {
/* Walk through sides */
for (size_t side = 0; side < NUM_SIDES; ++side) {
Side side_manager(side);
/* skip unwanted sides */
if ( (IO_TYPE == cur_grid.type)
&& (side != io_side_manager.to_size_t()) ) {
continue;
}
/* Find OPINs */
/* Configure pins by pins */
std::vector<int> opin_list = get_grid_side_pins(cur_grid, DRIVER, side_manager.get_side(), height);
for (size_t pin = 0; pin < opin_list.size(); ++pin) {
/* Configure the rr_node for the OPIN */
rr_graph->rr_node[*cur_node_id].type = OPIN;
rr_graph->rr_node[*cur_node_id].xlow = grid_coordinator.get_x();
rr_graph->rr_node[*cur_node_id].xhigh = grid_coordinator.get_x();
rr_graph->rr_node[*cur_node_id].ylow = grid_coordinator.get_y();
rr_graph->rr_node[*cur_node_id].yhigh = grid_coordinator.get_y();
rr_graph->rr_node[*cur_node_id].ptc_num = opin_list[pin];
rr_graph->rr_node[*cur_node_id].capacity = 1;
rr_graph->rr_node[*cur_node_id].occ = 0;
/* cost index is a FIXED value for OPIN */
rr_graph->rr_node[*cur_node_id].cost_index = OPIN_COST_INDEX;
/* Switch info */
rr_graph->rr_node[*cur_node_id].driver_switch = delayless_switch;
/* fill fast look-up table */
load_one_node_to_rr_graph_fast_lookup(rr_graph, *cur_node_id,
rr_graph->rr_node[*cur_node_id].type,
rr_graph->rr_node[*cur_node_id].xlow,
rr_graph->rr_node[*cur_node_id].ylow,
rr_graph->rr_node[*cur_node_id].ptc_num);
/* Update node counter */
(*cur_node_id)++;
}
/* Find IPINs */
/* Configure pins by pins */
std::vector<int> ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), height);
for (size_t pin = 0; pin < ipin_list.size(); ++pin) {
rr_graph->rr_node[*cur_node_id].type = IPIN;
rr_graph->rr_node[*cur_node_id].xlow = grid_coordinator.get_x();
rr_graph->rr_node[*cur_node_id].xhigh = grid_coordinator.get_x();
rr_graph->rr_node[*cur_node_id].ylow = grid_coordinator.get_y();
rr_graph->rr_node[*cur_node_id].yhigh = grid_coordinator.get_y();
rr_graph->rr_node[*cur_node_id].ptc_num = opin_list[pin];
rr_graph->rr_node[*cur_node_id].capacity = 1;
rr_graph->rr_node[*cur_node_id].occ = 0;
/* cost index is a FIXED value for IPIN */
rr_graph->rr_node[*cur_node_id].cost_index = IPIN_COST_INDEX;
/* Switch info */
rr_graph->rr_node[*cur_node_id].driver_switch = wire_to_ipin_switch;
/* fill fast look-up table */
load_one_node_to_rr_graph_fast_lookup(rr_graph, *cur_node_id,
rr_graph->rr_node[*cur_node_id].type,
rr_graph->rr_node[*cur_node_id].xlow,
rr_graph->rr_node[*cur_node_id].ylow,
rr_graph->rr_node[*cur_node_id].ptc_num);
/* Update node counter */
(*cur_node_id)++;
}
Side io_side_manager(io_side);
/* Consider capacity of the grid */
for (int iblk = 0; iblk < cur_grid.type->capacity; ++iblk) {
/* Walk through the height of each grid,
* get pins and configure the rr_nodes */
for (int height = 0; height < cur_grid.type->height; ++height) {
/* Walk through sides */
for (size_t side = 0; side < NUM_SIDES; ++side) {
Side side_manager(side);
/* skip unwanted sides */
if ( (IO_TYPE == cur_grid.type)
&& (side != io_side_manager.to_size_t()) ) {
continue;
}
/* Find OPINs */
/* Configure pins by pins */
std::vector<int> opin_list = get_grid_side_pins(cur_grid, DRIVER, side_manager.get_side(), height);
for (size_t pin = 0; pin < opin_list.size(); ++pin) {
/* Configure the rr_node for the OPIN */
rr_graph->rr_node[*cur_node_id].type = OPIN;
rr_graph->rr_node[*cur_node_id].xlow = grid_coordinator.get_x();
rr_graph->rr_node[*cur_node_id].xhigh = grid_coordinator.get_x();
rr_graph->rr_node[*cur_node_id].ylow = grid_coordinator.get_y();
rr_graph->rr_node[*cur_node_id].yhigh = grid_coordinator.get_y();
rr_graph->rr_node[*cur_node_id].ptc_num = opin_list[pin];
rr_graph->rr_node[*cur_node_id].capacity = 1;
rr_graph->rr_node[*cur_node_id].occ = 0;
/* cost index is a FIXED value for OPIN */
rr_graph->rr_node[*cur_node_id].cost_index = OPIN_COST_INDEX;
/* Switch info */
rr_graph->rr_node[*cur_node_id].driver_switch = delayless_switch;
/* fill fast look-up table */
load_one_node_to_rr_graph_fast_lookup(rr_graph, *cur_node_id,
rr_graph->rr_node[*cur_node_id].type,
rr_graph->rr_node[*cur_node_id].xlow,
rr_graph->rr_node[*cur_node_id].ylow,
rr_graph->rr_node[*cur_node_id].ptc_num);
/* Update node counter */
(*cur_node_id)++;
} /* End of loading OPIN rr_nodes */
/* Find IPINs */
/* Configure pins by pins */
std::vector<int> ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), height);
for (size_t pin = 0; pin < ipin_list.size(); ++pin) {
rr_graph->rr_node[*cur_node_id].type = IPIN;
rr_graph->rr_node[*cur_node_id].xlow = grid_coordinator.get_x();
rr_graph->rr_node[*cur_node_id].xhigh = grid_coordinator.get_x();
rr_graph->rr_node[*cur_node_id].ylow = grid_coordinator.get_y();
rr_graph->rr_node[*cur_node_id].yhigh = grid_coordinator.get_y();
rr_graph->rr_node[*cur_node_id].ptc_num = ipin_list[pin];
rr_graph->rr_node[*cur_node_id].capacity = 1;
rr_graph->rr_node[*cur_node_id].occ = 0;
/* cost index is a FIXED value for IPIN */
rr_graph->rr_node[*cur_node_id].cost_index = IPIN_COST_INDEX;
/* Switch info */
rr_graph->rr_node[*cur_node_id].driver_switch = wire_to_ipin_switch;
/* fill fast look-up table */
load_one_node_to_rr_graph_fast_lookup(rr_graph, *cur_node_id,
rr_graph->rr_node[*cur_node_id].type,
rr_graph->rr_node[*cur_node_id].xlow,
rr_graph->rr_node[*cur_node_id].ylow,
rr_graph->rr_node[*cur_node_id].ptc_num);
/* Update node counter */
(*cur_node_id)++;
} /* End of loading IPIN rr_nodes */
} /* End of side enumeration */
} /* End of height enumeration */
} /* End of capacity enumeration */
/* Consider capacity of the grid */
for (int iblk = 0; iblk < cur_grid.type->capacity; ++iblk) {
/* Walk through the height of each grid,
* get pins and configure the rr_nodes */
for (int height = 0; height < cur_grid.type->height; ++height) {
/* Set a SOURCE or a SINK rr_node for each class */
for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) {
/* Set a SINK rr_node for the OPIN */
@ -815,6 +871,10 @@ void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
if (EMPTY_TYPE == grids[ix][iy].type) {
continue;
}
/* We only build rr_nodes for grids with offset=0 */
if (0 < grids[ix][iy].offset) {
continue;
}
DeviceCoordinator grid_coordinator(ix, iy);
enum e_side io_side = NUM_SIDES;
/* If this is the block on borders, we consider IO side */
@ -829,13 +889,29 @@ void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
}
}
/* FIXME: DEBUG CODES TO BE REMOVED
std::vector<size_t> node_cnt;
node_cnt.resize(NUM_RR_TYPES);
for (int inode = 0; inode < rr_graph->num_rr_nodes; ++inode) {
node_cnt[rr_graph->rr_node[inode].type]++;
}
vpr_printf(TIO_MESSAGE_INFO, "Load basic information to %lu SOURCE NODE.\n", node_cnt[SOURCE]);
vpr_printf(TIO_MESSAGE_INFO, "Load basic information to %lu SINK NODE.\n", node_cnt[SINK]);
vpr_printf(TIO_MESSAGE_INFO, "Load basic information to %lu OPIN NODE.\n", node_cnt[OPIN]);
vpr_printf(TIO_MESSAGE_INFO, "Load basic information to %lu IPIN NODE.\n", node_cnt[IPIN]);
*/
/* For X-direction Channel: CHANX */
for (size_t iy = 0; iy < device_size.get_y() - 1; ++iy) {
/* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */
std::vector<size_t> track_node_ids;
/* Make sure a clean start */
track_node_ids.clear();
for (size_t ix = 1; ix < device_size.get_x() - 1; ++ix) {
DeviceCoordinator chan_coordinator(ix, iy);
enum e_side chan_side = NUM_SIDES;
/* For LEFT side of FPGA */
if (0 == ix) {
if (1 == ix) {
chan_side = LEFT;
}
/* For RIGHT side of FPGA */
@ -843,37 +919,47 @@ void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
chan_side = RIGHT;
}
ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width[0], device_size.get_x() - 2, chan_side, segment_infs);
/* Configure CHANX in this channel */
load_one_chan_rr_nodes_basic_info(chan_coordinator, CHANX,
&chanx_details,
segment_infs,
CHANX_COST_INDEX_START,
rr_graph, &cur_node_id);
/* Rotate the chanx_details by an offset of 1*/
/* Force node_ids from the previous chanx */
if (0 < track_node_ids.size()) {
chanx_details.set_track_node_ids(track_node_ids);
}
/* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */
/* For INC_DIRECTION, we use clockwise rotation
* node_id A ----> -----> node_id D
* node_id B ----> / ----> node_id A
* node_id C ----> / ----> node_id B
* node_id D ----> ----> node_id C
*/
chanx_details.rotate_track_node_id(1, INC_DIRECTION, false);
chanx_details.rotate_track_node_id(ix - 1, INC_DIRECTION, false);
/* For DEC_DIRECTION, we use clockwise rotation
* node_id A <----- <----- node_id B
* node_id B <----- \ <----- node_id C
* node_id C <----- \ <----- node_id D
* node_id D <----- <----- node_id A
*/
chanx_details.rotate_track_node_id(1, DEC_DIRECTION, true);
chanx_details.rotate_track_node_id(ix - 1, DEC_DIRECTION, true);
/* Configure CHANX in this channel */
load_one_chan_rr_nodes_basic_info(chan_coordinator, CHANX,
&chanx_details,
segment_infs,
CHANX_COST_INDEX_START,
rr_graph, &cur_node_id);
/* Get a copy of node_ids */
track_node_ids = chanx_details.get_track_node_ids();
}
}
/* For Y-direction Channel: CHANX */
for (size_t ix = 0; ix < device_size.get_x() - 1; ++ix) {
/* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */
std::vector<size_t> track_node_ids;
/* Make sure a clean start */
track_node_ids.clear();
for (size_t iy = 1; iy < device_size.get_y() - 1; ++iy) {
DeviceCoordinator chan_coordinator(ix, iy);
enum e_side chan_side = NUM_SIDES;
/* For LEFT side of FPGA */
if (0 == iy) {
if (1 == iy) {
chan_side = BOTTOM;
}
/* For RIGHT side of FPGA */
@ -881,12 +967,10 @@ void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
chan_side = TOP;
}
ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width[1], device_size.get_y() - 2, chan_side, segment_infs);
/* Configure CHANX in this channel */
load_one_chan_rr_nodes_basic_info(chan_coordinator, CHANY,
&chany_details,
segment_infs,
CHANX_COST_INDEX_START + segment_infs.size(),
rr_graph, &cur_node_id);
/* Force node_ids from the previous chanx */
if (0 < track_node_ids.size()) {
chany_details.set_track_node_ids(track_node_ids);
}
/* Rotate the chany_details by an offset of 1*/
/* For INC_DIRECTION, we use clockwise rotation
* node_id A ----> -----> node_id D
@ -894,14 +978,22 @@ void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
* node_id C ----> / ----> node_id B
* node_id D ----> ----> node_id C
*/
chany_details.rotate_track_node_id(1, INC_DIRECTION, false);
chany_details.rotate_track_node_id(iy - 1, INC_DIRECTION, false);
/* For DEC_DIRECTION, we use clockwise rotation
* node_id A <----- <----- node_id B
* node_id B <----- \ <----- node_id C
* node_id C <----- \ <----- node_id D
* node_id D <----- <----- node_id A
*/
chany_details.rotate_track_node_id(1, DEC_DIRECTION, true);
chany_details.rotate_track_node_id(iy - 1, DEC_DIRECTION, true);
/* Configure CHANX in this channel */
load_one_chan_rr_nodes_basic_info(chan_coordinator, CHANY,
&chany_details,
segment_infs,
CHANX_COST_INDEX_START + segment_infs.size(),
rr_graph, &cur_node_id);
/* Get a copy of node_ids */
track_node_ids = chany_details.get_track_node_ids();
}
}
@ -1005,13 +1097,13 @@ void build_rr_graph_edges(t_rr_graph* rr_graph,
/* adapt the track_to_ipin_lookup for the GSB nodes */
t_track2pin_map track2ipin_map; /* [0..track_gsb_side][0..num_tracks][ipin_indices] */
/* Get the Fc index of the grid */
int grid_Fc_in_index = grids[grid_coordinator.get_x()][grid_coordinator.get_x()].type->index;
int grid_Fc_in_index = grids[grid_coordinator.get_x()][grid_coordinator.get_y()].type->index;
track2ipin_map = build_gsb_track_to_ipin_map(rr_graph, rr_gsb, segment_inf, Fc_in[grid_Fc_in_index]);
/* adapt the opin_to_track_map for the GSB nodes */
t_pin2track_map opin2track_map; /* [0..gsb_side][0..num_opin_node][track_indices] */
/* Get the Fc index of the grid */
int grid_Fc_out_index = grids[grid_coordinator.get_x()][grid_coordinator.get_x()].type->index;
int grid_Fc_out_index = grids[grid_coordinator.get_x()][grid_coordinator.get_y()].type->index;
opin2track_map = build_gsb_opin_to_track_map(rr_graph, rr_gsb, segment_inf, Fc_out[grid_Fc_out_index]);
/* adapt the switch_block_conn for the GSB nodes */
@ -1019,7 +1111,7 @@ void build_rr_graph_edges(t_rr_graph* rr_graph,
sb_conn = build_gsb_track_to_track_map(rr_graph, rr_gsb, sb_type, Fs, segment_inf);
/* Build edges for a GSB */
build_edges_for_one_tileable_rr_gsb(rr_graph, &rr_gsb,
build_edges_for_one_tileable_rr_gsb(rr_graph, grids, &rr_gsb,
track2ipin_map, opin2track_map,
sb_conn);
/* Finish this GSB, go to the next*/
@ -1218,9 +1310,6 @@ void build_tileable_unidir_rr_graph(INP const int L_num_types,
*Warnings |= RR_GRAPH_WARN_FC_CLIPPED;
}
vpr_printf(TIO_MESSAGE_INFO,
"Actual Fc numbers loaded.\n");
/************************************************************************
* 6. Build the connections tile by tile:
* We classify rr_nodes into a general switch block (GSB) data structure
@ -1235,9 +1324,6 @@ void build_tileable_unidir_rr_graph(INP const int L_num_types,
Fc_in, Fc_out,
sb_type, Fs);
vpr_printf(TIO_MESSAGE_INFO,
"Regular edges of RR graph built.\n");
/************************************************************************
* 7. Build direction connection lists
***********************************************************************/
@ -1249,8 +1335,12 @@ void build_tileable_unidir_rr_graph(INP const int L_num_types,
build_rr_graph_direct_connections(&rr_graph, device_size, grids, delayless_switch,
num_directs, directs, clb_to_clb_directs);
size_t num_edges = 0;
for (int inode = 0; inode < rr_graph.num_rr_nodes; ++inode) {
num_edges += rr_graph.rr_node[inode].num_edges;
}
vpr_printf(TIO_MESSAGE_INFO,
"Direct-connection edges of RR graph built.\n");
"%lu edges of RR graph built.\n", num_edges);
/************************************************************************
* 8. Allocate external data structures

View File

@ -131,8 +131,8 @@ bool is_gsb_in_track_cb_population(const RRGSB& rr_gsb,
DeviceCoordinator side_coordinator = rr_gsb.get_side_block_coordinator(gsb_side);
/* Get the offset */
size_t offset = (side_coordinator.get_x() - track_node->xlow)
+ (side_coordinator.get_y() - track_node->ylow);
size_t offset = std::abs((int)side_coordinator.get_x() - track_node->xlow)
+ std::abs((int)side_coordinator.get_y() - track_node->ylow);
/* Get segment id */
size_t seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id);
@ -170,8 +170,8 @@ bool is_gsb_in_track_sb_population(const RRGSB& rr_gsb,
DeviceCoordinator side_coordinator = rr_gsb.get_side_block_coordinator(gsb_side);
/* Get the offset */
size_t offset = (side_coordinator.get_x() - track_node->xlow)
+ (side_coordinator.get_y() - track_node->ylow);
size_t offset = std::abs((int)side_coordinator.get_x() - track_node->xlow)
+ std::abs((int)side_coordinator.get_y() - track_node->ylow);
/* Get segment id */
size_t seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id);
@ -198,9 +198,9 @@ std::vector<size_t> get_to_track_list(const int Fs, const int to_track, const in
/* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied
* The optimal track selection should be done in a more scientific way!!!
*/
size_t to_track_i = to_track + i;
int to_track_i = to_track + i;
/* make sure the track id is still in range */
if ( to_track_i > (size_t)num_to_tracks) {
if ( to_track_i > num_to_tracks) {
to_track_i = to_track_i % num_to_tracks;
}
/* from track must be connected */
@ -368,6 +368,9 @@ void build_gsb_one_group_track_to_track_map(const t_rr_graph* rr_graph,
size_t from_side_index = side_manager.to_size_t();
size_t from_track_index = from_tracks[side][inode];
size_t to_track_index = to_tracks[to_side_index][to_track_ids[to_track_id]];
printf("from_track(size=%lu): %lu , to_track_ids[%lu]:%lu, to_track_index: %lu in a group of %lu tracks\n",
from_tracks[side].size(), inode, to_track_id, to_track_ids[to_track_id],
to_track_index, to_tracks[to_side_index].size());
t_rr_node* to_track_node = rr_gsb.get_chan_node(to_side, to_track_index);
(*track2track_map)[from_side_index][from_track_index].push_back(to_track_node - rr_graph->rr_node);
}
@ -453,11 +456,11 @@ t_track2track_map build_gsb_track_to_track_map(const t_rr_graph* rr_graph,
switch (track_status) {
case TRACK_START:
/* update starting track list */
start_tracks[gsb_side].push_back(inode);
start_tracks[side].push_back(inode);
break;
case TRACK_END:
/* Update end track list */
end_tracks[gsb_side].push_back(inode);
end_tracks[side].push_back(inode);
break;
case TRACK_PASS:
/* We need to check Switch block population of this track
@ -465,7 +468,7 @@ t_track2track_map build_gsb_track_to_track_map(const t_rr_graph* rr_graph,
*/
if (true == is_gsb_in_track_sb_population(rr_gsb, gsb_side, inode, segment_inf)) {
/* Update passing track list */
pass_tracks[gsb_side].push_back(inode);
pass_tracks[side].push_back(inode);
}
break;
default:
@ -917,6 +920,17 @@ void add_one_edge_for_two_rr_nodes(const t_rr_graph* rr_graph,
return;
}
/************************************************************************
* Get the class index of a grid pin
***********************************************************************/
static
int get_grid_pin_class_index(const t_grid_tile& cur_grid,
const int pin_index) {
/* check */
assert ( pin_index < cur_grid.type->num_pins);
return cur_grid.type->pin_class[pin_index];
}
/************************************************************************
* Create edges for each rr_node of a General Switch Blocks (GSB):
* 1. create edges between SOURCE and OPINs
@ -925,7 +939,9 @@ void add_one_edge_for_two_rr_nodes(const t_rr_graph* rr_graph,
* 4. create edges between OPINs, CHANX and CHANY (connections inside switch blocks)
* 5. create edges between OPINs and IPINs (direct-connections)
***********************************************************************/
void build_edges_for_one_tileable_rr_gsb(const t_rr_graph* rr_graph, const RRGSB* rr_gsb,
void build_edges_for_one_tileable_rr_gsb(const t_rr_graph* rr_graph,
const std::vector< std::vector<t_grid_tile> > grids,
const RRGSB* rr_gsb,
const t_track2pin_map track2ipin_map,
const t_pin2track_map opin2track_map,
const t_track2track_map track2track_map) {
@ -940,9 +956,10 @@ void build_edges_for_one_tileable_rr_gsb(const t_rr_graph* rr_graph, const RRGSB
/* Find OPINs */
for (size_t inode = 0; inode < rr_gsb->get_num_opin_nodes(gsb_side); ++inode) {
t_rr_node* opin_node = rr_gsb->get_opin_node(gsb_side, inode);
int src_node_ptc_num = get_grid_pin_class_index(grids[opin_node->xlow][opin_node->ylow], opin_node->ptc_num);
/* 1. create edges between SOURCE and OPINs */
int src_node_id = get_rr_node_index(opin_node->xlow, opin_node->ylow,
SOURCE, opin_node->ptc_num,
SOURCE, src_node_ptc_num,
rr_graph->rr_node_indices);
/* add edges to the src_node */
add_one_edge_for_two_rr_nodes(rr_graph, src_node_id, opin_node - rr_graph->rr_node,
@ -960,27 +977,38 @@ void build_edges_for_one_tileable_rr_gsb(const t_rr_graph* rr_graph, const RRGSB
/* Find IPINs */
for (size_t inode = 0; inode < rr_gsb->get_num_ipin_nodes(gsb_side); ++inode) {
t_rr_node* ipin_node = rr_gsb->get_ipin_node(gsb_side, inode);
int sink_node_ptc_num = get_grid_pin_class_index(grids[ipin_node->xlow][ipin_node->ylow], ipin_node->ptc_num);
/* 3. create edges between IPINs and SINKs */
int sink_node_id = get_rr_node_index(ipin_node->xlow, ipin_node->ylow,
SINK, ipin_node->ptc_num,
SINK, sink_node_ptc_num,
rr_graph->rr_node_indices);
/* add edges to connect the IPIN node to SINK nodes */
add_one_edge_for_two_rr_nodes(rr_graph, ipin_node - rr_graph->rr_node, sink_node_id,
rr_graph->rr_node[sink_node_id].driver_switch);
}
/* Find CHANX or CHANY */
/* For TRACKs to IPINs, we only care LEFT and TOP sides
* Skip RIGHT and BOTTOM for the ipin2track_map since they should be handled in other GSBs
*/
if ( (side_manager.get_side() == rr_gsb->get_cb_chan_side(CHANX))
|| (side_manager.get_side() == rr_gsb->get_cb_chan_side(CHANY)) ) {
/* 4. create edges between CHANX|CHANY and IPINs, using ipin2track_map */
for (size_t inode = 0; inode < rr_gsb->get_chan_width(gsb_side); ++inode) {
t_rr_node* chan_node = rr_gsb->get_chan_node(gsb_side, inode);
int num_edges = track2ipin_map[side_manager.to_size_t()][inode].size();
for (int iedge = 0; iedge < num_edges; ++iedge) {
int ipin_node_id = track2ipin_map[side_manager.to_size_t()][inode][iedge];
/* add edges to the chan_node */
add_one_edge_for_two_rr_nodes(rr_graph, chan_node - rr_graph->rr_node, ipin_node_id,
rr_graph->rr_node[ipin_node_id].driver_switch);
}
}
}
/* 5. create edges between CHANX|CHANY and CHANX|CHANY, using track2track_map */
for (size_t inode = 0; inode < rr_gsb->get_chan_width(gsb_side); ++inode) {
t_rr_node* chan_node = rr_gsb->get_chan_node(gsb_side, inode);
/* 4. create edges between CHANX|CHANY and IPINs, using ipin2track_map */
int num_edges = track2ipin_map[side_manager.to_size_t()][inode].size();
for (int iedge = 0; iedge < num_edges; ++iedge) {
int ipin_node_id = track2ipin_map[side_manager.to_size_t()][inode][iedge];
/* add edges to the chan_node */
add_one_edge_for_two_rr_nodes(rr_graph, chan_node - rr_graph->rr_node, ipin_node_id,
rr_graph->rr_node[ipin_node_id].driver_switch);
}
/* 5. create edges between CHANX|CHANY and CHANX|CHANY, using track2track_map */
num_edges = track2track_map[side_manager.to_size_t()][inode].size();
int num_edges = track2track_map[side_manager.to_size_t()][inode].size();
for (int iedge = 0; iedge < num_edges; ++iedge) {
int track_node_id = track2track_map[side_manager.to_size_t()][inode][iedge];
/* add edges to the chan_node */
@ -1015,6 +1043,7 @@ void build_gsb_one_ipin_track2pin_map(const t_rr_graph* rr_graph,
t_track2pin_map* track2ipin_map) {
/* Get a list of segment_ids*/
enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side);
Side chan_side_manager(chan_side);
std::vector<size_t> seg_list = rr_gsb.get_chan_segment_ids(chan_side);
size_t chan_width = rr_gsb.get_chan_width(chan_side);
Side ipin_side_manager(ipin_side);
@ -1058,11 +1087,11 @@ void build_gsb_one_ipin_track2pin_map(const t_rr_graph* rr_graph,
/* Assign tracks: since we assign 2 track per round, we increment itrack by 2* step */
for (size_t itrack = 0; itrack < actual_track_list.size(); itrack = itrack + 2 * track_step) {
/* Update pin2track map */
size_t ipin_side_index = ipin_side_manager.to_size_t();
size_t chan_side_index = chan_side_manager.to_size_t();
size_t track_index = actual_track_list[itrack];
size_t ipin_index = ipin_node - rr_graph->rr_node;
(*track2ipin_map)[ipin_side_index][track_index].push_back(ipin_index);
(*track2ipin_map)[ipin_side_index][track_index + 1].push_back(ipin_index);
(*track2ipin_map)[chan_side_index][track_index].push_back(ipin_index);
(*track2ipin_map)[chan_side_index][track_index + 1].push_back(ipin_index);
}
}
@ -1181,14 +1210,15 @@ t_track2pin_map build_gsb_track_to_ipin_map(t_rr_graph* rr_graph,
/* This track2pin mapping is for Connection Blocks, so we only care two sides! */
/* Get channel width and resize the matrix */
size_t chan_width = rr_gsb.get_chan_width(chan_side);
track2ipin_map[side].resize(chan_width);
track2ipin_map[chan_side_manager.to_size_t()].resize(chan_width);
/* Find the ipin/opin nodes */
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(ipin_side); ++inode) {
t_rr_node* ipin_node = rr_gsb.get_ipin_node(ipin_side, inode);
/* Get Fc of the ipin */
int ipin_Fc = Fc_in[ipin_node->ptc_num];
/* skip Fc = 0 */
if (0 == ipin_Fc) {
if ( (-1 == ipin_Fc)
|| (0 == ipin_Fc) ) {
continue;
}
/* Build track2ipin_map for this IPIN */
@ -1249,7 +1279,9 @@ t_pin2track_map build_gsb_opin_to_track_map(t_rr_graph* rr_graph,
/* Get Fc of the ipin */
int opin_Fc = Fc_out[opin_node->ptc_num];
/* skip Fc = 0 */
if (0 == opin_Fc) {
printf("opin_Fc[%d]=%d\n", opin_node->ptc_num, opin_Fc);
if ( (-1 == opin_Fc)
|| (0 == opin_Fc) ) {
continue;
}
/* Build track2ipin_map for this IPIN */

View File

@ -31,7 +31,9 @@ RRGSB build_one_tileable_rr_gsb(const DeviceCoordinator& device_range,
const DeviceCoordinator& gsb_coordinator,
t_rr_graph* rr_graph);
void build_edges_for_one_tileable_rr_gsb(const t_rr_graph* rr_graph, const RRGSB* rr_gsb,
void build_edges_for_one_tileable_rr_gsb(const t_rr_graph* rr_graph,
const std::vector< std::vector<t_grid_tile> > grids,
const RRGSB* rr_gsb,
const t_track2pin_map track2ipin_map,
const t_pin2track_map opin2track_map,
const t_track2track_map track2track_map);

View File

@ -692,6 +692,9 @@ alloc_and_load_actual_fc(INP int L_num_types, INP t_type_ptr types,
float *Fc = (float *) my_malloc(sizeof(float) * types[i].num_pins); /* [0..num_pins-1] */
for (j = 0; j < types[i].num_pins; ++j) {
Fc[j] = types[i].Fc[j];
/* Xifan Tang: give an initial value! */
/* Result[i][j] = 0; */
if(Fc[j] == 0 && ignore_Fc_0 == FALSE) {
/* Special case indicating that this pin does not connect to general-purpose routing */