tile direct supports inter-column/inter-row direct connections

This commit is contained in:
tangxifan 2020-02-15 13:42:53 -07:00
parent 213c611c0b
commit 539f13720a
7 changed files with 590 additions and 121 deletions

View File

@ -53,7 +53,7 @@ bool is_vpr_rr_graph_supported(const RRGraph& rr_graph) {
* - physical pb_graph nodes and pb_graph pins
* - circuit models for global routing architecture
*******************************************************************/
void link_arch(OpenfpgaContext& openfpga_context,
void link_arch(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
vtr::ScopedStartFinishTimer timer("Link OpenFPGA architecture to VPR architecture");
@ -65,8 +65,8 @@ void link_arch(OpenfpgaContext& openfpga_context,
* - mode selection bits for pb_type and pb interconnect
* - circuit models for pb_type and pb interconnect
*/
annotate_pb_types(g_vpr_ctx.device(), openfpga_context.arch(),
openfpga_context.mutable_vpr_device_annotation(),
annotate_pb_types(g_vpr_ctx.device(), openfpga_ctx.arch(),
openfpga_ctx.mutable_vpr_device_annotation(),
cmd_context.option_enable(cmd, opt_verbose));
/* Annotate pb_graph_nodes
@ -75,21 +75,21 @@ void link_arch(OpenfpgaContext& openfpga_context,
* - Bind pins from operating pb_graph_node to their physical pb_graph_node pins
*/
annotate_pb_graph(g_vpr_ctx.device(),
openfpga_context.mutable_vpr_device_annotation(),
openfpga_ctx.mutable_vpr_device_annotation(),
cmd_context.option_enable(cmd, opt_verbose));
/* Annotate routing architecture to circuit library */
annotate_rr_graph_circuit_models(g_vpr_ctx.device(),
openfpga_context.arch(),
openfpga_context.mutable_vpr_device_annotation(),
openfpga_ctx.arch(),
openfpga_ctx.mutable_vpr_device_annotation(),
cmd_context.option_enable(cmd, opt_verbose));
/* Annotate net mapping to each rr_node
*/
openfpga_context.mutable_vpr_routing_annotation().init(g_vpr_ctx.device().rr_graph);
openfpga_ctx.mutable_vpr_routing_annotation().init(g_vpr_ctx.device().rr_graph);
annotate_rr_node_nets(g_vpr_ctx.device(), g_vpr_ctx.clustering(), g_vpr_ctx.routing(),
openfpga_context.mutable_vpr_routing_annotation(),
openfpga_ctx.mutable_vpr_routing_annotation(),
cmd_context.option_enable(cmd, opt_verbose));
/* Build the routing graph annotation
@ -101,17 +101,16 @@ void link_arch(OpenfpgaContext& openfpga_context,
}
annotate_device_rr_gsb(g_vpr_ctx.device(),
openfpga_context.mutable_device_rr_gsb(),
openfpga_ctx.mutable_device_rr_gsb(),
cmd_context.option_enable(cmd, opt_verbose));
/* Build multiplexer library */
openfpga_context.mutable_mux_lib() = build_device_mux_library(g_vpr_ctx.device(),
const_cast<const OpenfpgaContext&>(openfpga_context));
openfpga_ctx.mutable_mux_lib() = build_device_mux_library(g_vpr_ctx.device(),
const_cast<const OpenfpgaContext&>(openfpga_ctx));
/* Build tile direct annotation */
openfpga_context.mutable_tile_direct() = build_device_tile_direct(g_vpr_ctx.device(),
openfpga_context.arch().arch_direct,
openfpga_context.arch().circuit_lib);
openfpga_ctx.mutable_tile_direct() = build_device_tile_direct(g_vpr_ctx.device(),
openfpga_ctx.arch().arch_direct);
}

View File

@ -0,0 +1,151 @@
/********************************************************************
* This file includes functions that are used to add module nets
* for direct connections between CLBs/heterogeneous blocks
* in the top-level module of a FPGA fabric
*******************************************************************/
#include <algorithm>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_port.h"
/* Headers from vpr library */
#include "vpr_utils.h"
#include "openfpga_reserved_words.h"
#include "openfpga_naming.h"
#include "module_manager_utils.h"
#include "build_top_module_directs.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Add module net for one direction connection between two CLBs or
* two grids
* This function will
* 1. find the pin id and port id of the source clb port in module manager
* 2. find the pin id and port id of the destination clb port in module manager
* 3. add a direct connection module to the top module
* 4. add a first module net and configure its source and sink,
* in order to connect the source pin to the input of the top module
* 4. add a second module net and configure its source and sink,
* in order to connect the sink pin to the output of the top module
*******************************************************************/
static
void add_module_nets_tile_direct_connection(ModuleManager& module_manager,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const DeviceGrid& grids,
const vtr::Matrix<size_t>& grid_instance_ids,
const TileDirect& tile_direct,
const TileDirectId& tile_direct_id,
const ArchDirect& arch_direct) {
vtr::Point<size_t> device_size(grids.width(), grids.height());
/* Find the module name of source clb */
vtr::Point<size_t> src_clb_coord = tile_direct.from_tile_coordinate(tile_direct_id);
t_physical_tile_type_ptr src_grid_type = grids[src_clb_coord.x()][src_clb_coord.y()].type;
e_side src_grid_border_side = find_grid_border_side(device_size, src_clb_coord);
std::string src_module_name_prefix(GRID_MODULE_NAME_PREFIX);
std::string src_module_name = generate_grid_block_module_name(src_module_name_prefix, std::string(src_grid_type->name), is_io_type(src_grid_type), src_grid_border_side);
ModuleId src_grid_module = module_manager.find_module(src_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(src_grid_module));
/* Record the instance id */
size_t src_grid_instance = grid_instance_ids[src_clb_coord.x()][src_clb_coord.y()];
/* Find the module name of sink clb */
vtr::Point<size_t> des_clb_coord = tile_direct.to_tile_coordinate(tile_direct_id);
t_physical_tile_type_ptr sink_grid_type = grids[des_clb_coord.x()][des_clb_coord.y()].type;
e_side sink_grid_border_side = find_grid_border_side(device_size, des_clb_coord);
std::string sink_module_name_prefix(GRID_MODULE_NAME_PREFIX);
std::string sink_module_name = generate_grid_block_module_name(sink_module_name_prefix, std::string(sink_grid_type->name), is_io_type(sink_grid_type), sink_grid_border_side);
ModuleId sink_grid_module = module_manager.find_module(sink_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(sink_grid_module));
/* Record the instance id */
size_t sink_grid_instance = grid_instance_ids[des_clb_coord.x()][des_clb_coord.y()];
/* Find the module id of a direct connection module */
CircuitModelId direct_circuit_model = arch_direct.circuit_model(tile_direct.arch_direct(tile_direct_id));
std::string direct_module_name = circuit_lib.model_name(direct_circuit_model);
ModuleId direct_module = module_manager.find_module(direct_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(direct_module));
/* Find inputs and outputs of the direct circuit module */
std::vector<CircuitPortId> direct_input_ports = circuit_lib.model_ports_by_type(direct_circuit_model, CIRCUIT_MODEL_PORT_INPUT, true);
VTR_ASSERT(1 == direct_input_ports.size());
ModulePortId direct_input_port_id = module_manager.find_module_port(direct_module, circuit_lib.port_prefix(direct_input_ports[0]));
VTR_ASSERT(true == module_manager.valid_module_port_id(direct_module, direct_input_port_id));
VTR_ASSERT(1 == module_manager.module_port(direct_module, direct_input_port_id).get_width());
std::vector<CircuitPortId> direct_output_ports = circuit_lib.model_ports_by_type(direct_circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
VTR_ASSERT(1 == direct_output_ports.size());
ModulePortId direct_output_port_id = module_manager.find_module_port(direct_module, circuit_lib.port_prefix(direct_output_ports[0]));
VTR_ASSERT(true == module_manager.valid_module_port_id(direct_module, direct_output_port_id));
VTR_ASSERT(1 == module_manager.module_port(direct_module, direct_output_port_id).get_width());
/* Generate the pin name of source port/pin in the grid */
e_side src_pin_grid_side = tile_direct.from_tile_side(tile_direct_id);
size_t src_tile_pin = tile_direct.from_tile_pin(tile_direct_id);
size_t src_pin_width = grids[src_clb_coord.x()][src_clb_coord.y()].type->pin_width_offset[src_tile_pin];
size_t src_pin_height = grids[src_clb_coord.x()][src_clb_coord.y()].type->pin_height_offset[src_tile_pin];
std::string src_port_name = generate_grid_port_name(src_clb_coord, src_pin_width, src_pin_height, src_pin_grid_side, src_tile_pin, false);
ModulePortId src_port_id = module_manager.find_module_port(src_grid_module, src_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module, src_port_id));
VTR_ASSERT(1 == module_manager.module_port(src_grid_module, src_port_id).get_width());
/* Generate the pin name of sink port/pin in the grid */
e_side sink_pin_grid_side = tile_direct.to_tile_side(tile_direct_id);
size_t sink_tile_pin = tile_direct.to_tile_pin(tile_direct_id);
size_t sink_pin_width = grids[des_clb_coord.x()][des_clb_coord.y()].type->pin_width_offset[src_tile_pin];
size_t sink_pin_height = grids[des_clb_coord.x()][des_clb_coord.y()].type->pin_height_offset[src_tile_pin];
std::string sink_port_name = generate_grid_port_name(des_clb_coord, sink_pin_width, sink_pin_height, sink_pin_grid_side, sink_tile_pin, false);
ModulePortId sink_port_id = module_manager.find_module_port(sink_grid_module, sink_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(sink_grid_module, sink_port_id));
VTR_ASSERT(1 == module_manager.module_port(sink_grid_module, sink_port_id).get_width());
/* Add a submodule of direct connection module to the top-level module */
size_t direct_instance_id = module_manager.num_instance(top_module, direct_module);
module_manager.add_child_module(top_module, direct_module);
/* Create the 1st module net */
ModuleNetId net_direct_src = module_manager.create_module_net(top_module);
/* Connect the wire between src_pin of clb and direct_instance input*/
module_manager.add_module_net_source(top_module, net_direct_src, src_grid_module, src_grid_instance, src_port_id, 0);
module_manager.add_module_net_sink(top_module, net_direct_src, direct_module, direct_instance_id, direct_input_port_id, 0);
/* Create the 2nd module net */
ModuleNetId net_direct_sink = module_manager.create_module_net(top_module);
/* Connect the wire between direct_instance output and sink_pin of clb */
module_manager.add_module_net_source(top_module, net_direct_sink, direct_module, direct_instance_id, direct_output_port_id, 0);
module_manager.add_module_net_sink(top_module, net_direct_sink, sink_grid_module, sink_grid_instance, sink_port_id, 0);
}
/********************************************************************
* 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
*******************************************************************/
void add_top_module_nets_tile_direct_connections(ModuleManager& module_manager,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const DeviceGrid& grids,
const vtr::Matrix<size_t>& grid_instance_ids,
const TileDirect& tile_direct,
const ArchDirect& arch_direct) {
for (const TileDirectId& tile_direct_id : tile_direct.directs()) {
add_module_nets_tile_direct_connection(module_manager, top_module, circuit_lib,
grids, grid_instance_ids,
tile_direct, tile_direct_id,
arch_direct);
}
}
} /* end namespace openfpga */

View File

@ -0,0 +1,33 @@
#ifndef BUILD_TOP_MODULE_DIRECTS_H
#define BUILD_TOP_MODULE_DIRECTS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <vector>
#include "vtr_geometry.h"
#include "vtr_ndmatrix.h"
#include "arch_direct.h"
#include "tile_direct.h"
#include "device_grid.h"
#include "module_manager.h"
#include "circuit_library.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void add_top_module_nets_tile_direct_connections(ModuleManager& module_manager,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const DeviceGrid& grids,
const vtr::Matrix<size_t>& grid_instance_ids,
const TileDirect& tile_direct,
const ArchDirect& arch_direct);
} /* end namespace openfpga */
#endif

View File

@ -119,26 +119,250 @@ std::vector<size_t> find_physical_tile_pin_id(t_physical_tile_type_ptr physical_
return pin_ids;
}
/********************************************************************
* Check if the grid coorindate given is in the device grid range
*******************************************************************/
static
bool is_grid_coordinate_exist_in_device(const DeviceGrid& device_grid,
const vtr::Point<size_t>& grid_coordinate) {
return (grid_coordinate < vtr::Point<size_t>(device_grid.width(), device_grid.height()));
}
/********************************************************************
* 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 DeviceGrid& grids,
const std::vector<vtr::Point<size_t>>& candidate_coords,
const std::string& wanted_grid_type_name) {
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(grids, coord)) {
continue;
}
if (wanted_grid_type_name == std::string(grids[coord.x()][coord.y()].type->name)) {
return coord;
}
}
/* Return an valid coordinate */
return vtr::Point<size_t>(grids.width(), grids.height());
}
/********************************************************************
* Find the coordinate of the destination clb/heterogeneous block
* considering intra column/row direct connections in core grids
*******************************************************************/
static
vtr::Point<size_t> find_inter_direct_destination_coordinate(const DeviceGrid& grids,
const vtr::Point<size_t>& src_coord,
const std::string des_tile_type_name,
const ArchDirect& arch_direct,
const ArchDirectId& arch_direct_id) {
vtr::Point<size_t> des_coord(grids.width(), grids.height());
std::vector<size_t> first_search_space;
std::vector<size_t> second_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 (INTER_COLUMN == arch_direct.type(arch_direct_id)) {
if (POSITIVE_DIR == arch_direct.x_dir(arch_direct_id)) {
/* Our first search space will be in x-direction:
*
* x ... nx
* +-----+
* |Grid | ----->
* +-----+
*/
for (size_t ix = src_coord.x() + 1; ix < grids.width() - 1; ++ix) {
first_search_space.push_back(ix);
}
} else {
VTR_ASSERT(NEGATIVE_DIR == arch_direct.x_dir(arch_direct_id));
/* Our first search space will be in x-direction:
*
* 1 ... x
* +-----+
* < -------|Grid |
* +-----+
*/
for (size_t ix = src_coord.x() - 1; ix >= 1; --ix) {
first_search_space.push_back(ix);
}
}
/* Our second search space will be in y-direction:
*
* +------+
* | Grid | ny
* +------+
* | .
* | .
* v .
* +------+
* | Grid | 1
* +------+
*/
for (size_t iy = 1 ; iy < grids.height() - 1; ++iy) {
second_search_space.push_back(iy);
}
/* For negative direction, our second search space will be in y-direction:
*
* +------+
* | Grid | ny
* +------+
* ^ .
* | .
* | .
* +------+
* | Grid | 1
* +------+
*/
if (NEGATIVE_DIR == arch_direct.y_dir(arch_direct_id)) {
std::reverse(second_search_space.begin(), second_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 (INTER_ROW == arch_direct.type(arch_direct_id)) {
if (POSITIVE_DIR == arch_direct.y_dir(arch_direct_id)) {
/* Our first search space will be in y-direction:
*
* +------+
* | Grid | ny
* +------+
* ^ .
* | .
* | .
* +------+
* | Grid | y
* +------+
*/
for (size_t iy = src_coord.y() + 1; iy < grids.height() - 1; ++iy) {
first_search_space.push_back(iy);
}
} else {
VTR_ASSERT(NEGATIVE_DIR == arch_direct.y_dir(arch_direct_id));
/* For negative y-direction,
* Our first search space will be in y-direction:
*
* +------+
* | Grid | ny
* +------+
* | .
* | .
* v .
* +------+
* | Grid | y
* +------+
*/
for (size_t iy = src_coord.y() - 1; iy >= 1; --iy) {
first_search_space.push_back(iy);
}
}
/* Our second search space will be in x-direction:
*
* 1 ... nx
* +------+ +------+
* | Grid |------>| Grid |
* +------+ +------+
*/
for (size_t ix = 1 ; ix < grids.width() - 1; ++ix) {
second_search_space.push_back(ix);
}
/* For negative direction,
* our second search space will be in x-direction:
*
* 1 ... nx
* +------+ +------+
* | Grid |<------| Grid |
* +------+ +------+
*/
if (NEGATIVE_DIR == arch_direct.x_dir(arch_direct_id)) {
std::reverse(second_search_space.begin(), second_search_space.end());
}
}
for (size_t ix : first_search_space) {
std::vector<vtr::Point<size_t>> next_col_row_coords;
for (size_t iy : second_search_space) {
if (INTER_COLUMN == arch_direct.type(arch_direct_id)) {
next_col_row_coords.push_back(vtr::Point<size_t>(ix, iy));
} else {
VTR_ASSERT(INTER_ROW == arch_direct.type(arch_direct_id));
/* For cross-row connection, our search space is flipped */
next_col_row_coords.push_back(vtr::Point<size_t>(iy, ix));
}
}
vtr::Point<size_t> des_coord_cand = find_grid_coordinate_given_type(grids, next_col_row_coords, des_tile_type_name);
/* For a valid coordinate, we can return */
if (true == is_grid_coordinate_exist_in_device(grids, des_coord_cand)) {
return des_coord_cand;
}
}
return des_coord;
}
/***************************************************************************************
* Report error for port matching failure
***************************************************************************************/
static
void report_direct_from_port_and_to_port_mismatch(const t_direct_inf& vpr_direct,
const BasicPort& from_tile_port,
const BasicPort& to_tile_port) {
VTR_LOG_ERROR("From_port '%s[%lu:%lu] of direct '%s' does not match to_port '%s[%lu:%lu]'!\n",
from_tile_port.get_name().c_str(),
from_tile_port.get_lsb(),
from_tile_port.get_msb(),
vpr_direct.name,
to_tile_port.get_name().c_str(),
to_tile_port.get_lsb(),
to_tile_port.get_msb());
}
/***************************************************************************************
* Build the point-to-point direct connections based on
* - original VPR arch definition
* This is limited to the inner-column and inner-row connections
* 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
*
* Build the inner-column and inner-row connections
*
* +------+
* | Tile |
* +------+ +------+ +------+
* | or | Tile |--->| Tile |
* v +------+ +------+
* This function supports the following type of direct connection:
* 1. Direct connection between tiles in the same column or row
* +------+ +------+
* | | | |
* | Tile |----->| Tile |
* | | | |
* +------+ +------+
* | direction connection
* v
* +------+
* | |
* | Tile |
* | |
* +------+
*
***************************************************************************************/
static
void build_inner_column_row_tile_direct(TileDirect& tile_direct,
t_direct_inf& vpr_direct,
const t_direct_inf& vpr_direct,
const DeviceContext& device_ctx,
const ArchDirectId& arch_direct_id) {
/* Get the source tile and pin information */
@ -166,10 +390,10 @@ void build_inner_column_row_tile_direct(TileDirect& tile_direct,
/* Try to find the pin in this tile */
std::vector<size_t> from_pins = find_physical_tile_pin_id(device_ctx.grid[x][y].type,
device_ctx.grid[x][y].width_offset,
device_ctx.grid[x][y].height_offset,
from_tile_port,
vpr_direct.from_side);
device_ctx.grid[x][y].width_offset,
device_ctx.grid[x][y].height_offset,
from_tile_port,
vpr_direct.from_side);
/* If nothing found, we can continue */
if (0 == from_pins.size()) {
continue;
@ -178,8 +402,7 @@ void build_inner_column_row_tile_direct(TileDirect& tile_direct,
/* We should try to the sink grid for inner-column/row direct connections */
vtr::Point<size_t> from_grid_coord(x, y);
vtr::Point<size_t> to_grid_coord(x + vpr_direct.x_offset, y + vpr_direct.y_offset);
if ((to_grid_coord.x() >= device_ctx.grid.width())
|| (to_grid_coord.y() >= device_ctx.grid.height())) {
if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, to_grid_coord)) {
continue;
}
@ -200,61 +423,60 @@ void build_inner_column_row_tile_direct(TileDirect& tile_direct,
/* If from port and to port do not match in sizes, error out */
if (from_pins.size() != to_pins.size()) {
VTR_LOG_ERROR("From_port '%s[%lu:%lu] of direct '%s' does not match to_port '%s[%lu:%lu]'!\n",
from_tile_port.get_name().c_str(),
from_tile_port.get_lsb(),
from_tile_port.get_msb(),
vpr_direct.name,
to_tile_port.get_name().c_str(),
to_tile_port.get_lsb(),
to_tile_port.get_msb());
report_direct_from_port_and_to_port_mismatch(vpr_direct, from_tile_port, to_tile_port);
exit(1);
}
/* Now add the tile direct */
for (size_t ipin = 0; ipin < from_pins.size(); ++ipin) {
TileDirectId tile_direct_id = tile_direct.add_direct(device_ctx.grid[x][y].type,
from_grid_coord, vpr_direct.from_side, from_pins[ipin],
device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type,
TileDirectId tile_direct_id = tile_direct.add_direct(from_grid_coord, vpr_direct.from_side, from_pins[ipin],
to_grid_coord, vpr_direct.to_side, to_pins[ipin]);
tile_direct.set_arch_direct_id(tile_direct_id, arch_direct_id);
}
}
}
}
/***************************************************************************************
/********************************************************************
* Build the point-to-point direct connections based on
* - OpenFPGA arch definition
* This is limited to the inter-column and inter-row connections
*
* Build the inter-column and inter-row connections
* 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
*
* +------+ +------+
* | Tile | | Tile |
* +------+ +------+
* | ^
* | |
* +-------------
* This function supports the following type of direct connection:
*
* +------+
* | Tile |-------+
* +------+ |
* |
* +------+ |
* | Tile |<------+
* +------+
*
* 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 build_inter_column_row_tile_direct(TileDirect& tile_direct,
t_direct_inf& vpr_direct,
const t_direct_inf& vpr_direct,
const DeviceContext& device_ctx,
const ArchDirect& arch_direct,
const ArchDirectId& arch_direct_id,
const CircuitLibrary& circuit_lib) {
const ArchDirectId& arch_direct_id) {
/* Get the source tile and pin information */
std::string from_tile_name = parse_direct_tile_name(std::string(vpr_direct.from_pin));
PortParser from_tile_port_parser(std::string(vpr_direct.from_pin));
@ -265,42 +487,63 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct,
PortParser to_tile_port_parser(std::string(vpr_direct.to_pin));
const BasicPort& to_tile_port = to_tile_port_parser.port();
/* Walk through the device fabric and find the grid that fit the source */
for (size_t x = 0; x < device_ctx.grid.width(); ++x) {
for (size_t y = 0; y < device_ctx.grid.height(); ++y) {
/* Bypass empty grid */
if (true == is_empty_type(device_ctx.grid[x][y].type)) {
continue;
/* Go through the direct connection list, see if we need intra-column/row connection here */
if ( (INTER_COLUMN != arch_direct.type(arch_direct_id))
&& (INTER_ROW != arch_direct.type(arch_direct_id))) {
return;
}
/* For cross-column connection, we will search the first valid grid in each column
* from y = 1 to y = ny
*
* +------+
* | Grid | y=ny
* +------+
* ^
* | search direction (when y_dir is negative)
* ...
* |
* +------+
* | Grid | y=1
* +------+
*
*/
if (INTER_COLUMN == arch_direct.type(arch_direct_id)) {
for (size_t ix = 1; ix < device_ctx.grid.width() - 1; ++ix) {
std::vector<vtr::Point<size_t>> next_col_src_grid_coords;
/* For negative y- direction, we should start from y = ny */
for (size_t iy = 1; iy < device_ctx.grid.height() - 1; ++iy) {
next_col_src_grid_coords.push_back(vtr::Point<size_t>(ix, iy));
}
/* For positive y- direction, we should start from y = 1 */
if (POSITIVE_DIR == arch_direct.y_dir(arch_direct_id)) {
std::reverse(next_col_src_grid_coords.begin(), next_col_src_grid_coords.end());
}
/* Bypass the grid that does not fit the from_tile name */
if (from_tile_name != std::string(device_ctx.grid[x][y].type->name)) {
vtr::Point<size_t> from_grid_coord = find_grid_coordinate_given_type(device_ctx.grid, next_col_src_grid_coords, from_tile_name);
/* Skip if we do not have a valid coordinate for source CLB/heterogeneous block */
if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, from_grid_coord)) {
continue;
}
/* Try to find the pin in this tile */
std::vector<size_t> from_pins = find_physical_tile_pin_id(device_ctx.grid[x][y].type,
device_ctx.grid[x][y].width_offset,
device_ctx.grid[x][y].height_offset,
std::vector<size_t> from_pins = find_physical_tile_pin_id(device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].type,
device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].width_offset,
device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].height_offset,
from_tile_port,
vpr_direct.from_side);
/* If nothing found, we can continue */
if (0 == from_pins.size()) {
continue;
}
/* We should try to the sink grid for inner-column/row direct connections */
vtr::Point<size_t> from_grid_coord(x, y);
vtr::Point<size_t> to_grid_coord(x + vpr_direct.x_offset, y + vpr_direct.y_offset);
if ((to_grid_coord.x() >= device_ctx.grid.width())
|| (to_grid_coord.y() >= device_ctx.grid.height())) {
continue;
/* For a valid coordinate, we can find the coordinate of the destination clb */
vtr::Point<size_t> to_grid_coord = find_inter_direct_destination_coordinate(device_ctx.grid, from_grid_coord, to_tile_name, arch_direct, arch_direct_id);
/* If destination clb is valid, we should add something */
if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, to_grid_coord)) {
continue;
}
/* Bypass the grid that does not fit the from_tile name */
if (to_tile_name != std::string(device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type->name)) {
continue;
}
/* Try to find the pin in this tile */
std::vector<size_t> to_pins = find_physical_tile_pin_id(device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type,
device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset,
@ -314,26 +557,88 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct,
/* If from port and to port do not match in sizes, error out */
if (from_pins.size() != to_pins.size()) {
VTR_LOG_ERROR("From_port '%s[%lu:%lu] of direct '%s' does not match to_port '%s[%lu:%lu]'!\n",
from_tile_port.get_name().c_str(),
from_tile_port.get_lsb(),
from_tile_port.get_msb(),
vpr_direct.name,
to_tile_port.get_name().c_str(),
to_tile_port.get_lsb(),
to_tile_port.get_msb());
report_direct_from_port_and_to_port_mismatch(vpr_direct, from_tile_port, to_tile_port);
exit(1);
}
/* Now add the tile direct */
for (size_t ipin = 0; ipin < from_pins.size(); ++ipin) {
TileDirectId tile_direct_id = tile_direct.add_direct(device_ctx.grid[x][y].type,
from_grid_coord, vpr_direct.from_side, from_pins[ipin],
device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type,
TileDirectId tile_direct_id = tile_direct.add_direct(from_grid_coord, vpr_direct.from_side, from_pins[ipin],
to_grid_coord, vpr_direct.to_side, to_pins[ipin]);
tile_direct.set_arch_direct_id(tile_direct_id, arch_direct_id);
}
}
return; /* Go to next direct type */
}
/* Reach here, it must be a cross-row connection */
VTR_ASSERT(INTER_ROW == arch_direct.type(arch_direct_id));
/* For cross-row connection, we will search the first valid grid in each column
* from x = 1 to x = nx
*
* x=1 x=nx
* +------+ +------+
* | Grid | <--- ... ---- | Grid |
* +------+ +------+
*
*/
for (size_t iy = 1; iy < device_ctx.grid.height() - 1; ++iy) {
std::vector<vtr::Point<size_t>> next_col_src_grid_coords;
/* For negative x- direction, we should start from x = nx */
for (size_t ix = 1; ix < device_ctx.grid.width() - 1; ++ix) {
next_col_src_grid_coords.push_back(vtr::Point<size_t>(ix, iy));
}
/* For positive x- direction, we should start from x = 1 */
if (POSITIVE_DIR == arch_direct.x_dir(arch_direct_id)) {
std::reverse(next_col_src_grid_coords.begin(), next_col_src_grid_coords.end());
}
vtr::Point<size_t> from_grid_coord = find_grid_coordinate_given_type(device_ctx.grid, next_col_src_grid_coords, from_tile_name);
/* Skip if we do not have a valid coordinate for source CLB/heterogeneous block */
if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, from_grid_coord)) {
continue;
}
/* Try to find the pin in this tile */
std::vector<size_t> from_pins = find_physical_tile_pin_id(device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].type,
device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].width_offset,
device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].height_offset,
from_tile_port,
vpr_direct.from_side);
/* If nothing found, we can continue */
if (0 == from_pins.size()) {
continue;
}
/* For a valid coordinate, we can find the coordinate of the destination clb */
vtr::Point<size_t> to_grid_coord = find_inter_direct_destination_coordinate(device_ctx.grid, from_grid_coord, to_tile_name, arch_direct, arch_direct_id);
/* If destination clb is valid, we should add something */
if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, to_grid_coord)) {
continue;
}
/* Try to find the pin in this tile */
std::vector<size_t> to_pins = find_physical_tile_pin_id(device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type,
device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset,
device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset,
to_tile_port,
vpr_direct.to_side);
/* If nothing found, we can continue */
if (0 == to_pins.size()) {
continue;
}
/* If from port and to port do not match in sizes, error out */
if (from_pins.size() != to_pins.size()) {
report_direct_from_port_and_to_port_mismatch(vpr_direct, from_tile_port, to_tile_port);
exit(1);
}
/* Now add the tile direct */
for (size_t ipin = 0; ipin < from_pins.size(); ++ipin) {
TileDirectId tile_direct_id = tile_direct.add_direct(from_grid_coord, vpr_direct.from_side, from_pins[ipin],
to_grid_coord, vpr_direct.to_side, to_pins[ipin]);
tile_direct.set_arch_direct_id(tile_direct_id, arch_direct_id);
}
}
}
@ -343,8 +648,7 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct,
* between tiles (programmable blocks)
***************************************************************************************/
TileDirect build_device_tile_direct(const DeviceContext& device_ctx,
const ArchDirect& arch_direct,
const CircuitLibrary& circuit_lib) {
const ArchDirect& arch_direct) {
vtr::ScopedStartFinishTimer timer("Build the annotation about direct connection between tiles");
TileDirect tile_direct;
@ -358,7 +662,12 @@ TileDirect build_device_tile_direct(const DeviceContext& device_ctx,
device_ctx.arch->Directs[idirect],
device_ctx,
arch_direct_id);
/* TODO: Build from OpenFPGA arch definition */
/* Build from OpenFPGA arch definition */
build_inter_column_row_tile_direct(tile_direct,
device_ctx.arch->Directs[idirect],
device_ctx,
arch_direct,
arch_direct_id);
}
return tile_direct;

