basically finished the coding of tileable rr_graph generator. testing to go

This commit is contained in:
tangxifan 2019-06-20 18:17:07 -06:00
parent e7f2bd3b7c
commit baab9c4a21
16 changed files with 1596 additions and 1282 deletions

View File

@ -56,26 +56,24 @@
#include "ReadOptions.h"
#include "rr_graph.h"
#include "rr_graph2.h"
#include "check_rr_graph.h"
#include "route_common.h"
#include "fpga_x2p_types.h"
#include "rr_graph_tileable_builder.h"
#include "fpga_x2p_backannotate_utils.h"
#include "my_free_fwd.h"
#include "rr_blocks.h"
#include "chan_node_details.h"
#include "device_coordinator.h"
#include "rr_graph_tileable_sbox.h"
#include "rr_graph_tileable_gsb.h"
/************************************************************************
* Local data stuctures in the file
***********************************************************************/
typedef std::vector<std::vector<std::vector<int>>> t_track2pin_map;
typedef std::vector<std::vector<std::vector<int>>> t_pin2track_map;
/************************************************************************
* Local function in the file
***********************************************************************/
/************************************************************************
* Initialize a rr_node
************************************************************************/
@ -153,9 +151,9 @@ void tileable_rr_graph_init_rr_node(t_rr_node* cur_rr_node) {
* In this way, we can assign the number of tracks with repect to frequency
***********************************************************************/
static
std::vector<size_t> get_num_tracks_per_seg_type(size_t chan_width,
std::vector<t_segment_inf> segment_inf,
bool use_full_seg_groups) {
std::vector<size_t> get_num_tracks_per_seg_type(const size_t chan_width,
const std::vector<t_segment_inf> segment_inf,
const bool use_full_seg_groups) {
std::vector<size_t> result;
std::vector<double> demand;
/* Make sure a clean start */
@ -269,26 +267,26 @@ std::vector<size_t> get_num_tracks_per_seg_type(size_t chan_width,
* in X-direction and Y-direction channels!!!
* So we will load segment details for different channels
***********************************************************************/
static
ChanNodeDetails build_unidir_chan_node_details(size_t chan_width, size_t max_seg_length,
enum e_side device_side,
std::vector<t_segment_inf> segment_inf) {
ChanNodeDetails build_unidir_chan_node_details(const size_t chan_width, const size_t max_seg_length,
const enum e_side device_side,
const std::vector<t_segment_inf> segment_inf) {
ChanNodeDetails chan_node_details;
size_t actual_chan_width = chan_width;
/* Correct the chan_width: it should be an even number */
if (0 != chan_width % 2) {
chan_width++; /* increment it to be even */
if (0 != actual_chan_width % 2) {
actual_chan_width++; /* increment it to be even */
}
assert (0 == chan_width % 2);
assert (0 == actual_chan_width % 2);
/* Reserve channel width */
chan_node_details.reserve(chan_width);
/* Return if zero width is forced */
if (0 == chan_width) {
if (0 == actual_chan_width) {
return chan_node_details;
}
/* Find the number of segments required by each group */
std::vector<size_t> num_tracks = get_num_tracks_per_seg_type(chan_width/2, segment_inf, TRUE);
std::vector<size_t> num_tracks = get_num_tracks_per_seg_type(actual_chan_width/2, segment_inf, TRUE);
/* Add node to ChanNodeDetails */
size_t cur_track = 0;
@ -319,7 +317,7 @@ ChanNodeDetails build_unidir_chan_node_details(size_t chan_width, size_t max_seg
}
}
/* Check if all the tracks have been satisified */
assert (cur_track == chan_width);
assert (cur_track == actual_chan_width);
/* If this is on the border of a device, segments should start */
switch (device_side) {
@ -375,7 +373,10 @@ enum e_side determine_io_grid_pin_side(const DeviceCoordinator& device_size,
* For others, we consider all the sides
***********************************************************************/
static
std::vector<int> get_grid_side_pins(const t_grid_tile& cur_grid, enum e_pin_type pin_type, enum e_side pin_side, int pin_height) {
std::vector<int> get_grid_side_pins(const t_grid_tile& cur_grid,
const enum e_pin_type pin_type,
const enum e_side pin_side,
const int pin_height) {
std::vector<int> pin_list;
/* Make sure a clear start */
pin_list.clear();
@ -395,7 +396,7 @@ std::vector<int> get_grid_side_pins(const t_grid_tile& cur_grid, enum e_pin_type
* For others, we consider all the sides
***********************************************************************/
static
size_t get_grid_num_pins(const t_grid_tile& cur_grid, enum e_pin_type pin_type, enum e_side io_side) {
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 */
@ -422,9 +423,9 @@ size_t get_grid_num_pins(const t_grid_tile& cur_grid, enum e_pin_type pin_type,
***********************************************************************/
static
std::vector<size_t> estimate_num_rr_nodes_per_type(const DeviceCoordinator& device_size,
std::vector<std::vector<t_grid_tile>> grids,
std::vector<size_t> chan_width,
std::vector<t_segment_inf> segment_infs) {
const std::vector<std::vector<t_grid_tile>> grids,
const std::vector<size_t> chan_width,
const std::vector<t_segment_inf> segment_infs) {
std::vector<size_t> num_rr_nodes_per_type;
/* reserve the vector:
* we have the follow type:
@ -525,8 +526,10 @@ std::vector<size_t> estimate_num_rr_nodes_per_type(const DeviceCoordinator& devi
* Configure one rr_node to the fast-look up of a rr_graph
***********************************************************************/
static
void load_one_node_to_rr_graph_fast_lookup(t_rr_graph* rr_graph, int node_index,
t_rr_type node_type, int x, int y, int ptc_num) {
void load_one_node_to_rr_graph_fast_lookup(t_rr_graph* rr_graph, const int node_index,
const t_rr_type node_type,
const int x, const int y,
const int ptc_num) {
/* check the size of ivec (nelem),
* if the ptc_num exceeds the size limit, we realloc the ivec */
if (ptc_num > rr_graph->rr_node_indices[node_type][x][y].nelem - 1) {
@ -545,10 +548,10 @@ void load_one_node_to_rr_graph_fast_lookup(t_rr_graph* rr_graph, int node_index,
static
void load_one_grid_rr_nodes_basic_info(const DeviceCoordinator& grid_coordinator,
const t_grid_tile& cur_grid,
enum e_side io_side,
const enum e_side io_side,
t_rr_graph* rr_graph,
size_t* cur_node_id,
int wire_to_ipin_switch, int delayless_switch) {
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 */
@ -791,10 +794,10 @@ void load_one_chan_rr_nodes_basic_info(const DeviceCoordinator& chan_coordinator
static
void load_rr_nodes_basic_info(t_rr_graph* rr_graph,
const DeviceCoordinator& device_size,
std::vector<std::vector<t_grid_tile>> grids,
std::vector<size_t> chan_width,
std::vector<t_segment_inf> segment_infs,
int wire_to_ipin_switch, int delayless_switch) {
const std::vector<std::vector<t_grid_tile>> grids,
const std::vector<size_t> chan_width,
const std::vector<t_segment_inf> segment_infs,
const int wire_to_ipin_switch, const int delayless_switch) {
/* counter */
size_t cur_node_id = 0;
/* configure by node type */
@ -966,665 +969,6 @@ void alloc_rr_graph_fast_lookup(const DeviceCoordinator& device_size,
return;
}
/* Build a RRChan Object with the given channel type and coorindators */
static
RRChan build_one_tileable_rr_chan(const DeviceCoordinator& chan_coordinator,
t_rr_type chan_type,
const t_rr_graph* rr_graph,
const ChanNodeDetails& chan_details) {
int chan_width = 0;
t_rr_node** chan_rr_nodes = NULL;
/* Create a rr_chan object and check if it is unique in the graph */
RRChan rr_chan;
/* Fill the information */
rr_chan.set_type(chan_type);
/* Collect rr_nodes for this channel */
chan_rr_nodes = get_chan_rr_nodes(&chan_width, chan_type, chan_coordinator.get_x(), chan_coordinator.get_y(),
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* Reserve */
/* rr_chan.reserve_node(size_t(chan_width)); */
/* Fill the rr_chan */
for (size_t itrack = 0; itrack < size_t(chan_width); ++itrack) {
size_t iseg = chan_details.get_track_segment_id(itrack);
rr_chan.add_node(chan_rr_nodes[itrack], iseg);
}
/* Free rr_nodes */
my_free(chan_rr_nodes);
return rr_chan;
}
/***********************************************************************
* Build a General Switch Block (GSB)
* which includes:
* [I] A Switch Box subckt consists of following ports:
* 1. Channel Y [x][y] inputs
* 2. Channel X [x+1][y] inputs
* 3. Channel Y [x][y-1] outputs
* 4. Channel X [x][y] outputs
* 5. Grid[x][y+1] Right side outputs pins
* 6. Grid[x+1][y+1] Left side output pins
* 7. Grid[x+1][y+1] Bottom side output pins
* 8. Grid[x+1][y] Top side output pins
* 9. Grid[x+1][y] Left side output pins
* 10. Grid[x][y] Right side output pins
* 11. Grid[x][y] Top side output pins
* 12. Grid[x][y+1] Bottom side output pins
*
* -------------- --------------
* | | CBY | |
* | Grid | ChanY | Grid |
* | [x][y+1] | [x][y+1] | [x+1][y+1] |
* | | | |
* -------------- --------------
* ----------
* ChanX & CBX | Switch | ChanX
* [x][y] | Box | [x+1][y]
* | [x][y] |
* ----------
* -------------- --------------
* | | | |
* | Grid | ChanY | Grid |
* | [x][y] | [x][y] | [x+1][y] |
* | | | |
* -------------- --------------
* For channels chanY with INC_DIRECTION on the top side, they should be marked as outputs
* For channels chanY with DEC_DIRECTION on the top side, they should be marked as inputs
* For channels chanY with INC_DIRECTION on the bottom side, they should be marked as inputs
* For channels chanY with DEC_DIRECTION on the bottom side, they should be marked as outputs
* For channels chanX with INC_DIRECTION on the left side, they should be marked as inputs
* For channels chanX with DEC_DIRECTION on the left side, they should be marked as outputs
* For channels chanX with INC_DIRECTION on the right side, they should be marked as outputs
* For channels chanX with DEC_DIRECTION on the right side, they should be marked as inputs
*
* [II] A X-direction Connection Block [x][y]
* The connection block shares the same routing channel[x][y] with the Switch Block
* We just need to fill the ipin nodes at TOP and BOTTOM sides
* as well as properly fill the ipin_grid_side information
* [III] A Y-direction Connection Block [x][y+1]
* The connection block shares the same routing channel[x][y+1] with the Switch Block
* We just need to fill the ipin nodes at LEFT and RIGHT sides
* as well as properly fill the ipin_grid_side information
***********************************************************************/
static
RRGSB build_one_tileable_rr_gsb(const DeviceCoordinator& device_range,
std::vector<size_t> device_chan_width,
std::vector<t_segment_inf> segment_inf,
const DeviceCoordinator& gsb_coordinator,
t_rr_graph* rr_graph) {
/* Create an object to return */
RRGSB rr_gsb;
/* Check */
assert(gsb_coordinator.get_x() <= device_range.get_x());
assert(gsb_coordinator.get_y() <= device_range.get_y());
/* Coordinator initialization */
rr_gsb.set_coordinator(gsb_coordinator.get_x(), gsb_coordinator.get_y());
/* Basic information*/
rr_gsb.init_num_sides(4); /* Fixed number of sides */
/* Find all rr_nodes of channels */
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
/* Local variables inside this for loop */
Side side_manager(side);
DeviceCoordinator coordinator = rr_gsb.get_side_block_coordinator(side_manager.get_side());
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};
enum PORTS chan_dir_to_port_dir_mapping[2] = {OUT_PORT, IN_PORT}; /* 0: INC_DIRECTION => ?; 1: DEC_DIRECTION => ? */
/* Build a segment details, where we need the segment ids for building rr_chan
* We do not care starting and ending points here, so set chan_side as NUM_SIDES
*/
ChanNodeDetails chanx_details = build_unidir_chan_node_details(device_chan_width[0], device_range.get_x() - 1,
NUM_SIDES, segment_inf);
ChanNodeDetails chany_details = build_unidir_chan_node_details(device_chan_width[1], device_range.get_y() - 1,
NUM_SIDES, segment_inf);
switch (side) {
case TOP: /* TOP = 0 */
/* For the bording, we should take special care */
if (gsb_coordinator.get_y() == device_range.get_y()) {
rr_gsb.clear_one_side(side_manager.get_side());
break;
}
/* Routing channels*/
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
/* Create a rr_chan object and check if it is unique in the graph */
rr_chan = build_one_tileable_rr_chan(coordinator, CHANY, rr_graph, chany_details);
chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */
chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */
/* Build the Switch block: opin and opin_grid_side */
/* Include Grid[x][y+1] RIGHT side outputs pins */
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
OPIN, gsb_coordinator.get_x(), gsb_coordinator.get_y() + 1, 1,
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* Include Grid[x+1][y+1] Left side output pins */
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
OPIN, gsb_coordinator.get_x() + 1, gsb_coordinator.get_y() + 1, 3,
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* Assign grid side of OPIN */
/* Grid[x][y+1] RIGHT side outputs pins */
opin_grid_side[0] = RIGHT;
/* Grid[x+1][y+1] left side outputs pins */
opin_grid_side[1] = LEFT;
break;
case RIGHT: /* RIGHT = 1 */
/* For the bording, we should take special care */
if (gsb_coordinator.get_x() == device_range.get_x()) {
rr_gsb.clear_one_side(side_manager.get_side());
break;
}
/* Routing channels*/
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
/* Collect rr_nodes for Tracks for top: chany[x][y+1] */
/* Create a rr_chan object and check if it is unique in the graph */
rr_chan = build_one_tileable_rr_chan(coordinator, CHANX, rr_graph, chanx_details);
chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */
chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */
/* Build the Switch block: opin and opin_grid_side */
/* include Grid[x+1][y+1] Bottom side output pins */
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
OPIN, gsb_coordinator.get_x() + 1, gsb_coordinator.get_y() + 1, 2,
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* include Grid[x+1][y] Top side output pins */
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
OPIN, gsb_coordinator.get_x() + 1, gsb_coordinator.get_y(), 0,
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* Assign grid side of OPIN */
/* Grid[x+1][y+1] BOTTOM side outputs pins */
opin_grid_side[0] = BOTTOM;
/* Grid[x+1][y] TOP side outputs pins */
opin_grid_side[1] = TOP;
break;
case BOTTOM: /* BOTTOM = 2*/
/* For the bording, we should take special care */
if (gsb_coordinator.get_y() == 0) {
rr_gsb.clear_one_side(side_manager.get_side());
break;
}
/* Routing channels*/
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
/* Collect rr_nodes for Tracks for bottom: chany[x][y] */
/* Create a rr_chan object and check if it is unique in the graph */
rr_chan = build_one_tileable_rr_chan(coordinator, CHANY, rr_graph, chany_details);
chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */
chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */
/* Build the Switch block: opin and opin_grid_side */
/* include Grid[x+1][y] Left side output pins */
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
OPIN, gsb_coordinator.get_x() + 1, gsb_coordinator.get_y(), 3,
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* include Grid[x][y] Right side output pins */
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
OPIN, gsb_coordinator.get_x(), gsb_coordinator.get_y(), 1,
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* Assign grid side of OPIN */
/* Grid[x+1][y] LEFT side outputs pins */
opin_grid_side[0] = LEFT;
/* Grid[x][y] RIGHT side outputs pins */
opin_grid_side[1] = RIGHT;
break;
case LEFT: /* LEFT = 3 */
/* For the bording, we should take special care */
if (gsb_coordinator.get_x() == 0) {
rr_gsb.clear_one_side(side_manager.get_side());
break;
}
/* Routing channels*/
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
/* Collect rr_nodes for Tracks for left: chanx[x][y] */
/* Create a rr_chan object and check if it is unique in the graph */
rr_chan = build_one_tileable_rr_chan(coordinator, CHANX, rr_graph, chanx_details);
chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */
chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */
/* Build the Switch block: opin and opin_grid_side */
/* include Grid[x][y+1] Bottom side outputs pins */
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
OPIN, gsb_coordinator.get_x(), gsb_coordinator.get_y() + 1, 2,
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* include Grid[x][y] Top side output pins */
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
OPIN, gsb_coordinator.get_x(), gsb_coordinator.get_y(), 0,
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* Grid[x][y+1] BOTTOM side outputs pins */
opin_grid_side[0] = BOTTOM;
/* Grid[x][y] TOP side outputs pins */
opin_grid_side[1] = TOP;
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])Invalid side index!\n",
__FILE__, __LINE__);
exit(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_gsb.add_chan_node(side_manager.get_side(), rr_chan, rr_chan_dir);
}
/* Fill opin_rr_nodes */
/* Copy from temp_opin_rr_node to opin_rr_node */
for (int inode = 0; inode < temp_num_opin_rr_nodes[0]; ++inode) {
/* Grid[x+1][y+1] Bottom side outputs pins */
rr_gsb.add_opin_node(temp_opin_rr_node[0][inode], side_manager.get_side(), opin_grid_side[0]);
}
for (int inode = 0; inode < temp_num_opin_rr_nodes[1]; ++inode) {
/* Grid[x+1][y] TOP side outputs pins */
rr_gsb.add_opin_node(temp_opin_rr_node[1][inode], side_manager.get_side(), opin_grid_side[1]);
}
/* Clean ipin_rr_nodes */
/* We do not have any IPIN for a Switch Block */
rr_gsb.clear_ipin_nodes(side_manager.get_side());
/* Free */
temp_num_opin_rr_nodes[0] = 0;
my_free(temp_opin_rr_node[0]);
temp_num_opin_rr_nodes[1] = 0;
my_free(temp_opin_rr_node[1]);
/* Set them to NULL, avoid double free errors */
temp_opin_rr_node[0] = NULL;
temp_opin_rr_node[1] = NULL;
opin_grid_side[0] = NUM_SIDES;
opin_grid_side[1] = NUM_SIDES;
}
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
/* Local variables inside this for loop */
Side side_manager(side);
size_t ix;
size_t iy;
enum e_side chan_side;
int num_temp_ipin_rr_nodes = 0;
t_rr_node** temp_ipin_rr_node = NULL;
enum e_side ipin_rr_node_grid_side;
switch (side) {
case TOP: /* TOP = 0 */
/* For the bording, we should take special care */
/* Check if left side chan width is 0 or not */
chan_side = LEFT;
/* Build the connection block: ipin and ipin_grid_side */
/* BOTTOM side INPUT Pins of Grid[x][y+1] */
ix = rr_gsb.get_sb_x();
iy = rr_gsb.get_sb_y() + 1;
ipin_rr_node_grid_side = BOTTOM;
break;
case RIGHT: /* RIGHT = 1 */
/* For the bording, we should take special care */
/* Check if TOP side chan width is 0 or not */
chan_side = TOP;
/* Build the connection block: ipin and ipin_grid_side */
/* LEFT side INPUT Pins of Grid[x+1][y+1] */
ix = rr_gsb.get_sb_x() + 1;
iy = rr_gsb.get_sb_y() + 1;
ipin_rr_node_grid_side = LEFT;
break;
case BOTTOM: /* BOTTOM = 2*/
/* For the bording, we should take special care */
/* Check if left side chan width is 0 or not */
chan_side = LEFT;
/* Build the connection block: ipin and ipin_grid_side */
/* TOP side INPUT Pins of Grid[x][y] */
ix = rr_gsb.get_sb_x();
iy = rr_gsb.get_sb_y();
ipin_rr_node_grid_side = TOP;
break;
case LEFT: /* LEFT = 3 */
/* For the bording, we should take special care */
/* Check if left side chan width is 0 or not */
chan_side = TOP;
/* Build the connection block: ipin and ipin_grid_side */
/* RIGHT side INPUT Pins of Grid[x][y+1] */
ix = rr_gsb.get_sb_x();
iy = rr_gsb.get_sb_y() + 1;
ipin_rr_node_grid_side = RIGHT;
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])Invalid side index!\n",
__FILE__, __LINE__);
exit(1);
}
/* If there is no channel at this side, we skip ipin_node annotation */
if (0 == rr_gsb.get_chan_width(chan_side)) {
continue;
}
/* Collect IPIN rr_nodes*/
temp_ipin_rr_node = get_grid_side_pin_rr_nodes(&(num_temp_ipin_rr_nodes),
IPIN, ix, iy, ipin_rr_node_grid_side,
rr_graph->num_rr_nodes, rr_graph->rr_node, rr_graph->rr_node_indices);
/* Fill the ipin nodes of RRGSB */
for (int inode = 0; inode < num_temp_ipin_rr_nodes; ++inode) {
rr_gsb.add_ipin_node(temp_ipin_rr_node[inode], side_manager.get_side(), ipin_rr_node_grid_side);
}
/* Free */
num_temp_ipin_rr_nodes = 0;
my_free(temp_ipin_rr_node);
}
return rr_gsb;
}
/************************************************************************
* Add a edge connecting two rr_nodes
* For src rr_node, update the edge list and update switch_id,
* For des rr_node, update the fan_in
***********************************************************************/
static
void add_one_edge_for_two_rr_nodes(t_rr_graph* rr_graph,
int src_rr_node_id,
int des_rr_node_id,
short switch_id) {
/* Check */
assert ( (-1 < src_rr_node_id) && (src_rr_node_id < rr_graph->num_rr_nodes) );
assert ( (-1 < des_rr_node_id) && (des_rr_node_id < rr_graph->num_rr_nodes) );
t_rr_node* src_rr_node = &(rr_graph->rr_node[src_rr_node_id]);
t_rr_node* des_rr_node = &(rr_graph->rr_node[des_rr_node_id]);
/* Allocate edge and switch to src_rr_node */
src_rr_node->num_edges++;
if (NULL == src_rr_node->edges) {
/* calloc */
src_rr_node->edges = (int*) my_calloc( src_rr_node->num_edges, sizeof(int) );
src_rr_node->switches = (short*) my_calloc( src_rr_node->num_edges, sizeof(short) );
} else {
/* realloc */
src_rr_node->edges = (int*) my_realloc(src_rr_node->edges,
src_rr_node->num_edges * sizeof(int));
src_rr_node->switches = (short*) my_realloc(src_rr_node->switches,
src_rr_node->num_edges * sizeof(short));
}
/* Fill edge and switch info */
src_rr_node->edges[src_rr_node->num_edges - 1] = des_rr_node_id;
src_rr_node->switches[src_rr_node->num_edges - 1] = switch_id;
/* Update the des_rr_node */
des_rr_node->fan_in++;
return;
}
/************************************************************************
* Create edges for each rr_node of a General Switch Blocks (GSB):
* 1. create edges between SOURCE and OPINs
* 2. create edges between IPINs and SINKs
* 3. create edges between CHANX | CHANY and IPINs (connections inside connection blocks)
* 4. create edges between OPINs, CHANX and CHANY (connections inside switch blocks)
* 5. create edges between OPINs and IPINs (direct-connections)
***********************************************************************/
static
void build_edges_for_one_tileable_rr_gsb(t_rr_graph* rr_graph, RRGSB* rr_gsb,
t_track2pin_map track2ipin_map,
t_pin2track_map opin2track_map,
t_track2track_map track2track_map) {
/* Check rr_gsb */
assert (NULL != rr_gsb);
/* Walk through each sides */
for (size_t side = 0; side < rr_gsb->get_num_sides(); ++side) {
Side side_manager(side);
enum e_side gsb_side = side_manager.get_side();
/* 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);
/* 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,
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,
opin_node->driver_switch);
/* 2. create edges between OPINs and CHANX|CHANY, using opin2track_map */
int num_edges = opin2track_map[side_manager.to_size_t()][inode].size();
for (int iedge = 0; iedge < num_edges; ++iedge) {
int track_node_id = opin2track_map[side_manager.to_size_t()][inode][iedge];
/* add edges to the chan_node */
add_one_edge_for_two_rr_nodes(rr_graph, opin_node - rr_graph->rr_node, track_node_id,
rr_graph->rr_node[track_node_id].driver_switch);
}
}
/* 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);
/* 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,
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 (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();
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 */
add_one_edge_for_two_rr_nodes(rr_graph, chan_node - rr_graph->rr_node, track_node_id,
rr_graph->rr_node[track_node_id].driver_switch);
}
}
}
return;
}
/************************************************************************
* Convert the pin_to_track_map[0..nodes_per_chan-1][0..height][0..3][pin_numbers]
* to the existing routing resources in the General Switch Block (GSB)
* The resulting matrix will be oragnized in
* pin2track_map[gsb_side][0..chan_width-1][ipin_indices]
***********************************************************************/
static
t_pin2track_map build_gsb_pin_to_track_map(const RRGSB& rr_gsb,
std::vector< std::vector<t_grid_tile> > grids,
int** Fc,
bool is_Fc_out,
int***** pin_to_track_map) {
/* [0..gsb_side][0..num_tracks][0..Fc-1] */
t_pin2track_map pin2track_map;
/* Resize the matrix */
pin2track_map.resize(rr_gsb.get_num_sides());
/* Walk through each side */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
Side side_manager(side);
enum e_side gsb_side = side_manager.get_side();
/* Get channel width and resize the matrix */
size_t chan_width = rr_gsb.get_chan_width(gsb_side);
pin2track_map[side].resize(chan_width);
/* Find the ipin/opin nodes */
size_t num_pin_nodes;
if (true == is_Fc_out) { /* Fc_out, we consider OPINs */
num_pin_nodes = rr_gsb.get_num_opin_nodes(gsb_side);
} else { /* Fc_in, we consider IPINs */
num_pin_nodes = rr_gsb.get_num_ipin_nodes(gsb_side);
}
for (size_t inode = 0; inode < num_pin_nodes; ++inode) {
t_rr_node* pin_node;
if (true == is_Fc_out) { /* Fc_out, we consider OPINs */
pin_node = rr_gsb.get_opin_node(gsb_side, inode);
} else { /* Fc_in, we consider IPINs */
pin_node = rr_gsb.get_ipin_node(gsb_side, inode);
}
/* For each IPIN, we find the type_descriptor, offset and pin_side on the grid */
int grid_type_id = grids[pin_node->xlow][pin_node->ylow].type->index;
int offset = grid[pin_node->xlow][pin_node->ylow].offset;
enum e_side pin_side;
if (true == is_Fc_out) { /* Fc_out, we consider OPINs */
pin_side = rr_gsb.get_opin_node_grid_side(gsb_side, inode);
} else { /* Fc_in, we consider IPINs */
pin_side = rr_gsb.get_ipin_node_grid_side(gsb_side, inode);
}
/* Now, we fill the return matrix */
/* Bypass empty array */
if (NULL == pin_to_track_map[grid_type_id][pin_node->ptc_num][offset][0]) {
continue;
}
/* Get each track_id */
for (int iconn = 0; iconn < Fc[grid_type_id][pin_node->ptc_num]; ++iconn) {
int track_id = pin_to_track_map[grid_type_id][pin_node->ptc_num][offset][pin_side][iconn];
pin2track_map[gsb_side][track_id].push_back(inode);
}
}
}
return pin2track_map;
}
/************************************************************************
* Build the track_to_ipin_map[gsb_side][0..chan_width-1][ipin_indices]
* based on the existing routing resources in the General Switch Block (GSB)
* This function supports both X-directional and Y-directional tracks
* The mapping is done in the following steps:
* 1. build a list of routing tracks which are allowed for connections
* We will check the Connection Block (CB) population of each routing track.
* By comparing current chan_y - ylow, we can determine if a CB connection
* is required for each routing track
* 2. Divide the routing tracks by segment types, so that we can balance
* the connections between IPINs and different types of routing tracks.
* 3. Scale the Fc of each pin to the actual number of routing tracks
* actual_Fc = (int) Fc * num_tracks / chan_width
* 4. Build ipin_to_track_map[gsb_side][0..num_ipin_nodes-1][track_indices]
* For each IPIN, we ensure at least one connection to the tracks.
* Then, we assign IPINs to tracks evenly while satisfying the actual_Fc
* 5. Convert the ipin_to_track_map to track_to_ipin_map
***********************************************************************/
/************************************************************************
* Build the opin_to_track_map[gsb_side][0..num_opin_nodes-1][track_indices]
* based on the existing routing resources in the General Switch Block (GSB)
* This function supports both X-directional and Y-directional tracks
* The mapping is done in the following steps:
* 1. Build a list of routing tracks whose starting points locate at this GSB
* (xlow - gsb_x == 0)
* 2. Divide the routing tracks by segment types, so that we can balance
* the connections between OPINs and different types of routing tracks.
* 3. Scale the Fc of each pin to the actual number of routing tracks
* actual_Fc = (int) Fc * num_tracks / chan_width
***********************************************************************/
/************************************************************************
* Add all direct clb-pin-to-clb-pin edges to given opin
***********************************************************************/
static
void build_direct_connections_for_one_gsb(t_rr_graph* rr_graph,
const DeviceCoordinator& device_size,
const DeviceCoordinator& from_grid_coordinator,
const t_grid_tile& from_grid,
const int delayless_switch,
const int num_directs,
const t_direct_inf *directs,
const t_clb_to_clb_directs *clb_to_clb_directs) {
t_type_ptr grid_type = from_grid.type;
/* Iterate through all direct connections */
for (int i = 0; i < num_directs; ++i) {
/* Bypass unmatched direct clb-to-clb connections */
if (grid_type != clb_to_clb_directs[i].from_clb_type) {
continue;
}
bool swap;
int max_index, min_index;
/* Compute index of opin with regards to given pins */
if ( clb_to_clb_directs[i].from_clb_pin_start_index
> clb_to_clb_directs[i].from_clb_pin_end_index) {
swap = true;
max_index = clb_to_clb_directs[i].from_clb_pin_start_index;
min_index = clb_to_clb_directs[i].from_clb_pin_end_index;
} else {
swap = false;
min_index = clb_to_clb_directs[i].from_clb_pin_start_index;
max_index = clb_to_clb_directs[i].from_clb_pin_end_index;
}
/* get every opin in the range */
for (int opin = min_index; opin <= max_index; ++opin) {
int offset = opin - min_index;
/* This opin is specified to connect directly to an ipin, now compute which ipin to connect to */
DeviceCoordinator to_grid_coordinator(from_grid_coordinator.get_x() + directs[i].x_offset,
from_grid_coordinator.get_y() + directs[i].y_offset);
if ( (to_grid_coordinator.get_x() < device_size.get_x() - 1)
&& (to_grid_coordinator.get_y() < device_size.get_y() - 1) ) {
int ipin = OPEN;
if ( clb_to_clb_directs[i].to_clb_pin_start_index
> clb_to_clb_directs[i].to_clb_pin_end_index) {
if (true == swap) {
ipin = clb_to_clb_directs[i].to_clb_pin_end_index + offset;
} else {
ipin = clb_to_clb_directs[i].to_clb_pin_start_index - offset;
}
} else {
if(true == swap) {
ipin = clb_to_clb_directs[i].to_clb_pin_end_index - offset;
} else {
ipin = clb_to_clb_directs[i].to_clb_pin_start_index + offset;
}
}
/* Get the pin index in the rr_graph */
int from_grid_ofs = from_grid.offset;
int to_grid_ofs = grid[to_grid_coordinator.get_x()][to_grid_coordinator.get_y()].offset;
int opin_node_id = get_rr_node_index(from_grid_coordinator.get_x(),
from_grid_coordinator.get_y() - from_grid_ofs,
OPIN, opin, rr_graph->rr_node_indices);
int ipin_node_id = get_rr_node_index(to_grid_coordinator.get_x(),
to_grid_coordinator.get_y() - to_grid_ofs,
IPIN, ipin, rr_graph->rr_node_indices);
/* add edges to the opin_node */
add_one_edge_for_two_rr_nodes(rr_graph, opin_node_id, ipin_node_id,
delayless_switch);
}
}
}
return;
}
/************************************************************************
* Build the edges of each rr_node tile by tile:
* We classify rr_nodes into a general switch block (GSB) data structure
@ -1640,12 +984,11 @@ void build_direct_connections_for_one_gsb(t_rr_graph* rr_graph,
static
void build_rr_graph_edges(t_rr_graph* rr_graph,
const DeviceCoordinator& device_size,
std::vector< std::vector<t_grid_tile> > grids,
std::vector<size_t> device_chan_width,
std::vector<t_segment_inf> segment_inf,
const std::vector< std::vector<t_grid_tile> > grids,
const std::vector<size_t> device_chan_width,
const std::vector<t_segment_inf> segment_inf,
int** Fc_in, int** Fc_out,
int***** ipin_to_track_map, int***** opin_to_track_map,
enum e_switch_block_type sb_type, int Fs) {
const enum e_switch_block_type sb_type, const int Fs) {
DeviceCoordinator device_range(device_size.get_x() - 1, device_size.get_y() - 1);
@ -1657,13 +1000,19 @@ void build_rr_graph_edges(t_rr_graph* rr_graph,
/* Create a GSB object */
RRGSB rr_gsb = build_one_tileable_rr_gsb(device_range, device_chan_width, segment_inf, gsb_coordinator, rr_graph);
DeviceCoordinator grid_coordinator = rr_gsb.get_grid_coordinator();
/* adapt the track_to_ipin_lookup for the GSB nodes */
t_pin2track_map ipin2track_map; /* [0..track_gsb_side][0..num_tracks][ipin_indices] */
ipin2track_map = build_gsb_pin_to_track_map(rr_gsb, grids, Fc_in, false, ipin_to_track_map);
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;
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] */
opin2track_map = build_gsb_pin_to_track_map(rr_gsb, grids, Fc_out, true, opin_to_track_map);
/* Get the Fc index of the grid */
int grid_Fc_out_index = grids[grid_coordinator.get_x()][grid_coordinator.get_x()].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 */
t_track2track_map sb_conn; /* [0..from_gsb_side][0..chan_width-1][track_indices] */
@ -1671,7 +1020,7 @@ void build_rr_graph_edges(t_rr_graph* rr_graph,
/* Build edges for a GSB */
build_edges_for_one_tileable_rr_gsb(rr_graph, &rr_gsb,
ipin2track_map, opin2track_map,
track2ipin_map, opin2track_map,
sb_conn);
/* Finish this GSB, go to the next*/
}
@ -1686,7 +1035,7 @@ void build_rr_graph_edges(t_rr_graph* rr_graph,
static
void build_rr_graph_direct_connections(t_rr_graph* rr_graph,
const DeviceCoordinator& device_size,
std::vector< std::vector<t_grid_tile> > grids,
const std::vector< std::vector<t_grid_tile> > grids,
const int delayless_switch,
const int num_directs,
const t_direct_inf *directs,
@ -1702,7 +1051,7 @@ void build_rr_graph_direct_connections(t_rr_graph* rr_graph,
continue;
}
DeviceCoordinator from_grid_coordinator(ix, iy);
build_direct_connections_for_one_gsb(rr_graph, device_size,
build_direct_connections_for_one_gsb(rr_graph, device_size, grids,
from_grid_coordinator,
grids[ix][iy],
delayless_switch,
@ -1752,17 +1101,17 @@ void build_rr_graph_direct_connections(t_rr_graph* rr_graph,
* a. cost_index
* b. RC tree
***********************************************************************/
void build_tileable_unidir_rr_graph(INP int L_num_types,
INP t_type_ptr types, INP int L_nx, INP int L_ny,
INP struct s_grid_tile **L_grid, INP int chan_width,
INP enum e_switch_block_type sb_type, INP int Fs,
INP int num_seg_types,
INP t_segment_inf * segment_inf,
INP int delayless_switch,
INP t_timing_inf timing_inf, INP int wire_to_ipin_switch,
INP enum e_base_cost_type base_cost_type,
INP t_direct_inf *directs,
INP int num_directs, INP boolean ignore_Fc_0,
void build_tileable_unidir_rr_graph(INP const int L_num_types,
INP t_type_ptr types, INP const int L_nx, INP const int L_ny,
INP const struct s_grid_tile **L_grid, INP const int chan_width,
INP const enum e_switch_block_type sb_type, INP const int Fs,
INP const int num_seg_types,
INP const t_segment_inf * segment_inf,
INP const int num_switches, INP int const delayless_switch, const int global_route_switch,
INP const t_timing_inf timing_inf, INP int const wire_to_ipin_switch,
INP const enum e_base_cost_type base_cost_type,
INP const t_direct_inf *directs,
INP const int num_directs, INP const boolean ignore_Fc_0,
OUTP int *Warnings) {
/* Create an empty graph */
t_rr_graph rr_graph;
@ -1856,23 +1205,6 @@ void build_tileable_unidir_rr_graph(INP int L_num_types,
*Warnings |= RR_GRAPH_WARN_FC_CLIPPED;
}
/* START IPINP MAP */
/* Create ipin map lookups */
int***** ipin_to_track_map = (int*****) my_calloc(L_num_types, sizeof(int****));
boolean* perturb_ipins = alloc_and_load_perturb_ipins(chan_width, L_num_types, Fc_in, Fc_out, UNI_DIRECTIONAL);
for (int i = 0; i < L_num_types; ++i) {
ipin_to_track_map[i] = alloc_and_load_pin_to_track_map(RECEIVER, chan_width, Fc_in[i], &types[i],
perturb_ipins[i], UNI_DIRECTIONAL);
}
/* END IPINP MAP */
/* START OPINP MAP */
/* Create opin map lookups */
int***** opin_to_track_map = (int*****) my_calloc(L_num_types, sizeof(int****));
for (int i = 0; i < L_num_types; ++i) {
opin_to_track_map[i] = alloc_and_load_pin_to_track_map(DRIVER, chan_width, Fc_out[i], &types[i], FALSE, UNI_DIRECTIONAL);
}
/************************************************************************
* 6. Build the connections tile by tile:
* We classify rr_nodes into a general switch block (GSB) data structure
@ -1884,7 +1216,7 @@ void build_tileable_unidir_rr_graph(INP int L_num_types,
/* Create edges for a tileable rr_graph */
build_rr_graph_edges(&rr_graph, device_size, grids, device_chan_width, segment_infs,
Fc_in, Fc_out, ipin_to_track_map, opin_to_track_map,
Fc_in, Fc_out,
sb_type, Fs);
/************************************************************************
@ -1903,18 +1235,21 @@ void build_tileable_unidir_rr_graph(INP int L_num_types,
* a. cost_index
* b. RC tree
***********************************************************************/
/* We set global variables for rr_nodes here, they will be updated by rr_graph_external */
num_rr_nodes = rr_graph.num_rr_nodes;
rr_node = rr_graph.rr_node;
rr_node_indices = rr_graph.rr_node_indices;
rr_graph_externals(timing_inf, segment_inf, num_seg_types, chan_width,
wire_to_ipin_switch, base_cost_type);
/************************************************************************
* 9. Sanitizer for the rr_graph, check connectivities of rr_nodes
***********************************************************************/
check_rr_graph(GRAPH_UNIDIR_TILEABLE, types, L_nx, L_ny, chan_width, Fs,
num_seg_types, num_switches, segment_inf, global_route_switch,
delayless_switch, wire_to_ipin_switch, Fc_in, Fc_out);
/* We set global variables for rr_nodes here,
*/
num_rr_nodes = rr_graph.num_rr_nodes;
rr_node = rr_graph.rr_node;
rr_node_indices = rr_graph.rr_node_indices;
/************************************************************************
* 10. Free all temp stucts
@ -1929,19 +1264,6 @@ void build_tileable_unidir_rr_graph(INP int L_num_types,
free_matrix(Fc_out,0, L_num_types, 0, sizeof(int));
Fc_out = NULL;
}
if (perturb_ipins) {
free(perturb_ipins);
perturb_ipins = NULL;
}
if (opin_to_track_map) {
for (int i = 0; i < L_num_types; ++i) {
free_matrix4(opin_to_track_map[i], 0, types[i].num_pins - 1, 0,
types[i].height - 1, 0, 3, 0, sizeof(int));
}
free(opin_to_track_map);
}
free_type_pin_to_track_map(ipin_to_track_map, types);
if(clb_to_clb_directs != NULL) {
free(clb_to_clb_directs);
}

View File

@ -1,15 +1,27 @@
#ifndef RR_GRAPH_TILEABLE_BUILDER_H
#define RR_GRAPH_TILEABLE_BUILDER_H
void build_tileable_unidir_rr_graph(INP int L_num_types,
INP t_type_ptr types, INP int L_nx, INP int L_ny,
INP struct s_grid_tile **L_grid, INP int chan_width,
INP enum e_switch_block_type sb_type, INP int Fs,
INP int num_seg_types,
INP t_segment_inf * segment_inf,
INP int delayless_switch,
INP t_timing_inf timing_inf, INP int wire_to_ipin_switch,
INP enum e_base_cost_type base_cost_type, INP t_direct_inf *directs,
INP int num_directs, INP boolean ignore_Fc_0, OUTP int *Warnings);
#include <vector>
#include "vpr_types.h"
#include "chan_node_details.h"
ChanNodeDetails build_unidir_chan_node_details(const size_t chan_width, const size_t max_seg_length,
const enum e_side device_side,
const std::vector<t_segment_inf> segment_inf);
void build_tileable_unidir_rr_graph(INP const int L_num_types,
INP t_type_ptr types, INP const int L_nx, INP const int L_ny,
INP const struct s_grid_tile **L_grid, INP const int chan_width,
INP const enum e_switch_block_type sb_type, INP const int Fs,
INP const int num_seg_types,
INP const t_segment_inf * segment_inf,
INP const int num_switches, INP int const delayless_switch, const int global_route_switch,
INP const t_timing_inf timing_inf, INP int const wire_to_ipin_switch,
INP const enum e_base_cost_type base_cost_type,
INP const t_direct_inf *directs,
INP const int num_directs, INP const boolean ignore_Fc_0,
OUTP int *Warnings);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
#ifndef RR_GRAPH_TILEABLE_GSB_H
#define RR_GRAPH_TILEABLE_GSB_H
#include <vector>
#include "vtr_ndmatrix.h"
#include "rr_blocks.h"
#include "fpga_x2p_types.h"
/************************************************************************
* Data stuctures related to the functions
***********************************************************************/
typedef std::vector<std::vector<std::vector<int>>> t_track2track_map;
typedef std::vector<std::vector<std::vector<int>>> t_track2pin_map;
typedef std::vector<std::vector<std::vector<int>>> t_pin2track_map;
/************************************************************************
* Functions
***********************************************************************/
t_track2track_map build_gsb_track_to_track_map(const t_rr_graph* rr_graph,
const RRGSB& rr_gsb,
const enum e_switch_block_type sb_type,
const int Fs,
const std::vector<t_segment_inf> segment_inf);
RRGSB build_one_tileable_rr_gsb(const DeviceCoordinator& device_range,
const std::vector<size_t> device_chan_width,
const std::vector<t_segment_inf> segment_inf,
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,
const t_track2pin_map track2ipin_map,
const t_pin2track_map opin2track_map,
const t_track2track_map track2track_map);
t_track2pin_map build_gsb_track_to_ipin_map(t_rr_graph* rr_graph,
const RRGSB& rr_gsb,
const std::vector<t_segment_inf> segment_inf,
const int* Fc_in);
t_pin2track_map build_gsb_opin_to_track_map(t_rr_graph* rr_graph,
const RRGSB& rr_gsb,
const std::vector<t_segment_inf> segment_inf,
const int* Fc_out);
void build_direct_connections_for_one_gsb(t_rr_graph* rr_graph,
const DeviceCoordinator& device_size,
const std::vector<std::vector<t_grid_tile>> grids,
const DeviceCoordinator& from_grid_coordinator,
const t_grid_tile& from_grid,
const int delayless_switch,
const int num_directs,
const t_direct_inf *directs,
const t_clb_to_clb_directs *clb_to_clb_directs);
#endif

View File

@ -1,461 +0,0 @@
/**********************************************************
* MIT License
*
* Copyright (c) 2018 LNIS - The University of Utah
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***********************************************************************/
/************************************************************************
* Filename: rr_graph_tileable_sbox.cpp
* Created by: Xifan Tang
* Change history:
* +-------------------------------------+
* | Date | Author | Notes
* +-------------------------------------+
* | 2019/06/19 | Xifan Tang | Created
* +-------------------------------------+
***********************************************************************/
/************************************************************************
* This file contains a builder for track-to-track connections inside a
* tileable General Switch Block (GSB).
***********************************************************************/
#include <cstdlib>
#include <cassert>
#include <vector>
#include "vpr_types.h"
#include "rr_graph_tileable_sbox.h"
/************************************************************************
* Internal data structures
***********************************************************************/
typedef std::vector<std::vector<int>> t_track_group;
/************************************************************************
* A enumeration to list the status of a track inside a GSB
* 1. start; 2. end; 3. passing
* This is used to group tracks which ease the building of
* track-to-track mapping matrix
***********************************************************************/
enum e_track_status {
TRACK_START,
TRACK_END,
TRACK_PASS,
NUM_TRACK_STATUS /* just a place holder to get the number of status */
};
/************************************************************************
* Check if a track starts from this GSB or not
* (xlow, ylow) should be same as the GSB side coordinator
*
* Check if a track ends at this GSB or not
* (xhigh, yhigh) should be same as the GSB side coordinator
***********************************************************************/
static
enum e_track_status determine_track_status_of_gsb(const RRGSB& rr_gsb,
const enum e_side gsb_side,
const size_t track_id) {
enum e_track_status track_status = TRACK_PASS;
/* Get the rr_node */
t_rr_node* track_node = rr_gsb.get_chan_node(gsb_side, track_id);
/* Get the coordinators */
DeviceCoordinator side_coordinator = rr_gsb.get_side_block_coordinator(gsb_side);
/* INC_DIRECTION start_track: (xlow, ylow) should be same as the GSB side coordinator */
if ( ((size_t)track_node->xlow == side_coordinator.get_x())
&& ((size_t)track_node->ylow == side_coordinator.get_y())
&& (OUT_PORT == rr_gsb.get_chan_node_direction(gsb_side, track_id)) ) {
/* Double check: start track should be an OUTPUT PORT of the GSB */
track_status = TRACK_START;
}
/* INC_DIRECTION end_track: (xhigh, yhigh) should be same as the GSB side coordinator */
if ( ((size_t)track_node->xhigh == side_coordinator.get_x())
&& ((size_t)track_node->yhigh == side_coordinator.get_y())
&& (IN_PORT == rr_gsb.get_chan_node_direction(gsb_side, track_id)) ) {
/* Double check: end track should be an INPUT PORT of the GSB */
track_status = TRACK_END;
}
return track_status;
}
/************************************************************************
* Check if the GSB is in the Switch Block (SB) population list of the segment
* SB population of a L3 wire: 1 0 0 1
*
* +----+ +----+ +----+ +----+
* | SB |--->| SB |--->| SB |--->| SB |
* +----+ +----+ +----+ +----+
* Engage SB connection Yes No No Yes
*
* We will find the offset between gsb_side_coordinator and (xlow,ylow) of the track
* Use the offset to check if the tracks should engage in this GSB connection
***********************************************************************/
static
bool is_gsb_in_track_sb_population(const RRGSB& rr_gsb,
const enum e_side gsb_side,
const int track_id,
const std::vector<t_segment_inf> segment_inf) {
/* Get the rr_node */
t_rr_node* track_node = rr_gsb.get_chan_node(gsb_side, track_id);
/* Get the coordinators */
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);
/* Get segment id */
size_t seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id);
/* validate offset */
assert (offset < (size_t)segment_inf[seg_id].sb_len);
/* Get the SB population */
bool in_sb_population = false;
if (TRUE == segment_inf[seg_id].sb[offset]) {
in_sb_population = true;
}
return in_sb_population;
}
/************************************************************************
* Create a list of track_id based on the to_track and num_to_tracks
* We consider the following list [to_track, to_track + Fs/3 - 1]
* if the [to_track + Fs/3 - 1] exceeds the num_to_tracks, we start over from 0!
***********************************************************************/
static
std::vector<size_t> get_to_track_list(const int Fs, const int to_track, const int num_to_tracks) {
std::vector<size_t> to_tracks;
for (int i = 0; i < Fs; i = i + 3) {
/* 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;
/* make sure the track id is still in range */
if ( to_track_i > (size_t)num_to_tracks) {
to_track_i = to_track_i % num_to_tracks;
}
/* from track must be connected */
to_tracks.push_back(to_track_i);
}
return to_tracks;
}
/************************************************************************
* This function aims to return the track indices that drive the from_track
* in a Switch Block
* The track_ids to return will depend on different topologies of SB
* SUBSET, UNIVERSAL, and WILTON.
***********************************************************************/
static
std::vector<size_t> get_switch_block_to_track_id(const enum e_switch_block_type switch_block_type,
const int Fs,
const enum e_side from_side,
const int from_track,
const enum e_side to_side,
const int num_to_tracks) {
/* This routine returns the track number to which the from_track should
* connect. It supports any Fs % 3 == 0, switch blocks.
*/
std::vector<size_t> to_tracks;
/* 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!!!
*/
assert (0 == Fs % 3);
switch (switch_block_type) {
case SUBSET: /* NB: Global routing uses SUBSET too */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
/* Finish, we return */
return to_tracks;
case UNIVERSAL:
if ( (from_side == LEFT)
|| (from_side == RIGHT) ) {
/* For the prev_side, to_track is from_track
* For the next_side, to_track is num_to_tracks - 1 - from_track
* For the opposite_side, to_track is always from_track
*/
Side side_manager(from_side);
if ( (to_side == side_manager.get_opposite())
|| (to_side == side_manager.get_rotate_counterclockwise()) ) {
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
} else if (to_side == side_manager.get_rotate_clockwise()) {
to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - from_track, num_to_tracks);
}
}
if ( (from_side == TOP)
|| (from_side == BOTTOM) ) {
/* For the next_side, to_track is from_track
* For the prev_side, to_track is num_to_tracks - 1 - from_track
* For the opposite_side, to_track is always from_track
*/
Side side_manager(from_side);
if ( (to_side == side_manager.get_opposite())
|| (to_side == side_manager.get_rotate_clockwise()) ) {
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
} else if (to_side == side_manager.get_rotate_counterclockwise()) {
to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - from_track, num_to_tracks);
}
}
/* Finish, we return */
return to_tracks;
/* End switch_block_type == UNIVERSAL case. */
case WILTON:
/* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */
if (from_side == LEFT) {
if (to_side == RIGHT) { /* CHANX to CHANX */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
} else if (to_side == TOP) { /* from CHANX to CHANY */
to_tracks = get_to_track_list(Fs, (num_to_tracks - (from_track % num_to_tracks)) % num_to_tracks, num_to_tracks);
} else if (to_side == BOTTOM) {
to_tracks = get_to_track_list(Fs, (num_to_tracks + from_track - 1) % num_to_tracks, num_to_tracks);
}
} else if (from_side == RIGHT) {
if (to_side == LEFT) { /* CHANX to CHANX */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
} else if (to_side == TOP) { /* from CHANX to CHANY */
to_tracks = get_to_track_list(Fs, (num_to_tracks + from_track - 1) % num_to_tracks, num_to_tracks);
} else if (to_side == BOTTOM) {
to_tracks = get_to_track_list(Fs, (num_to_tracks - 2 - from_track) % num_to_tracks, num_to_tracks);
}
} else if (from_side == BOTTOM) {
if (to_side == TOP) { /* CHANY to CHANY */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
} else if (to_side == LEFT) { /* from CHANY to CHANX */
to_tracks = get_to_track_list(Fs, (from_track + 1) % num_to_tracks, num_to_tracks);
} else if (to_side == RIGHT) {
to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - from_track) % num_to_tracks, num_to_tracks);
}
} else if (from_side == TOP) {
if (to_side == BOTTOM) { /* CHANY to CHANY */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
} else if (to_side == LEFT) { /* from CHANY to CHANX */
to_tracks = get_to_track_list(Fs, (num_to_tracks - (from_track % num_to_tracks)) % num_to_tracks, num_to_tracks);
} else if (to_side == RIGHT) {
to_tracks = get_to_track_list(Fs, (from_track + 1) % num_to_tracks, num_to_tracks);
}
}
/* Finish, we return */
return to_tracks;
/* End switch_block_type == WILTON case. */
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d]) Invalid switch block pattern !\n",
__FILE__, __LINE__);
exit(1);
}
return to_tracks;
}
/************************************************************************
* Build the track_to_track_map[from_side][0..chan_width-1][to_side][track_indices]
* For a group of from_track nodes and to_track nodes
* For each side of from_tracks, we call a routine to get the list of to_tracks
* Then, we fill the track2track_map
***********************************************************************/
static
void build_gsb_one_group_track_to_track_map(const t_rr_graph* rr_graph,
const RRGSB& rr_gsb,
const enum e_switch_block_type sb_type,
const int Fs,
const t_track_group from_tracks, /* [0..gsb_side][track_indices] */
const t_track_group to_tracks, /* [0..gsb_side][track_indices] */
t_track2track_map* track2track_map) {
for (size_t side = 0; side < from_tracks.size(); ++side) {
Side side_manager(side);
enum e_side gsb_side = side_manager.get_side();
/* Find the other sides where the start tracks will locate */
std::vector<enum e_side> to_track_sides;
/* 0. opposite side */
to_track_sides.push_back(side_manager.get_opposite());
/* 1. prev side */
/* Previous side definition: TOP => LEFT; RIGHT=>TOP; BOTTOM=>RIGHT; LEFT=>BOTTOM */
to_track_sides.push_back(side_manager.get_rotate_counterclockwise());
/* 2. next side */
/* Next side definition: TOP => RIGHT; RIGHT=>BOTTOM; BOTTOM=>LEFT; LEFT=>TOP */
to_track_sides.push_back(side_manager.get_rotate_clockwise());
for (size_t inode = 0; inode < from_tracks[side].size(); ++inode) {
for (size_t to_side_id = 0; to_side_id < to_track_sides.size(); ++to_side_id) {
enum e_side to_side = to_track_sides[to_side_id];
Side to_side_manager(to_side);
size_t to_side_index = to_side_manager.to_size_t();
/* Bypass those to_sides have no nodes */
if (0 == to_tracks[to_side_index].size()) {
continue;
}
/* Get other track_ids depending on the switch block pattern */
/* Find the track ids that will start at the other sides */
std::vector<size_t> to_track_ids = get_switch_block_to_track_id(sb_type, Fs, gsb_side, inode,
to_side,
to_tracks[to_side_index].size());
/* Update the track2track_map: */
for (size_t to_track_id = 0; to_track_id < to_track_ids.size(); ++to_track_id) {
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]];
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);
}
}
}
}
return;
}
/************************************************************************
* Build the track_to_track_map[from_side][0..chan_width-1][to_side][track_indices]
* based on the existing routing resources in the General Switch Block (GSB)
* The track_indices is the indices of tracks that the node at from_side and [0..chan_width-1] will drive
* IMPORTANT: the track_indices are the indicies in the GSB context, but not the rr_graph!!!
* We separate the connections into two groups:
* Group 1: the routing tracks start from this GSB
* We will apply switch block patterns (SUBSET, UNIVERSAL, WILTON)
* Group 2: the routing tracks do not start from this GSB (bypassing wires)
* We will apply switch block patterns (SUBSET, UNIVERSAL, WILTON)
* but we will check the Switch Block (SB) population of these
* routing segments, and determine which requires connections
*
* CHANY CHANY CHANY CHANY
* [0] [1] [2] [3]
* start yes no yes no
* end +-------------------------+ start Group 1 Group 2
* no CHANX[0] | TOP | CHANX[0] yes TOP/BOTTOM TOP/BOTTOM
* | | CHANY[0,2] CHANY[1,3]
* yes CHANX[1] | | CHANX[1] no
* | LEFT RIGHT |
* no CHANX[2] | | CHANX[2] yes
* | |
* yes CHANX[3] | BOTTOM | CHANX[3] no
* +-------------------------+
* CHANY CHANY CHANY CHANY
* [0] [1] [2] [3]
* start yes no yes no
*
* The mapping is done in the following steps: (For each side of the GSB)
* 1. Build a list of tracks that will start from this side
* if a track starts, its xlow/ylow is the same as the x,y of this gsb
* 2. Build a list of tracks on the other sides belonging to Group 1.
* Take the example of RIGHT side, we will collect
* a. tracks that will end at the LEFT side
* b. tracks that will start at the TOP side
* c. tracks that will start at the BOTTOM side
* 3. Apply switch block patterns to Group 1 (SUBSET, UNIVERSAL, WILTON)
* 4. Build a list of tracks on the other sides belonging to Group 1.
* Take the example of RIGHT side, we will collect
* a. tracks that will bypass at the TOP side
* b. tracks that will bypass at the BOTTOM side
* 5. Apply switch block patterns to Group 2 (SUBSET, UNIVERSAL, WILTON)
***********************************************************************/
t_track2track_map build_gsb_track_to_track_map(const t_rr_graph* rr_graph,
const RRGSB& rr_gsb,
const enum e_switch_block_type sb_type,
const int Fs,
const std::vector<t_segment_inf> segment_inf) {
t_track2track_map track2track_map; /* [0..gsb_side][0..chan_width][track_indices] */
/* Categorize tracks into 3 groups:
* (1) tracks will start here
* (2) tracks will end here
* (2) tracks will just pass through the SB */
t_track_group start_tracks; /* [0..gsb_side][track_indices] */
t_track_group end_tracks; /* [0..gsb_side][track_indices] */
t_track_group pass_tracks; /* [0..gsb_side][track_indices] */
/* resize to the number of sides */
start_tracks.resize(rr_gsb.get_num_sides());
end_tracks.resize(rr_gsb.get_num_sides());
pass_tracks.resize(rr_gsb.get_num_sides());
/* Walk through each side */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
Side side_manager(side);
enum e_side gsb_side = side_manager.get_side();
/* Build a list of tracks that will start from this side */
for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) {
/* check if this track will start from here */
enum e_track_status track_status = determine_track_status_of_gsb(rr_gsb, gsb_side, inode);
switch (track_status) {
case TRACK_START:
/* update starting track list */
start_tracks[gsb_side].push_back(inode);
break;
case TRACK_END:
/* Update end track list */
end_tracks[gsb_side].push_back(inode);
break;
case TRACK_PASS:
/* We need to check Switch block population of this track
* The track node will not be considered if there supposed to be no SB at this position
*/
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);
}
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d]) Invalid track status!\n",
__FILE__, __LINE__);
exit(1);
}
}
}
/* Allocate track2track map */
track2track_map.resize(rr_gsb.get_num_sides());
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
Side side_manager(side);
enum e_side gsb_side = side_manager.get_side();
/* allocate track2track_map[gsb_side] */
track2track_map[side].resize(rr_gsb.get_chan_width(gsb_side));
for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) {
/* allocate track2track_map[gsb_side][inode] */
track2track_map[side][inode].clear();
}
}
/* For Group 1: we build connections between end_tracks and start_tracks*/
build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb,
sb_type, Fs,
end_tracks, start_tracks,
&track2track_map);
/* For Group 2: we build connections between end_tracks and start_tracks*/
/* Currently, I use the same Switch Block pattern for the passing tracks and end tracks,
* TODO: This can be improved with different patterns!
*/
build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb,
sb_type, Fs,
pass_tracks, start_tracks,
&track2track_map);
return track2track_map;
}

View File

@ -1,20 +0,0 @@
#ifndef RR_GRAPH_TILEABLE_SBOX_H
#define RR_GRAPH_TILEABLE_SBOX_H
#include <vector>
#include "vtr_ndmatrix.h"
#include "rr_blocks.h"
#include "fpga_x2p_types.h"
typedef std::vector<std::vector<std::vector<int>>> t_track2track_map;
t_track2track_map build_gsb_track_to_track_map(const t_rr_graph* rr_graph,
const RRGSB& rr_gsb,
const enum e_switch_block_type sb_type,
const int Fs,
const std::vector<t_segment_inf> segment_inf);
#endif

View File

@ -125,6 +125,24 @@ std::vector<size_t> RRChan::get_segment_ids() const {
return seg_list;
}
/* Get a list of nodes whose segment_id is specified */
std::vector<size_t> RRChan::get_node_ids_by_segment_ids(size_t seg_id) const {
std::vector<size_t> node_list;
/* make sure a clean start */
node_list.clear();
/* Traverse node_segments */
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
/* Try to find the node_segment id in the list */
if ( seg_id == node_segments_[inode] ) {
node_list.push_back(inode);
}
}
return node_list;
}
/* Mutators */
void RRChan::set(const RRChan& rr_chan) {
/* Ensure a clean start */
@ -611,6 +629,22 @@ RRChan RRGSB::get_chan(enum e_side side) const {
return chan_node_[side_manager.to_size_t()];
}
/* Get a list of segments used in this routing channel */
std::vector<size_t> RRGSB::get_chan_segment_ids(enum e_side side) 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) );
return get_chan(side).get_segment_ids();
}
/* Get a list of rr_nodes whose sed_id is specified */
std::vector<size_t> RRGSB::get_chan_node_ids_by_segment_ids(enum e_side side, size_t seg_id) const {
return get_chan(side).get_node_ids_by_segment_ids(seg_id);
}
/* get a rr_node at a given side and track_id */
t_rr_node* RRGSB::get_chan_node(enum e_side side, size_t track_id) const {
Side side_manager(side);
@ -1302,6 +1336,24 @@ enum e_side RRGSB::get_cb_chan_side(t_rr_type cb_type) const {
}
}
/* Get the side of routing channel in the GSB according to the side of IPIN */
enum e_side RRGSB::get_cb_chan_side(enum e_side ipin_side) const {
switch(ipin_side) {
case TOP:
return LEFT;
case RIGHT:
return TOP;
case BOTTOM:
return LEFT;
case LEFT:
return TOP;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])Invalid type of ipin_side!\n",
__FILE__, __LINE__);
exit(1);
}
}
DeviceCoordinator RRGSB::get_side_block_coordinator(enum e_side side) const {
Side side_manager(side);
@ -1337,6 +1389,13 @@ DeviceCoordinator RRGSB::get_side_block_coordinator(enum e_side side) const {
return ret;
}
DeviceCoordinator RRGSB::get_grid_coordinator() const {
DeviceCoordinator ret(get_sb_x(), get_sb_y());
ret.set_y(ret.get_y() + 1);
return ret;
}
/* Public Accessors Verilog writer */
const char* RRGSB::gen_cb_verilog_routing_track_name(t_rr_type cb_type,
size_t track_id) const {

View File

@ -84,6 +84,7 @@ class RRChan {
int get_node_segment(size_t track_num) const;
bool is_mirror(const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */
std::vector<size_t> get_segment_ids() const; /* Get a list of segments used in this routing channel */
std::vector<size_t> get_node_ids_by_segment_ids(size_t seg_id) const; /* Get a list of segments used in this routing channel */
public: /* Mutators */
void set(const RRChan&); /* copy */
void set_type(t_rr_type type); /* modify type */
@ -188,6 +189,8 @@ class RRGSB {
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 */
RRChan get_chan(enum e_side side) const; /* get a rr_node at a given side and track_id */
std::vector<size_t> get_chan_segment_ids(enum e_side side) const; /* Get a list of segments used in this routing channel */
std::vector<size_t> get_chan_node_ids_by_segment_ids(enum e_side side, size_t seg_id) const; /* Get a list of segments used in this routing channel */
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 */
@ -232,7 +235,9 @@ class RRGSB {
size_t get_cb_y(t_rr_type cb_type) const; /* get the y coordinator of this X/Y-direction block */
DeviceCoordinator get_cb_coordinator(t_rr_type cb_type) const; /* Get the coordinator of the X/Y-direction CB */
enum e_side get_cb_chan_side(t_rr_type cb_type) const; /* get the side of a Connection block */
enum e_side get_cb_chan_side(enum e_side ipin_side) const; /* get the side of a Connection block */
DeviceCoordinator get_side_block_coordinator(enum e_side side) const;
DeviceCoordinator get_grid_coordinator() const;
public: /* Verilog writer */
const char* gen_sb_verilog_module_name() const;
const char* gen_sb_verilog_instance_name() const;

View File

@ -23,15 +23,12 @@ static void check_pass_transistors(int from_node);
/************************ Subroutine definitions ****************************/
void check_rr_graph(INP t_graph_type graph_type, INP t_type_ptr types,
INP int L_nx, INP int L_ny, INP int nodes_per_chan, INP int Fs,
INP int num_seg_types, INP int num_switches,
INP t_segment_inf * segment_inf, INP int global_route_switch,
INP int delayless_switch, INP int wire_to_ipin_switch,
t_seg_details * seg_details, int **Fc_in, int **Fc_out,
int *****opin_to_track_map, int *****ipin_to_track_map,
t_ivec **** track_to_ipin_lookup, t_ivec *** switch_block_conn,
boolean * perturb_ipins) {
void check_rr_graph(INP const t_graph_type graph_type, INP t_type_ptr types,
INP const int L_nx, INP const int L_ny, INP const int nodes_per_chan, INP int Fs,
INP const int num_seg_types, INP const int num_switches,
INP const t_segment_inf * segment_inf, INP const int global_route_switch,
INP const int delayless_switch, INP const int wire_to_ipin_switch,
int **Fc_in, int **Fc_out) {
int *num_edges_from_current_to_node; /* [0..num_rr_nodes-1] */
int *total_edges_to_node; /* [0..num_rr_nodes-1] */

View File

@ -1,26 +1,20 @@
#ifndef CHECK_RR_GRAPH_H
#define CHECK_RR_GRAPH_H
void check_rr_graph(INP t_graph_type graph_type,
void check_rr_graph(INP const t_graph_type graph_type,
INP t_type_ptr types,
INP int L_nx,
INP int L_ny,
INP int nodes_per_chan,
INP int Fs,
INP int num_seg_types,
INP int num_switches,
INP t_segment_inf * segment_inf,
INP int global_route_switch,
INP int delayless_switch,
INP int wire_to_ipin_switch,
t_seg_details * seg_details,
INP const int L_nx,
INP const int L_ny,
INP const int nodes_per_chan,
INP const int Fs,
INP const int num_seg_types,
INP const int num_switches,
INP const t_segment_inf * segment_inf,
INP const int global_route_switch,
INP const int delayless_switch,
INP const int wire_to_ipin_switch,
int ** Fc_in,
int ** Fc_out,
int *****opin_to_track_map,
int *****ipin_to_track_map,
t_ivec **** track_to_ipin_lookup,
t_ivec *** switch_block_conn,
boolean * perturb_ipins);
int ** Fc_out);
void check_node(int inode, enum e_route_type route_type);

View File

@ -458,9 +458,7 @@ void build_rr_graph(INP t_graph_type graph_type, INP int L_num_types,
check_rr_graph(graph_type, types, L_nx, L_ny, nodes_per_chan, Fs,
num_seg_types, num_switches, segment_inf, global_route_switch,
delayless_switch, wire_to_ipin_switch, seg_details, Fc_in, Fc_out,
opin_to_track_map, ipin_to_track_map, track_to_ipin_lookup,
switch_block_conn, perturb_ipins);
delayless_switch, wire_to_ipin_switch, Fc_in, Fc_out);
/* Free all temp structs */
if (seg_details) {
@ -514,9 +512,9 @@ void build_rr_graph(INP t_graph_type graph_type, INP int L_num_types,
}
}
void rr_graph_externals(t_timing_inf timing_inf,
t_segment_inf * segment_inf, int num_seg_types, int nodes_per_chan,
int wire_to_ipin_switch, enum e_base_cost_type base_cost_type) {
void rr_graph_externals(const t_timing_inf timing_inf,
const t_segment_inf * segment_inf, const int num_seg_types, const int nodes_per_chan,
const int wire_to_ipin_switch, const enum e_base_cost_type base_cost_type) {
add_rr_graph_C_from_switches(timing_inf.C_ipin_cblock);
alloc_and_load_rr_indexed_data(segment_inf, num_seg_types, rr_node_indices,
nodes_per_chan, wire_to_ipin_switch, base_cost_type);

View File

@ -59,9 +59,9 @@ alloc_and_load_actual_fc(INP int L_num_types, INP t_type_ptr types,
INP int nodes_per_chan, INP boolean is_Fc_out,
INP enum e_directionality directionality, OUTP boolean * Fc_clipped, INP boolean ignore_Fc_0);
void rr_graph_externals(t_timing_inf timing_inf,
t_segment_inf * segment_inf, int num_seg_types, int nodes_per_chan,
int wire_to_ipin_switch, enum e_base_cost_type base_cost_type);
void rr_graph_externals(const t_timing_inf timing_inf,
const t_segment_inf * segment_inf, const int num_seg_types, const int nodes_per_chan,
const int wire_to_ipin_switch, const enum e_base_cost_type base_cost_type);
/* Xifan Tang: Functions shared by tileable rr_graph generator */

View File

@ -25,7 +25,7 @@ static float get_average_opin_delay(t_ivec *** L_rr_node_indices,
static void load_rr_indexed_data_T_values(int index_start,
int num_indices_to_load, t_rr_type rr_type, int nodes_per_chan,
t_ivec *** L_rr_node_indices, t_segment_inf * segment_inf);
t_ivec *** L_rr_node_indices, const t_segment_inf * segment_inf);
/******************** Subroutine definitions *********************************/
@ -42,7 +42,7 @@ static void load_rr_indexed_data_T_values(int index_start,
* etc. more expensive than others. I give each segment type in an *
* x-channel its own cost_index, and each segment type in a y-channel its *
* own cost_index. */
void alloc_and_load_rr_indexed_data(INP t_segment_inf * segment_inf,
void alloc_and_load_rr_indexed_data(INP const t_segment_inf * segment_inf,
INP int num_segment, INP t_ivec *** L_rr_node_indices,
INP int nodes_per_chan, int wire_to_ipin_switch,
enum e_base_cost_type base_cost_type) {
@ -258,7 +258,7 @@ static float get_average_opin_delay(t_ivec *** L_rr_node_indices,
static void load_rr_indexed_data_T_values(int index_start,
int num_indices_to_load, t_rr_type rr_type, int nodes_per_chan,
t_ivec *** L_rr_node_indices, t_segment_inf * segment_inf) {
t_ivec *** L_rr_node_indices, const t_segment_inf * segment_inf) {
/* Loads the average propagation times through segments of each index type *
* for either all CHANX segment types or all CHANY segment types. It does *

View File

@ -1,3 +1,3 @@
void alloc_and_load_rr_indexed_data(t_segment_inf * segment_inf,
void alloc_and_load_rr_indexed_data(const t_segment_inf * segment_inf,
int num_segment, t_ivec *** L_rr_node_indices, int nodes_per_chan,
int wire_to_ipin_switch, enum e_base_cost_type base_cost_type);

View File

@ -1165,8 +1165,8 @@ void alloc_and_load_idirect_from_blk_pin(t_direct_inf* directs, int num_directs,
* This data structure supplements the the info in the "directs" data structure
* TODO: The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety, should replace with this one
*/
t_clb_to_clb_directs * alloc_and_load_clb_to_clb_directs(INP t_direct_inf *directs,
INP int num_directs) {
t_clb_to_clb_directs * alloc_and_load_clb_to_clb_directs(INP const t_direct_inf *directs,
INP const int num_directs) {
int i, j;
t_clb_to_clb_directs *clb_to_clb_directs;
char *pb_type_name, *port_name;

View File

@ -41,7 +41,7 @@ void alloc_and_load_idirect_from_blk_pin(t_direct_inf* directs, int num_directs,
void parse_direct_pin_name(char * src_string, int line, int * start_pin_index,
int * end_pin_index, char * pb_type_name, char * port_name);
t_clb_to_clb_directs *alloc_and_load_clb_to_clb_directs(INP t_direct_inf *directs, INP int num_directs);
t_clb_to_clb_directs *alloc_and_load_clb_to_clb_directs(INP const t_direct_inf *directs, INP const int num_directs);
void free_cb(t_pb *pb);