OpenFPGA/openfpga/src/fabric/build_top_module_directs.cpp

176 lines
11 KiB
C++
Raw Normal View History

/********************************************************************
* 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"
#include "vtr_time.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 VprDeviceAnnotation& vpr_device_annotation,
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);
t_physical_tile_type_ptr src_grid_type_descriptor = grids[src_clb_coord.x()][src_clb_coord.y()].type;
size_t src_pin_width = src_grid_type_descriptor->pin_width_offset[src_tile_pin];
size_t src_pin_height = src_grid_type_descriptor->pin_height_offset[src_tile_pin];
BasicPort src_pin_info = vpr_device_annotation.physical_tile_pin_port_info(src_grid_type_descriptor, src_tile_pin);
VTR_ASSERT(true == src_pin_info.is_valid());
int src_subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(src_grid_type_descriptor, src_tile_pin);
VTR_ASSERT(OPEN != src_subtile_index && src_subtile_index < src_grid_type_descriptor->capacity);
std::string src_port_name = generate_grid_port_name(src_pin_width, src_pin_height, src_subtile_index, src_pin_grid_side, src_pin_info);
ModulePortId src_port_id = module_manager.find_module_port(src_grid_module, src_port_name);
2020-03-21 13:43:56 -05:00
if (true != module_manager.valid_module_port_id(src_grid_module, src_port_id)) {
VTR_LOG_ERROR("Fail to find port '%s[%lu][%lu].%s'\n",
src_module_name.c_str(), src_clb_coord.x(), src_clb_coord.y(),
src_port_name.c_str());
2020-03-21 13:43:56 -05:00
}
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);
t_physical_tile_type_ptr sink_grid_type_descriptor = grids[des_clb_coord.x()][des_clb_coord.y()].type;
size_t sink_pin_width = sink_grid_type_descriptor->pin_width_offset[src_tile_pin];
size_t sink_pin_height = sink_grid_type_descriptor->pin_height_offset[src_tile_pin];
BasicPort sink_pin_info = vpr_device_annotation.physical_tile_pin_port_info(sink_grid_type_descriptor, sink_tile_pin);
VTR_ASSERT(true == sink_pin_info.is_valid());
int sink_subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(sink_grid_type_descriptor, sink_tile_pin);
VTR_ASSERT(OPEN != src_subtile_index && src_subtile_index < sink_grid_type_descriptor->capacity);
std::string sink_port_name = generate_grid_port_name(sink_pin_width, sink_pin_height, sink_subtile_index, sink_pin_grid_side, sink_pin_info);
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
* Connect the wire between direct_instance output and sink_pin of clb
*/
ModuleNetId net_direct_sink = create_module_source_pin_net(module_manager, top_module, 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 VprDeviceAnnotation& vpr_device_annotation,
const DeviceGrid& grids,
const vtr::Matrix<size_t>& grid_instance_ids,
const TileDirect& tile_direct,
const ArchDirect& arch_direct) {
vtr::ScopedStartFinishTimer timer("Add module nets for inter-tile connections");
for (const TileDirectId& tile_direct_id : tile_direct.directs()) {
add_module_nets_tile_direct_connection(module_manager, top_module, circuit_lib,
vpr_device_annotation,
grids, grid_instance_ids,
tile_direct, tile_direct_id,
arch_direct);
}
}
} /* end namespace openfpga */