View File

@ -17,8 +17,7 @@
namespace openfpga {
TileDirect build_device_tile_direct(const DeviceContext& device_ctx,
const ArchDirect& arch_direct,
const CircuitLibrary& circuit_lib);
const ArchDirect& arch_direct);
} /* end namespace openfpga */

View File

@ -15,12 +15,6 @@ TileDirect::tile_direct_range TileDirect::directs() const {
return vtr::make_range(direct_ids_.begin(), direct_ids_.end());
}
t_physical_tile_type_ptr TileDirect::from_tile(const TileDirectId& direct_id) const {
/* Validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
return from_tiles_[direct_id];
}
vtr::Point<size_t> TileDirect::from_tile_coordinate(const TileDirectId& direct_id) const {
/* Validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
@ -39,12 +33,6 @@ e_side TileDirect::from_tile_side(const TileDirectId& direct_id) const {
return from_tile_sides_[direct_id];
}
t_physical_tile_type_ptr TileDirect::to_tile(const TileDirectId& direct_id) const {
/* Validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
return to_tiles_[direct_id];
}
vtr::Point<size_t> TileDirect::to_tile_coordinate(const TileDirectId& direct_id) const {
/* Validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
@ -72,11 +60,9 @@ ArchDirectId TileDirect::arch_direct(const TileDirectId& direct_id) const {
/******************************************************************************
* Private Mutators
******************************************************************************/
TileDirectId TileDirect::add_direct(t_physical_tile_type_ptr from_tile,
const vtr::Point<size_t>& from_tile_coord,
TileDirectId TileDirect::add_direct(const vtr::Point<size_t>& from_tile_coord,
const e_side& from_tile_side,
const size_t& from_tile_pin,
t_physical_tile_type_ptr to_tile,
const vtr::Point<size_t>& to_tile_coord,
const e_side& to_tile_side,
const size_t& to_tile_pin) {
@ -85,12 +71,10 @@ TileDirectId TileDirect::add_direct(t_physical_tile_type_ptr from_tile,
direct_ids_.push_back(direct);
/* Allocate other attributes */
from_tiles_.push_back(from_tile);
from_tile_coords_.push_back(from_tile_coord);
from_tile_sides_.push_back(from_tile_side);
from_tile_pins_.push_back(from_tile_pin);
to_tiles_.push_back(to_tile);
to_tile_coords_.push_back(to_tile_coord);
to_tile_sides_.push_back(to_tile_side);
to_tile_pins_.push_back(to_tile_pin);

View File

@ -33,21 +33,17 @@ class TileDirect {
typedef vtr::Range<tile_direct_iterator> tile_direct_range;
public: /* Public aggregators */
tile_direct_range directs() const;
t_physical_tile_type_ptr from_tile(const TileDirectId& direct_id) const;
vtr::Point<size_t> from_tile_coordinate(const TileDirectId& direct_id) const;
e_side from_tile_side(const TileDirectId& direct_id) const;
size_t from_tile_pin(const TileDirectId& direct_id) const;
t_physical_tile_type_ptr to_tile(const TileDirectId& direct_id) const;
vtr::Point<size_t> to_tile_coordinate(const TileDirectId& direct_id) const;
e_side to_tile_side(const TileDirectId& direct_id) const;
size_t to_tile_pin(const TileDirectId& direct_id) const;
ArchDirectId arch_direct(const TileDirectId& direct_id) const;
public: /* Public mutators */
TileDirectId add_direct(t_physical_tile_type_ptr from_tile,
const vtr::Point<size_t>& from_tile_coord,
TileDirectId add_direct(const vtr::Point<size_t>& from_tile_coord,
const e_side& from_tile_side,
const size_t& from_tile_pin,
t_physical_tile_type_ptr to_tile,
const vtr::Point<size_t>& to_tile_coord,
const e_side& to_tile_side,
const size_t& to_tile_pin);
@ -63,7 +59,6 @@ class TileDirect {
* - tile coordinate
* - tile pin id
*/
vtr::vector<TileDirectId, t_physical_tile_type_ptr> from_tiles_;
vtr::vector<TileDirectId, vtr::Point<size_t>> from_tile_coords_;
vtr::vector<TileDirectId, e_side> from_tile_sides_;
vtr::vector<TileDirectId, size_t> from_tile_pins_;
@ -73,7 +68,6 @@ class TileDirect {
* - tile coordinate
* - tile pin id
*/
vtr::vector<TileDirectId, t_physical_tile_type_ptr> to_tiles_;
vtr::vector<TileDirectId, vtr::Point<size_t>> to_tile_coords_;
vtr::vector<TileDirectId, e_side> to_tile_sides_;
vtr::vector<TileDirectId, size_t> to_tile_pins_;