refactored clb2clb direct connects for cross-column/row

This commit is contained in:
tangxifan 2019-10-17 23:06:59 -06:00
parent 190449c06f
commit 4171a674b1
3 changed files with 316 additions and 26 deletions

View File

@ -835,6 +835,63 @@ e_side find_grid_border_side(const vtr::Point<size_t>& device_size,
return grid_side;
}
/********************************************************************
* This function try to infer if a grid locates at the border of the
* core FPGA fabric, i.e., TOP/RIGHT/BOTTOM/LEFT sides
* 1. if this grid is on the border and it matches the given side, return true,
* 2. if this grid is in the center, return false
*
* In this function, we assume that the corner grids are actually empty!
*
* +-------+ +----------------------------+ +-------+
* | EMPTY | | TOP side I/O | | EMPTY |
* +-------+ +----------------------------+ +-------+
*
* +-------+ +----------------------------+ +-------+
* | | | TOP | | |
* | | |----------------------------| | |
* | | | | | | | |
* | LEFT | | | | | | RIGHT |
* | side | | LEFT | Core grids | RIGHT| | side |
* | I/O | | | | | | I/O |
* | | | | | | | |
* | | | | | | | |
* | | |---------------------| | | |
* | | | BOTTOM | | | |
* +-------+ +----------------------------+ +-------+
*
* +-------+ +----------------------------+ +-------+
* | EMPTY | | BOTTOM side I/O | | EMPTY |
* +-------+ +----------------------------+ +-------+
*
* Note: for the blocks on the four corners of the core grids
* Please refer to the figure above to infer its border_side
*******************************************************************/
bool is_core_grid_on_given_border_side(const vtr::Point<size_t>& device_size,
const vtr::Point<size_t>& grid_coordinate,
const e_side& border_side) {
if ( (device_size.y() - 2 == grid_coordinate.y())
&& (TOP == border_side) ) {
return true;
}
if ( (device_size.x() - 2 == grid_coordinate.x())
&& (RIGHT == border_side) ) {
return true;
}
if ( (1 == grid_coordinate.y())
&& (BOTTOM == border_side) ) {
return true;
}
if ( (1 == grid_coordinate.x())
&& (LEFT == border_side) ) {
return true;
}
return false;
}
/*********************************************************************
* Generate the port name of a Verilog module describing a pb_type
* The name convention is

View File

@ -151,6 +151,10 @@ std::string generate_grid_physical_block_module_name(const std::string& prefix,
e_side find_grid_border_side(const vtr::Point<size_t>& device_size,
const vtr::Point<size_t>& grid_coordinate);
bool is_core_grid_on_given_border_side(const vtr::Point<size_t>& device_size,
const vtr::Point<size_t>& grid_coordinate,
const e_side& border_side);
std::string generate_pb_type_port_name(t_port* pb_type_port);
std::string generate_fpga_global_io_port_name(const std::string& prefix,

View File

@ -4,6 +4,7 @@
*******************************************************************/
#include <fstream>
#include <map>
#include <algorithm>
#include "vtr_assert.h"
@ -913,7 +914,7 @@ void add_module_nets_clb2clb_direct_connection(ModuleManager& module_manager,
* It can be more generic and thus cover all the grid types,
* such as heterogeneous blocks
*
* This function supports the following types of direct connection:
* This function supports the following type of direct connection:
* 1. Direct connection between grids in the same column or row
* +------+ +------+
* | | | |
@ -928,33 +929,15 @@ void add_module_nets_clb2clb_direct_connection(ModuleManager& module_manager,
* | |
* +------+
*
* 2. Direct connections across columns and rows
* +------+
* | |
* | v
* +------+ | +------+
* | | | | |
* | Grid | | | Grid |
* | | | | |
* +------+ | +------+
* |
* +------+ | +------+
* | | | | |
* | Grid | | | Grid |
* | | | | |
* +------+ | +------+
* | |
* +------+
*
*******************************************************************/
static
void add_top_module_nets_clb2clb_direct_connections(ModuleManager& module_manager,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<std::vector<size_t>>& grid_instance_ids,
const std::vector<t_clb_to_clb_directs>& clb2clb_directs) {
void add_top_module_nets_intra_clb2clb_direct_connections(ModuleManager& module_manager,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<std::vector<size_t>>& grid_instance_ids,
const std::vector<t_clb_to_clb_directs>& clb2clb_directs) {
/* Scan the grid, visit each grid and apply direct connections */
for (size_t ix = 0; ix < device_size.x(); ++ix) {
for (size_t iy = 0; iy < device_size.y(); ++iy) {
@ -996,6 +979,252 @@ void add_top_module_nets_clb2clb_direct_connections(ModuleManager& module_manage
}
}
/********************************************************************
* Find the coordinate of a grid in a specific column
* with a given type
* This function will return the coordinate of the grid that satifies
* the type requirement
*******************************************************************/
static
vtr::Point<size_t> find_grid_coordinate_given_type(const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<vtr::Point<size_t>>& candidate_coords,
t_type_ptr wanted_grid_type) {
for (vtr::Point<size_t> coord : candidate_coords) {
/* If the next column is not longer in device range, we can return */
if (false == is_grid_coordinate_exist_in_device(device_size, coord)) {
continue;
}
if (wanted_grid_type == grids[coord.x()][coord.y()].type) {
return coord;
}
}
/* Return an valid coordinate */
return vtr::Point<size_t>(size_t(-1), size_t(-1));
}
/********************************************************************
* Find the coordinate of the destination clb/heterogeneous block
* considering intra column/row direct connections in core grids
*******************************************************************/
static
vtr::Point<size_t> find_intra_direct_destination_coordinate(const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t> src_coord,
const t_clb_to_clb_directs& direct) {
vtr::Point<size_t> des_coord(size_t(-1), size_t(-1));
t_type_ptr src_grid_type = grids[src_coord.x()][src_coord.y()].type;
std::vector<size_t> x_search_space;
std::vector<size_t> y_search_space;
/* Cross column connection from Bottom to Top on Right
* The next column may NOT have the grid type we want!
* Think about heterogeneous architecture!
* Our search space will start from the next column
* and ends at the RIGHT side of fabric
*/
if (P2P_DIRECT_COLUMN == direct.interconnection_type) {
if (POSITIVE_DIR == direct.x_dir) {
/* By default our search space in x-direction is like
* ----->
*/
for (size_t ix = src_coord.x() + 1; ix < device_size.x() - 1; ++ix) {
x_search_space.push_back(ix);
}
} else {
VTR_ASSERT(NEGATIVE_DIR == direct.x_dir);
/* By default our search space in x-direction is like
* <-----
*/
for (size_t ix = src_coord.x() - 1; ix >= 1; --ix) {
x_search_space.push_back(ix);
}
}
/* By default our search space in y-direction is like
* y_search_space
* |
* |
* v
*/
for (size_t iy = 1 ; iy < device_size.y() - 1; ++iy) {
y_search_space.push_back(iy);
}
if (NEGATIVE_DIR == direct.y_dir) {
std::reverse(y_search_space.begin(), y_search_space.end());
}
}
/* Cross row connection from Bottom to Top on Right
* The next column may NOT have the grid type we want!
* Think about heterogeneous architecture!
* Our search space will start from the next column
* and ends at the RIGHT side of fabric
*/
if (P2P_DIRECT_ROW == direct.interconnection_type) {
if (POSITIVE_DIR == direct.x_dir) {
/* By default our search space in y-direction is like
* |
* |
* v
*/
for (size_t iy = src_coord.y() + 1; iy < device_size.y() - 1; ++iy) {
y_search_space.push_back(iy);
}
} else {
VTR_ASSERT(NEGATIVE_DIR == direct.y_dir);
/* By default our search space in y-direction is like
* ^
* |
* |
*/
for (size_t iy = src_coord.y() - 1; iy >= 1; --iy) {
y_search_space.push_back(iy);
}
}
/* By default our search space in x-direction is like
* x_search_space ------>
*/
for (size_t ix = 1 ; ix < device_size.x() - 1; ++ix) {
x_search_space.push_back(ix);
}
if (NEGATIVE_DIR == direct.x_dir) {
std::reverse(x_search_space.begin(), x_search_space.end());
}
}
for (size_t ix : x_search_space) {
std::vector<vtr::Point<size_t>> next_col_coords;
for (size_t iy : y_search_space) {
next_col_coords.push_back(vtr::Point<size_t>(ix, iy));
}
vtr::Point<size_t> des_coord_cand = find_grid_coordinate_given_type(device_size, grids, next_col_coords, src_grid_type);
/* For a valid coordinate, we can return */
if ( (size_t(-1) != des_coord_cand.x())
&& (size_t(-1) != des_coord_cand.y()) ) {
return des_coord_cand;
}
}
return des_coord;
}
/********************************************************************
* Add module net of clb-to-clb direct connections to module manager
* Note that the direct connections are not limited to CLBs only.
* It can be more generic and thus cover all the grid types,
* such as heterogeneous blocks
*
* This function supports the following type of direct connection:
*
* 1. Direct connections across columns and rows
* +------+
* | |
* | v
* +------+ | +------+
* | | | | |
* | Grid | | | Grid |
* | | | | |
* +------+ | +------+
* |
* +------+ | +------+
* | | | | |
* | Grid | | | Grid |
* | | | | |
* +------+ | +------+
* | |
* +------+
*
* Note that: this will only apply to the core grids!
* I/Os or any blocks on the border of fabric are NOT supported!
*
*******************************************************************/
static
void add_top_module_nets_inter_clb2clb_direct_connections(ModuleManager& module_manager,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<std::vector<size_t>>& grid_instance_ids,
const std::vector<t_clb_to_clb_directs>& clb2clb_directs) {
std::vector<e_side> border_sides = {TOP, RIGHT, BOTTOM, LEFT};
/* Scan the grid, visit each grid and apply direct connections */
for (size_t ix = 1; ix < device_size.x() - 1; ++ix) {
for (size_t iy = 1; iy < device_size.y() - 1; ++iy) {
/* Bypass EMPTY_TYPE*/
if ( (NULL == grids[ix][iy].type)
|| (EMPTY_TYPE == grids[ix][iy].type)) {
continue;
}
/* Bypass any grid with a non-zero offset! They have been visited in the offset=0 case */
if (0 != grids[ix][iy].offset) {
continue;
}
vtr::Point<size_t> src_clb_coord(ix, iy);
/* We only care clb/heterogeneous blocks on the border of core logic! */
for (const e_side& border_side : border_sides) {
if (false == is_core_grid_on_given_border_side(device_size, src_clb_coord, border_side)) {
continue;
}
/* Go through the direct connection list, see if we need intra-column/row connection here */
for (const t_clb_to_clb_directs& direct: clb2clb_directs) {
if ( (P2P_DIRECT_COLUMN != direct.interconnection_type)
&& (P2P_DIRECT_ROW != direct.interconnection_type)) {
continue;
}
/* Bypass unmatched clb type */
if (grids[src_clb_coord.x()][src_clb_coord.y()].type != direct.from_clb_type) {
continue;
}
/* Reach here it means we may of great possibility to add direct connection */
/* Find the coordinate of the destination clb */
vtr::Point<size_t> des_clb_coord = find_intra_direct_destination_coordinate(device_size, grids, src_clb_coord, direct);
/* If destination clb is valid, we should add something */
if ( (size_t(-1) == des_clb_coord.x())
|| (size_t(-1) == des_clb_coord.y()) ) {
continue;
}
add_module_nets_clb2clb_direct_connection(module_manager, top_module, circuit_lib,
device_size, grids, grid_instance_ids,
src_clb_coord, des_clb_coord,
direct);
}
}
}
}
}
/********************************************************************
* Add module net of clb-to-clb direct connections to module manager
* Note that the direct connections are not limited to CLBs only.
* It can be more generic and thus cover all the grid types,
* such as heterogeneous blocks
*******************************************************************/
static
void add_top_module_nets_clb2clb_direct_connections(ModuleManager& module_manager,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<std::vector<size_t>>& grid_instance_ids,
const std::vector<t_clb_to_clb_directs>& clb2clb_directs) {
add_top_module_nets_intra_clb2clb_direct_connections(module_manager, top_module, circuit_lib,
device_size, grids, grid_instance_ids,
clb2clb_directs);
add_top_module_nets_inter_clb2clb_direct_connections(module_manager, top_module, circuit_lib,
device_size, grids, grid_instance_ids,
clb2clb_directs);
}
/********************************************************************
* Print the top-level module for the FPGA fabric in Verilog format
* This function will