basically finished the coding of tileable rr_graph generator. testing to go
This commit is contained in:
parent
e7f2bd3b7c
commit
baab9c4a21
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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] */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue