set chan_rr_nodes in tileable rr_graph builder
This commit is contained in:
parent
8c9cc003ea
commit
1af3b5ef55
|
@ -184,6 +184,12 @@ void ChanNodeDetails::add_track(size_t track_node_id, e_direction track_directio
|
|||
track_end_.push_back(is_end);
|
||||
}
|
||||
|
||||
/* Update the node_id of a given track */
|
||||
void ChanNodeDetails::set_track_node_id(size_t track_index, size_t track_node_id) {
|
||||
assert(validate_track_id(track_index));
|
||||
track_node_ids_[track_index] = track_node_id;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
|
@ -205,7 +211,7 @@ 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, bool counter_rotate) {
|
||||
void ChanNodeDetails::rotate_track_node_id(size_t offset, e_direction track_direction, bool counter_rotate) {
|
||||
/* Rotate the node_ids by groups
|
||||
* A group begins from a track_start and ends before another track_start
|
||||
*/
|
||||
|
@ -215,6 +221,10 @@ void ChanNodeDetails::rotate_track_node_id(size_t offset, bool counter_rotate) {
|
|||
if (false == is_track_start(itrack) ) {
|
||||
continue;
|
||||
}
|
||||
/* Bypass segments do not match track_direction */
|
||||
if (track_direction != get_track_direction(itrack) ) {
|
||||
continue;
|
||||
}
|
||||
/* Find the group nodes */
|
||||
std::vector<size_t> track_group = get_seg_group(itrack);
|
||||
/* Build a vector of the node ids of the tracks */
|
||||
|
|
|
@ -86,9 +86,10 @@ class ChanNodeDetails {
|
|||
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_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_tracks_start(e_direction track_direction);
|
||||
void set_tracks_end(e_direction track_direction);
|
||||
void rotate_track_node_id(size_t offset, bool counter_rotate); /* rotate the track_node_id by an offset */
|
||||
void rotate_track_node_id(size_t offset, e_direction track_direction, bool counter_rotate); /* rotate the track_node_id by an offset */
|
||||
void clear();
|
||||
private: /* validators */
|
||||
bool validate_chan_width() const;
|
||||
|
|
|
@ -218,29 +218,29 @@ std::vector<size_t> get_num_tracks_per_seg_type(size_t chan_width,
|
|||
* But still the rr_graph is tileable, which is the first concern!
|
||||
*
|
||||
* Here is a quick example of Length-4 wires in a W=12 routing channel
|
||||
* +---------------------------------+
|
||||
* | Index | Direction | Start Point |
|
||||
* +---------------------------------+
|
||||
* | 0 | --------> | Yes |
|
||||
* +---------------------------------+
|
||||
* | 1 | <-------- | Yes |
|
||||
* +---------------------------------+
|
||||
* | 2 | --------> | No |
|
||||
* +---------------------------------+
|
||||
* | 3 | <-------- | No |
|
||||
* +---------------------------------+
|
||||
* | 4 | --------> | No |
|
||||
* +---------------------------------+
|
||||
* | 5 | <-------- | No |
|
||||
* +---------------------------------+
|
||||
* | 7 | --------> | No |
|
||||
* +---------------------------------+
|
||||
* | 8 | <-------- | No |
|
||||
* +---------------------------------+
|
||||
* | 9 | --------> | Yes |
|
||||
* +---------------------------------+
|
||||
* | 10 | <-------- | Yes |
|
||||
* +---------------------------------+
|
||||
* +---------------------------------------+--------------+
|
||||
* | Index | Direction | Starting Point | Ending Point |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 0 | MUX--------> | Yes | No |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 1 | <--------MUX | Yes | No |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 2 | --------> | No | No |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 3 | <-------- | No | No |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 4 | --------> | No | No |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 5 | <-------- | No | No |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 7 | -------->MUX | No | Yes |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 8 | MUX<-------- | No | Yes |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 9 | MUX--------> | Yes | No |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 10 | <--------MUX | Yes | No |
|
||||
* +---------------------------------------+--------------+
|
||||
* | 11 | --------> | No |
|
||||
* +---------------------------------+
|
||||
* | 12 | <-------- | No |
|
||||
|
@ -285,16 +285,21 @@ ChanNodeDetails build_unidir_chan_node_details(size_t chan_width, size_t max_seg
|
|||
}
|
||||
for (size_t itrack = 0; itrack < num_tracks[iseg]; ++itrack) {
|
||||
bool seg_start = false;
|
||||
/* Every length of wire, we set a starting point */
|
||||
bool seg_end = false;
|
||||
/* Every first track of a group of Length-N wires, we set a starting point */
|
||||
if (0 == itrack % seg_len) {
|
||||
seg_start = true;
|
||||
}
|
||||
/* Every last track of a group of Length-N wires, we set an ending point */
|
||||
if (seg_len - 1 == itrack % seg_len) {
|
||||
seg_end = true;
|
||||
}
|
||||
/* Since this is a unidirectional routing architecture,
|
||||
* Add a pair of tracks, 1 INC_DIRECTION track and 1 DEC_DIRECTION track
|
||||
*/
|
||||
chan_node_details.add_track(cur_track, INC_DIRECTION, seg_len, seg_start, false);
|
||||
chan_node_details.add_track(cur_track, INC_DIRECTION, seg_len, seg_start, seg_end);
|
||||
cur_track++;
|
||||
chan_node_details.add_track(cur_track, DEC_DIRECTION, seg_len, seg_start, false);
|
||||
chan_node_details.add_track(cur_track, DEC_DIRECTION, seg_len, seg_start, seg_end);
|
||||
cur_track++;
|
||||
}
|
||||
}
|
||||
|
@ -535,6 +540,7 @@ void load_one_grid_rr_nodes_basic_info(const DeviceCoordinator& grid_coordinator
|
|||
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;
|
||||
/* Update node counter */
|
||||
(*cur_node_id)++;
|
||||
/* Set a SOURCE rr_node for the OPIN */
|
||||
rr_graph->rr_node[*cur_node_id].type = SOURCE;
|
||||
|
@ -546,6 +552,7 @@ void load_one_grid_rr_nodes_basic_info(const DeviceCoordinator& grid_coordinator
|
|||
rr_graph->rr_node[*cur_node_id].capacity = 1;
|
||||
rr_graph->rr_node[*cur_node_id].occ = 0;
|
||||
/* TODO: should we set pb_graph_pin here? */
|
||||
/* Update node counter */
|
||||
(*cur_node_id)++;
|
||||
}
|
||||
/* Find IPINs */
|
||||
|
@ -560,6 +567,7 @@ void load_one_grid_rr_nodes_basic_info(const DeviceCoordinator& grid_coordinator
|
|||
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;
|
||||
/* Update node counter */
|
||||
(*cur_node_id)++;
|
||||
/* Set a SINK rr_node for the OPIN */
|
||||
rr_graph->rr_node[*cur_node_id].type = SINK;
|
||||
|
@ -571,6 +579,7 @@ void load_one_grid_rr_nodes_basic_info(const DeviceCoordinator& grid_coordinator
|
|||
rr_graph->rr_node[*cur_node_id].capacity = 1;
|
||||
rr_graph->rr_node[*cur_node_id].occ = 0;
|
||||
/* TODO: should we set pb_graph_pin here? */
|
||||
/* Update node counter */
|
||||
(*cur_node_id)++;
|
||||
}
|
||||
}
|
||||
|
@ -587,9 +596,54 @@ void load_one_grid_rr_nodes_basic_info(const DeviceCoordinator& grid_coordinator
|
|||
static
|
||||
void load_one_chan_rr_nodes_basic_info(const DeviceCoordinator& chan_coordinator,
|
||||
t_rr_type chan_type,
|
||||
const ChanNodeDetails& chan_details,
|
||||
ChanNodeDetails* chan_details,
|
||||
t_rr_graph* rr_graph,
|
||||
size_t* cur_node_id) {
|
||||
/* Check each node_id(potential ptc_num) in the channel :
|
||||
* If this is a starting point, we set a new rr_node with xlow/ylow, ptc_num
|
||||
* If this is a ending point, we set xhigh/yhigh and track_ids
|
||||
* For other nodes, we set changes in track_ids
|
||||
*/
|
||||
for (size_t itrack = 0; itrack < chan_details->get_chan_width(); ++itrack) {
|
||||
if (true == chan_details->is_track_start(itrack)) {
|
||||
/* Use a new chan rr_node */
|
||||
rr_graph->rr_node[*cur_node_id].type = chan_type;
|
||||
rr_graph->rr_node[*cur_node_id].xlow = chan_coordinator.get_x();
|
||||
rr_graph->rr_node[*cur_node_id].ylow = chan_coordinator.get_y();
|
||||
rr_graph->rr_node[*cur_node_id].direction = chan_details->get_track_direction(itrack);
|
||||
rr_graph->rr_node[*cur_node_id].ptc_num = itrack;
|
||||
rr_graph->rr_node[*cur_node_id].track_ids.push_back(itrack);
|
||||
rr_graph->rr_node[*cur_node_id].capacity = 1;
|
||||
rr_graph->rr_node[*cur_node_id].occ = 0;
|
||||
/* Update chan_details with node_id */
|
||||
chan_details->set_track_node_id(itrack, *cur_node_id);
|
||||
/* Update node counter */
|
||||
(*cur_node_id)++;
|
||||
/* Finish here, go to next */
|
||||
continue;
|
||||
}
|
||||
if (true == chan_details->is_track_end(itrack)) {
|
||||
/* Get the node_id */
|
||||
size_t rr_node_id = chan_details->get_track_node_id(itrack);
|
||||
/* Do a quick check, make sure we do not mistakenly modify other nodes */
|
||||
assert(chan_type == rr_graph->rr_node[rr_node_id].type);
|
||||
assert(chan_details->get_track_direction(itrack) == rr_graph->rr_node[rr_node_id].type);
|
||||
/* set xhigh/yhigh and push changes to track_ids */
|
||||
rr_graph->rr_node[rr_node_id].xhigh = chan_coordinator.get_x();
|
||||
rr_graph->rr_node[rr_node_id].yhigh = chan_coordinator.get_y();
|
||||
rr_graph->rr_node[rr_node_id].track_ids.push_back(itrack);
|
||||
/* Finish here, go to next */
|
||||
continue;
|
||||
}
|
||||
/* For other nodes, we get the node_id and just update track_ids */
|
||||
/* Get the node_id */
|
||||
size_t rr_node_id = chan_details->get_track_node_id(itrack);
|
||||
/* Do a quick check, make sure we do not mistakenly modify other nodes */
|
||||
assert(chan_type == rr_graph->rr_node[rr_node_id].type);
|
||||
assert(chan_details->get_track_direction(itrack) == rr_graph->rr_node[rr_node_id].type);
|
||||
rr_graph->rr_node[rr_node_id].track_ids.push_back(itrack);
|
||||
/* Finish here, go to next */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -616,8 +670,8 @@ void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
|
|||
* 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;
|
||||
|
@ -636,8 +690,8 @@ void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
|
|||
}
|
||||
|
||||
/* For X-direction Channel: CHANX */
|
||||
for (size_t ix = 0; ix < grids.size() - 1; ++ix) {
|
||||
for (size_t iy = 0; iy < grids[ix].size() - 1; ++iy) {
|
||||
for (size_t iy = 0; iy < device_size.get_y() - 1; ++iy) {
|
||||
for (size_t ix = 0; ix < device_size.get_x() - 1; ++ix) {
|
||||
DeviceCoordinator chan_coordinator(ix, iy);
|
||||
enum e_side chan_side = NUM_SIDES;
|
||||
/* For LEFT side of FPGA */
|
||||
|
@ -645,19 +699,34 @@ void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
|
|||
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);
|
||||
/* Configure CHANX in this channel */
|
||||
load_one_chan_rr_nodes_basic_info(chan_coordinator, CHANX, chanx_details,
|
||||
load_one_chan_rr_nodes_basic_info(chan_coordinator, CHANX, &chanx_details,
|
||||
rr_graph, &cur_node_id);
|
||||
/* Rotate the chanx_details by an offset of 1*/
|
||||
/* 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);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* For Y-direction Channel: CHANX */
|
||||
for (size_t ix = 0; ix < grids.size() - 1; ++ix) {
|
||||
for (size_t iy = 0; iy < grids[ix].size() - 1; ++iy) {
|
||||
for (size_t ix = 0; ix < device_size.get_x() - 1; ++ix) {
|
||||
for (size_t iy = 0; iy < device_size.get_y() - 1; ++iy) {
|
||||
DeviceCoordinator chan_coordinator(ix, iy);
|
||||
enum e_side chan_side = NUM_SIDES;
|
||||
/* For LEFT side of FPGA */
|
||||
|
@ -665,13 +734,28 @@ void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
|
|||
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);
|
||||
/* Configure CHANX in this channel */
|
||||
load_one_chan_rr_nodes_basic_info(chan_coordinator, CHANY, chany_details,
|
||||
load_one_chan_rr_nodes_basic_info(chan_coordinator, CHANY, &chany_details,
|
||||
rr_graph, &cur_node_id);
|
||||
/* Rotate the chany_details by an offset of 1*/
|
||||
/* 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
|
||||
*/
|
||||
chany_details.rotate_track_node_id(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue