2020-02-14 11:45:24 -06:00
|
|
|
/********************************************************************
|
2022-10-06 19:08:50 -05:00
|
|
|
* This file include most utilized functions for building connections
|
2020-02-14 11:45:24 -06:00
|
|
|
* inside the module graph for FPGA fabric
|
|
|
|
*******************************************************************/
|
|
|
|
/* Headers from vtrutil library */
|
|
|
|
#include "vtr_assert.h"
|
2020-06-30 00:17:03 -05:00
|
|
|
#include "vtr_time.h"
|
2020-02-14 11:45:24 -06:00
|
|
|
|
2020-11-10 17:59:00 -06:00
|
|
|
/* Headers from openfpgashell library */
|
|
|
|
#include "command_exit_codes.h"
|
|
|
|
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Headers from openfpgautil library */
|
|
|
|
#include "openfpga_side_manager.h"
|
|
|
|
|
2020-11-10 17:59:00 -06:00
|
|
|
/* Headers from vpr library */
|
2022-10-06 19:08:50 -05:00
|
|
|
#include "build_routing_module_utils.h"
|
|
|
|
#include "build_top_module_connection.h"
|
|
|
|
#include "build_top_module_utils.h"
|
|
|
|
#include "module_manager_utils.h"
|
|
|
|
#include "openfpga_device_grid_utils.h"
|
2020-02-14 11:45:24 -06:00
|
|
|
#include "openfpga_naming.h"
|
2020-03-21 22:02:47 -05:00
|
|
|
#include "openfpga_physical_tile_utils.h"
|
2022-10-06 19:08:50 -05:00
|
|
|
#include "openfpga_reserved_words.h"
|
2022-08-17 18:25:12 -05:00
|
|
|
#include "openfpga_rr_graph_utils.h"
|
2022-10-06 19:08:50 -05:00
|
|
|
#include "pb_type_utils.h"
|
|
|
|
#include "rr_gsb_utils.h"
|
|
|
|
#include "vpr_utils.h"
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* begin namespace openfpga */
|
|
|
|
namespace openfpga {
|
|
|
|
|
|
|
|
/********************************************************************
|
2022-10-06 19:08:50 -05:00
|
|
|
* Add module nets to connect a GSB to adjacent grid ports/pins
|
2020-02-14 11:45:24 -06:00
|
|
|
* as well as connection blocks
|
|
|
|
* This function will create nets for the following types of connections
|
|
|
|
* between grid output pins of Switch block and adjacent grids
|
|
|
|
* In this case, the net source is the grid pin, while the net sink
|
|
|
|
* is the switch block pin
|
2022-10-06 19:08:50 -05:00
|
|
|
*
|
2020-02-14 11:45:24 -06:00
|
|
|
* +------------+ +------------+
|
|
|
|
* | | | |
|
|
|
|
* | Grid | | Grid |
|
|
|
|
* | [x][y+1] | | [x+1][y+1] |
|
|
|
|
* | |----+ +----| |
|
|
|
|
* +------------+ | | +------------+
|
|
|
|
* | v v |
|
|
|
|
* | +------------+ |
|
|
|
|
* +------>| |<-----+
|
|
|
|
* | Switch |
|
|
|
|
* | Block |
|
|
|
|
* +------>| [x][y] |<-----+
|
|
|
|
* | +------------+ |
|
|
|
|
* | ^ ^ |
|
|
|
|
* | | | |
|
|
|
|
* +------------+ | | +------------+
|
|
|
|
* | |----+ +-----| |
|
|
|
|
* | Grid | | Grid |
|
|
|
|
* | [x][y] | | [x+1][y] |
|
|
|
|
* | | | |
|
|
|
|
* +------------+ +------------+
|
|
|
|
|
|
|
|
*
|
|
|
|
*******************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
static void add_top_module_nets_connect_grids_and_sb(
|
|
|
|
ModuleManager& module_manager, const ModuleId& top_module,
|
|
|
|
const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids,
|
|
|
|
const vtr::Matrix<size_t>& grid_instance_ids, const RRGraphView& rr_graph,
|
|
|
|
const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb,
|
|
|
|
const vtr::Matrix<size_t>& sb_instance_ids,
|
|
|
|
const bool& compact_routing_hierarchy) {
|
2020-03-24 18:39:26 -05:00
|
|
|
/* Skip those Switch blocks that do not exist */
|
|
|
|
if (false == rr_gsb.is_sb_exist()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* We could have two different coordinators, one is the instance, the other is
|
|
|
|
* the module */
|
|
|
|
vtr::Point<size_t> instance_sb_coordinate(rr_gsb.get_sb_x(),
|
|
|
|
rr_gsb.get_sb_y());
|
2020-02-14 11:45:24 -06:00
|
|
|
vtr::Point<size_t> module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y());
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* If we use compact routing hierarchy, we should find the unique module of
|
|
|
|
* CB, which is added to the top module */
|
2020-02-14 11:45:24 -06:00
|
|
|
if (true == compact_routing_hierarchy) {
|
|
|
|
vtr::Point<size_t> gsb_coord(rr_gsb.get_x(), rr_gsb.get_y());
|
|
|
|
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord);
|
2022-10-06 19:08:50 -05:00
|
|
|
module_gsb_coordinate.set_x(unique_mirror.get_x());
|
|
|
|
module_gsb_coordinate.set_y(unique_mirror.get_y());
|
|
|
|
}
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* This is the source cb that is added to the top module */
|
|
|
|
const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_coordinate);
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::Point<size_t> module_sb_coordinate(module_sb.get_sb_x(),
|
|
|
|
module_sb.get_sb_y());
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Collect sink-related information */
|
2022-10-06 19:08:50 -05:00
|
|
|
std::string sink_sb_module_name =
|
|
|
|
generate_switch_block_module_name(module_sb_coordinate);
|
2020-02-14 11:45:24 -06:00
|
|
|
ModuleId sink_sb_module = module_manager.find_module(sink_sb_module_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(sink_sb_module));
|
2022-10-06 19:08:50 -05:00
|
|
|
size_t sink_sb_instance =
|
|
|
|
sb_instance_ids[instance_sb_coordinate.x()][instance_sb_coordinate.y()];
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Connect grid output pins (OPIN) to switch block grid pins */
|
|
|
|
for (size_t side = 0; side < module_sb.get_num_sides(); ++side) {
|
|
|
|
SideManager side_manager(side);
|
2022-10-06 19:08:50 -05:00
|
|
|
for (size_t inode = 0;
|
|
|
|
inode < module_sb.get_num_opin_nodes(side_manager.get_side());
|
|
|
|
++inode) {
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Collect source-related information */
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Generate the grid module name by considering if it locates on the
|
|
|
|
* border */
|
|
|
|
vtr::Point<size_t> grid_coordinate(
|
|
|
|
rr_graph.node_xlow(
|
|
|
|
rr_gsb.get_opin_node(side_manager.get_side(), inode)),
|
|
|
|
rr_graph.node_ylow(
|
|
|
|
rr_gsb.get_opin_node(side_manager.get_side(), inode)));
|
|
|
|
std::string src_grid_module_name =
|
|
|
|
generate_grid_block_module_name_in_top_module(
|
|
|
|
std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate);
|
|
|
|
ModuleId src_grid_module =
|
|
|
|
module_manager.find_module(src_grid_module_name);
|
2020-02-14 11:45:24 -06:00
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(src_grid_module));
|
2022-10-06 19:08:50 -05:00
|
|
|
size_t src_grid_instance =
|
|
|
|
grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()];
|
|
|
|
size_t src_grid_pin_index = rr_graph.node_pin_num(
|
|
|
|
rr_gsb.get_opin_node(side_manager.get_side(), inode));
|
|
|
|
|
|
|
|
t_physical_tile_type_ptr grid_type_descriptor =
|
|
|
|
grids[grid_coordinate.x()][grid_coordinate.y()].type;
|
|
|
|
size_t src_grid_pin_width =
|
|
|
|
grid_type_descriptor->pin_width_offset[src_grid_pin_index];
|
|
|
|
size_t src_grid_pin_height =
|
|
|
|
grid_type_descriptor->pin_height_offset[src_grid_pin_index];
|
|
|
|
BasicPort src_grid_pin_info =
|
|
|
|
vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor,
|
|
|
|
src_grid_pin_index);
|
2021-03-13 21:05:18 -06:00
|
|
|
VTR_ASSERT(true == src_grid_pin_info.is_valid());
|
2022-10-06 19:08:50 -05:00
|
|
|
int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(
|
|
|
|
grid_type_descriptor, src_grid_pin_index);
|
|
|
|
VTR_ASSERT(OPEN != subtile_index &&
|
|
|
|
subtile_index < grid_type_descriptor->capacity);
|
|
|
|
std::string src_grid_port_name = generate_grid_port_name(
|
|
|
|
src_grid_pin_width, src_grid_pin_height, subtile_index,
|
|
|
|
get_rr_graph_single_node_side(
|
|
|
|
rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)),
|
|
|
|
src_grid_pin_info);
|
|
|
|
ModulePortId src_grid_port_id =
|
|
|
|
module_manager.find_module_port(src_grid_module, src_grid_port_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module,
|
|
|
|
src_grid_port_id));
|
|
|
|
BasicPort src_grid_port =
|
|
|
|
module_manager.module_port(src_grid_module, src_grid_port_id);
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Collect sink-related information */
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::Point<size_t> sink_sb_port_coord(
|
|
|
|
rr_graph.node_xlow(
|
|
|
|
module_sb.get_opin_node(side_manager.get_side(), inode)),
|
|
|
|
rr_graph.node_ylow(
|
|
|
|
module_sb.get_opin_node(side_manager.get_side(), inode)));
|
|
|
|
std::string sink_sb_port_name = generate_sb_module_grid_port_name(
|
|
|
|
side_manager.get_side(),
|
|
|
|
get_rr_graph_single_node_side(
|
|
|
|
rr_graph, module_sb.get_opin_node(side_manager.get_side(), inode)),
|
|
|
|
grids, vpr_device_annotation, rr_graph,
|
|
|
|
module_sb.get_opin_node(side_manager.get_side(), inode));
|
|
|
|
ModulePortId sink_sb_port_id =
|
|
|
|
module_manager.find_module_port(sink_sb_module, sink_sb_port_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_port_id(sink_sb_module,
|
|
|
|
sink_sb_port_id));
|
|
|
|
BasicPort sink_sb_port =
|
|
|
|
module_manager.module_port(sink_sb_module, sink_sb_port_id);
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Source and sink port should match in size */
|
|
|
|
VTR_ASSERT(src_grid_port.get_width() == sink_sb_port.get_width());
|
2022-10-06 19:08:50 -05:00
|
|
|
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Create a net for each pin */
|
|
|
|
for (size_t pin_id = 0; pin_id < src_grid_port.pins().size(); ++pin_id) {
|
2022-10-06 19:08:50 -05:00
|
|
|
ModuleNetId net = create_module_source_pin_net(
|
|
|
|
module_manager, top_module, src_grid_module, src_grid_instance,
|
|
|
|
src_grid_port_id, src_grid_port.pins()[pin_id]);
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Configure the net sink */
|
2022-10-06 19:08:50 -05:00
|
|
|
module_manager.add_module_net_sink(top_module, net, sink_sb_module,
|
|
|
|
sink_sb_instance, sink_sb_port_id,
|
|
|
|
sink_sb_port.pins()[pin_id]);
|
2020-02-14 11:45:24 -06:00
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
}
|
2020-02-14 11:45:24 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
2022-10-06 19:08:50 -05:00
|
|
|
* Add module nets to connect a GSB to adjacent grid ports/pins
|
2020-02-14 11:45:24 -06:00
|
|
|
* as well as connection blocks
|
|
|
|
* This function will create nets for the following types of connections
|
|
|
|
* between grid output pins of Switch block and adjacent grids
|
|
|
|
* In this case, the net source is the grid pin, while the net sink
|
|
|
|
* is the switch block pin
|
|
|
|
*
|
|
|
|
* In particular, this function considers the duplicated output pins of grids
|
|
|
|
* when creating the connecting nets.
|
|
|
|
* The follow figure shows the different pin postfix to be considered when
|
|
|
|
* connecting the grid pins to SB inputs
|
2022-10-06 19:08:50 -05:00
|
|
|
*
|
2020-02-14 11:45:24 -06:00
|
|
|
* +------------+ +------------+
|
|
|
|
* | | | |
|
|
|
|
* | Grid | | Grid |
|
|
|
|
* | [x][y+1] |lower lower| [x+1][y+1] |
|
|
|
|
* | |----+ +----| |
|
|
|
|
* +------------+ | | +------------+
|
|
|
|
* |lower v v |upper
|
|
|
|
* | +------------+ |
|
|
|
|
* +------>| |<-----+
|
|
|
|
* | Switch |
|
|
|
|
* | Block |
|
|
|
|
* +------>| [x][y] |<-----+
|
|
|
|
* | +------------+ |
|
|
|
|
* | ^ ^ |
|
|
|
|
* |lower | | |upper
|
|
|
|
* +------------+ | | +------------+
|
|
|
|
* | |----+ +-----| |
|
|
|
|
* | Grid |upper upper | Grid |
|
|
|
|
* | [x][y] | | [x+1][y] |
|
|
|
|
* | | | |
|
|
|
|
* +------------+ +------------+
|
|
|
|
*
|
|
|
|
*******************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
static void add_top_module_nets_connect_grids_and_sb_with_duplicated_pins(
|
|
|
|
ModuleManager& module_manager, const ModuleId& top_module,
|
|
|
|
const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids,
|
|
|
|
const vtr::Matrix<size_t>& grid_instance_ids, const RRGraphView& rr_graph,
|
|
|
|
const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb,
|
|
|
|
const vtr::Matrix<size_t>& sb_instance_ids,
|
|
|
|
const bool& compact_routing_hierarchy) {
|
2020-03-24 18:39:26 -05:00
|
|
|
/* Skip those Switch blocks that do not exist */
|
|
|
|
if (false == rr_gsb.is_sb_exist()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* We could have two different coordinators, one is the instance, the other is
|
|
|
|
* the module */
|
|
|
|
vtr::Point<size_t> instance_sb_coordinate(rr_gsb.get_sb_x(),
|
|
|
|
rr_gsb.get_sb_y());
|
2020-02-14 11:45:24 -06:00
|
|
|
vtr::Point<size_t> module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y());
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* If we use compact routing hierarchy, we should find the unique module of
|
|
|
|
* CB, which is added to the top module */
|
2020-02-14 11:45:24 -06:00
|
|
|
if (true == compact_routing_hierarchy) {
|
|
|
|
vtr::Point<size_t> gsb_coord(rr_gsb.get_x(), rr_gsb.get_y());
|
|
|
|
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord);
|
2022-10-06 19:08:50 -05:00
|
|
|
module_gsb_coordinate.set_x(unique_mirror.get_x());
|
|
|
|
module_gsb_coordinate.set_y(unique_mirror.get_y());
|
|
|
|
}
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* This is the source cb that is added to the top module */
|
|
|
|
const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_coordinate);
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::Point<size_t> module_sb_coordinate(module_sb.get_sb_x(),
|
|
|
|
module_sb.get_sb_y());
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Collect sink-related information */
|
2022-10-06 19:08:50 -05:00
|
|
|
std::string sink_sb_module_name =
|
|
|
|
generate_switch_block_module_name(module_sb_coordinate);
|
2020-02-14 11:45:24 -06:00
|
|
|
ModuleId sink_sb_module = module_manager.find_module(sink_sb_module_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(sink_sb_module));
|
2022-10-06 19:08:50 -05:00
|
|
|
size_t sink_sb_instance =
|
|
|
|
sb_instance_ids[instance_sb_coordinate.x()][instance_sb_coordinate.y()];
|
2020-02-14 11:45:24 -06:00
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Create a truth table for the postfix to be used regarding to the different
|
|
|
|
* side of switch blocks */
|
2020-02-14 11:45:24 -06:00
|
|
|
std::map<e_side, bool> sb_side2postfix_map;
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Boolean variable "true" indicates the upper postfix in naming functions
|
|
|
|
* Boolean variable "false" indicates the lower postfix in naming functions
|
2020-02-14 11:45:24 -06:00
|
|
|
*/
|
|
|
|
sb_side2postfix_map[TOP] = false;
|
|
|
|
sb_side2postfix_map[RIGHT] = true;
|
|
|
|
sb_side2postfix_map[BOTTOM] = true;
|
|
|
|
sb_side2postfix_map[LEFT] = false;
|
|
|
|
|
|
|
|
/* Connect grid output pins (OPIN) to switch block grid pins */
|
|
|
|
for (size_t side = 0; side < module_sb.get_num_sides(); ++side) {
|
|
|
|
SideManager side_manager(side);
|
2022-10-06 19:08:50 -05:00
|
|
|
for (size_t inode = 0;
|
|
|
|
inode < module_sb.get_num_opin_nodes(side_manager.get_side());
|
|
|
|
++inode) {
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Collect source-related information */
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Generate the grid module name by considering if it locates on the
|
|
|
|
* border */
|
|
|
|
vtr::Point<size_t> grid_coordinate(
|
|
|
|
rr_graph.node_xlow(
|
|
|
|
rr_gsb.get_opin_node(side_manager.get_side(), inode)),
|
|
|
|
rr_graph.node_ylow(
|
|
|
|
rr_gsb.get_opin_node(side_manager.get_side(), inode)));
|
|
|
|
std::string src_grid_module_name =
|
|
|
|
generate_grid_block_module_name_in_top_module(
|
|
|
|
std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate);
|
|
|
|
ModuleId src_grid_module =
|
|
|
|
module_manager.find_module(src_grid_module_name);
|
2020-02-14 11:45:24 -06:00
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(src_grid_module));
|
2022-10-06 19:08:50 -05:00
|
|
|
size_t src_grid_instance =
|
|
|
|
grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()];
|
|
|
|
size_t src_grid_pin_index = rr_graph.node_pin_num(
|
|
|
|
rr_gsb.get_opin_node(side_manager.get_side(), inode));
|
|
|
|
|
|
|
|
t_physical_tile_type_ptr grid_type_descriptor =
|
|
|
|
grids[grid_coordinate.x()][grid_coordinate.y()].type;
|
|
|
|
size_t src_grid_pin_width =
|
|
|
|
grid_type_descriptor->pin_width_offset[src_grid_pin_index];
|
|
|
|
size_t src_grid_pin_height =
|
|
|
|
grid_type_descriptor->pin_height_offset[src_grid_pin_index];
|
|
|
|
|
|
|
|
BasicPort src_grid_pin_info =
|
|
|
|
vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor,
|
|
|
|
src_grid_pin_index);
|
2021-03-13 21:05:18 -06:00
|
|
|
VTR_ASSERT(true == src_grid_pin_info.is_valid());
|
2022-10-06 19:08:50 -05:00
|
|
|
int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(
|
|
|
|
grid_type_descriptor, src_grid_pin_index);
|
|
|
|
VTR_ASSERT(OPEN != subtile_index &&
|
|
|
|
subtile_index < grid_type_descriptor->capacity);
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Pins for direct connection are NOT duplicated.
|
2022-10-06 19:08:50 -05:00
|
|
|
* Follow the traditional recipe when adding nets!
|
|
|
|
* Xifan: I assume that each direct connection pin must have Fc=0.
|
2020-02-14 11:45:24 -06:00
|
|
|
* For other duplicated pins, we follow the new naming
|
|
|
|
*/
|
|
|
|
std::string src_grid_port_name;
|
2022-10-06 19:08:50 -05:00
|
|
|
if (0. ==
|
|
|
|
find_physical_tile_pin_Fc(grid_type_descriptor, src_grid_pin_index)) {
|
|
|
|
src_grid_port_name = generate_grid_port_name(
|
|
|
|
src_grid_pin_width, src_grid_pin_height, subtile_index,
|
|
|
|
get_rr_graph_single_node_side(
|
|
|
|
rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)),
|
|
|
|
src_grid_pin_info);
|
2020-02-14 11:45:24 -06:00
|
|
|
} else {
|
2022-10-06 19:08:50 -05:00
|
|
|
src_grid_port_name = generate_grid_duplicated_port_name(
|
|
|
|
src_grid_pin_width, src_grid_pin_height, subtile_index,
|
|
|
|
get_rr_graph_single_node_side(
|
|
|
|
rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)),
|
|
|
|
src_grid_pin_info, sb_side2postfix_map[side_manager.get_side()]);
|
2020-02-14 11:45:24 -06:00
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
ModulePortId src_grid_port_id =
|
|
|
|
module_manager.find_module_port(src_grid_module, src_grid_port_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module,
|
|
|
|
src_grid_port_id));
|
|
|
|
BasicPort src_grid_port =
|
|
|
|
module_manager.module_port(src_grid_module, src_grid_port_id);
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Collect sink-related information */
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::Point<size_t> sink_sb_port_coord(
|
|
|
|
rr_graph.node_xlow(
|
|
|
|
module_sb.get_opin_node(side_manager.get_side(), inode)),
|
|
|
|
rr_graph.node_ylow(
|
|
|
|
module_sb.get_opin_node(side_manager.get_side(), inode)));
|
|
|
|
std::string sink_sb_port_name = generate_sb_module_grid_port_name(
|
|
|
|
side_manager.get_side(),
|
|
|
|
get_rr_graph_single_node_side(
|
|
|
|
rr_graph, module_sb.get_opin_node(side_manager.get_side(), inode)),
|
|
|
|
grids, vpr_device_annotation, rr_graph,
|
|
|
|
module_sb.get_opin_node(side_manager.get_side(), inode));
|
|
|
|
ModulePortId sink_sb_port_id =
|
|
|
|
module_manager.find_module_port(sink_sb_module, sink_sb_port_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_port_id(sink_sb_module,
|
|
|
|
sink_sb_port_id));
|
|
|
|
BasicPort sink_sb_port =
|
|
|
|
module_manager.module_port(sink_sb_module, sink_sb_port_id);
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Source and sink port should match in size */
|
|
|
|
VTR_ASSERT(src_grid_port.get_width() == sink_sb_port.get_width());
|
2022-10-06 19:08:50 -05:00
|
|
|
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Create a net for each pin */
|
|
|
|
for (size_t pin_id = 0; pin_id < src_grid_port.pins().size(); ++pin_id) {
|
2022-10-06 19:08:50 -05:00
|
|
|
ModuleNetId net = create_module_source_pin_net(
|
|
|
|
module_manager, top_module, src_grid_module, src_grid_instance,
|
|
|
|
src_grid_port_id, src_grid_port.pins()[pin_id]);
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Configure the net sink */
|
2022-10-06 19:08:50 -05:00
|
|
|
module_manager.add_module_net_sink(top_module, net, sink_sb_module,
|
|
|
|
sink_sb_instance, sink_sb_port_id,
|
|
|
|
sink_sb_port.pins()[pin_id]);
|
2020-02-14 11:45:24 -06:00
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
}
|
2020-02-14 11:45:24 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* This function will create nets for the connections
|
|
|
|
* between grid input pins and connection blocks
|
2022-10-06 19:08:50 -05:00
|
|
|
* In this case, the net source is the connection block pin,
|
2020-02-14 11:45:24 -06:00
|
|
|
* while the net sink is the grid input
|
|
|
|
*
|
|
|
|
* +------------+ +------------------+ +------------+
|
|
|
|
* | | | | | |
|
|
|
|
* | Grid |<-----| Connection Block |----->| Grid |
|
2022-10-06 19:08:50 -05:00
|
|
|
* | [x][y+1] | | Y-direction | | [x+1][y+1] |
|
2020-02-14 11:45:24 -06:00
|
|
|
* | | | [x][y+1] | | |
|
|
|
|
* +------------+ +------------------+ +------------+
|
2022-10-06 19:08:50 -05:00
|
|
|
* ^
|
|
|
|
* |
|
|
|
|
* +------------+ +------------------+
|
|
|
|
* | Connection | | |
|
|
|
|
* | Block | | Switch Block |
|
|
|
|
* | X-direction| | [x][y] |
|
|
|
|
* | [x][y] | | |
|
|
|
|
* +------------+ +------------------+
|
|
|
|
* |
|
|
|
|
* v
|
|
|
|
* +------------+
|
|
|
|
* | |
|
|
|
|
* | Grid |
|
|
|
|
* | [x][y] |
|
|
|
|
* | |
|
|
|
|
* +------------+
|
2020-02-14 11:45:24 -06:00
|
|
|
*
|
|
|
|
*
|
2022-10-06 19:08:50 -05:00
|
|
|
* Relationship between source connection block and its unique module
|
2020-02-14 11:45:24 -06:00
|
|
|
* Take an example of a CBY
|
|
|
|
*
|
|
|
|
* grid_pin name should follow unique module of Grid[x][y+1]
|
|
|
|
* cb_pin name should follow unique module of CBY[x][y+1]
|
2022-10-06 19:08:50 -05:00
|
|
|
*
|
|
|
|
* However, instace id should follow the origin Grid and Connection block
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* +------------+ +------------------+
|
|
|
|
* | | | |
|
2020-02-14 11:45:24 -06:00
|
|
|
* | Grid |<------------| Connection Block |
|
2022-10-06 19:08:50 -05:00
|
|
|
* | [x][y+1] | | Y-direction |
|
2020-02-14 11:45:24 -06:00
|
|
|
* | | | [x][y+1] |
|
|
|
|
* +------------+ +------------------+
|
|
|
|
* ^
|
|
|
|
* || unique mirror
|
2022-10-06 19:08:50 -05:00
|
|
|
* +------------+ +------------------+
|
|
|
|
* | | | |
|
2020-02-14 11:45:24 -06:00
|
|
|
* | Grid |<------------| Connection Block |
|
2022-10-06 19:08:50 -05:00
|
|
|
* | [i][j+1] | | Y-direction |
|
2020-02-14 11:45:24 -06:00
|
|
|
* | | | [i][j+1] |
|
|
|
|
* +------------+ +------------------+
|
|
|
|
*
|
|
|
|
*******************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
static void add_top_module_nets_connect_grids_and_cb(
|
|
|
|
ModuleManager& module_manager, const ModuleId& top_module,
|
|
|
|
const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids,
|
|
|
|
const vtr::Matrix<size_t>& grid_instance_ids, const RRGraphView& rr_graph,
|
|
|
|
const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb,
|
|
|
|
const t_rr_type& cb_type, const vtr::Matrix<size_t>& cb_instance_ids,
|
|
|
|
const bool& compact_routing_hierarchy) {
|
|
|
|
/* We could have two different coordinators, one is the instance, the other is
|
|
|
|
* the module */
|
|
|
|
vtr::Point<size_t> instance_cb_coordinate(rr_gsb.get_cb_x(cb_type),
|
|
|
|
rr_gsb.get_cb_y(cb_type));
|
2020-02-14 11:45:24 -06:00
|
|
|
vtr::Point<size_t> module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y());
|
|
|
|
|
|
|
|
/* Skip those Connection blocks that do not exist */
|
|
|
|
if (false == rr_gsb.is_cb_exist(cb_type)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Skip if the cb does not contain any configuration bits! */
|
|
|
|
if (true == connection_block_contain_only_routing_tracks(rr_gsb, cb_type)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* If we use compact routing hierarchy, we should find the unique module of
|
|
|
|
* CB, which is added to the top module */
|
2020-02-14 11:45:24 -06:00
|
|
|
if (true == compact_routing_hierarchy) {
|
|
|
|
vtr::Point<size_t> gsb_coord(rr_gsb.get_x(), rr_gsb.get_y());
|
2022-10-06 19:08:50 -05:00
|
|
|
const RRGSB& unique_mirror =
|
|
|
|
device_rr_gsb.get_cb_unique_module(cb_type, gsb_coord);
|
|
|
|
module_gsb_coordinate.set_x(unique_mirror.get_x());
|
|
|
|
module_gsb_coordinate.set_y(unique_mirror.get_y());
|
|
|
|
}
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* This is the source cb that is added to the top module */
|
|
|
|
const RRGSB& module_cb = device_rr_gsb.get_gsb(module_gsb_coordinate);
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::Point<size_t> module_cb_coordinate(module_cb.get_cb_x(cb_type),
|
|
|
|
module_cb.get_cb_y(cb_type));
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Collect source-related information */
|
2022-10-06 19:08:50 -05:00
|
|
|
std::string src_cb_module_name =
|
|
|
|
generate_connection_block_module_name(cb_type, module_cb_coordinate);
|
2020-02-14 11:45:24 -06:00
|
|
|
ModuleId src_cb_module = module_manager.find_module(src_cb_module_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(src_cb_module));
|
|
|
|
/* Instance id should follow the instance cb coordinate */
|
2022-10-06 19:08:50 -05:00
|
|
|
size_t src_cb_instance =
|
|
|
|
cb_instance_ids[instance_cb_coordinate.x()][instance_cb_coordinate.y()];
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Iterate over the output pins of the Connection Block */
|
|
|
|
std::vector<enum e_side> cb_ipin_sides = module_cb.get_cb_ipin_sides(cb_type);
|
|
|
|
for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) {
|
|
|
|
enum e_side cb_ipin_side = cb_ipin_sides[iside];
|
2022-10-06 19:08:50 -05:00
|
|
|
for (size_t inode = 0; inode < module_cb.get_num_ipin_nodes(cb_ipin_side);
|
|
|
|
++inode) {
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Collect source-related information */
|
|
|
|
RRNodeId module_ipin_node = module_cb.get_ipin_node(cb_ipin_side, inode);
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::Point<size_t> cb_src_port_coord(
|
|
|
|
rr_graph.node_xlow(module_ipin_node),
|
|
|
|
rr_graph.node_ylow(module_ipin_node));
|
|
|
|
std::string src_cb_port_name = generate_cb_module_grid_port_name(
|
|
|
|
cb_ipin_side, grids, vpr_device_annotation, rr_graph, module_ipin_node);
|
|
|
|
ModulePortId src_cb_port_id =
|
|
|
|
module_manager.find_module_port(src_cb_module, src_cb_port_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_port_id(src_cb_module,
|
|
|
|
src_cb_port_id));
|
|
|
|
BasicPort src_cb_port =
|
|
|
|
module_manager.module_port(src_cb_module, src_cb_port_id);
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Collect sink-related information */
|
|
|
|
/* Note that we use the instance cb pin here!!!
|
2022-10-06 19:08:50 -05:00
|
|
|
* because it has the correct coordinator for the grid!!!
|
2020-02-14 11:45:24 -06:00
|
|
|
*/
|
|
|
|
RRNodeId instance_ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode);
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::Point<size_t> grid_coordinate(
|
|
|
|
rr_graph.node_xlow(instance_ipin_node),
|
|
|
|
rr_graph.node_ylow(instance_ipin_node));
|
|
|
|
std::string sink_grid_module_name =
|
|
|
|
generate_grid_block_module_name_in_top_module(
|
|
|
|
std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate);
|
|
|
|
ModuleId sink_grid_module =
|
|
|
|
module_manager.find_module(sink_grid_module_name);
|
2020-02-14 11:45:24 -06:00
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(sink_grid_module));
|
2022-10-06 19:08:50 -05:00
|
|
|
size_t sink_grid_instance =
|
|
|
|
grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()];
|
2020-02-14 11:45:24 -06:00
|
|
|
size_t sink_grid_pin_index = rr_graph.node_pin_num(instance_ipin_node);
|
2021-03-13 21:05:18 -06:00
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
t_physical_tile_type_ptr grid_type_descriptor =
|
|
|
|
grids[grid_coordinate.x()][grid_coordinate.y()].type;
|
|
|
|
size_t sink_grid_pin_width =
|
|
|
|
grid_type_descriptor->pin_width_offset[sink_grid_pin_index];
|
|
|
|
size_t sink_grid_pin_height =
|
|
|
|
grid_type_descriptor->pin_height_offset[sink_grid_pin_index];
|
|
|
|
BasicPort sink_grid_pin_info =
|
|
|
|
vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor,
|
|
|
|
sink_grid_pin_index);
|
2021-03-13 21:05:18 -06:00
|
|
|
VTR_ASSERT(true == sink_grid_pin_info.is_valid());
|
2022-10-06 19:08:50 -05:00
|
|
|
int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(
|
|
|
|
grid_type_descriptor, sink_grid_pin_index);
|
|
|
|
VTR_ASSERT(OPEN != subtile_index &&
|
|
|
|
subtile_index < grid_type_descriptor->capacity);
|
|
|
|
std::string sink_grid_port_name = generate_grid_port_name(
|
|
|
|
sink_grid_pin_width, sink_grid_pin_height, subtile_index,
|
|
|
|
get_rr_graph_single_node_side(
|
|
|
|
rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, inode)),
|
|
|
|
sink_grid_pin_info);
|
|
|
|
ModulePortId sink_grid_port_id =
|
|
|
|
module_manager.find_module_port(sink_grid_module, sink_grid_port_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_port_id(
|
|
|
|
sink_grid_module, sink_grid_port_id));
|
|
|
|
BasicPort sink_grid_port =
|
|
|
|
module_manager.module_port(sink_grid_module, sink_grid_port_id);
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Source and sink port should match in size */
|
|
|
|
VTR_ASSERT(src_cb_port.get_width() == sink_grid_port.get_width());
|
2022-10-06 19:08:50 -05:00
|
|
|
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Create a net for each pin */
|
|
|
|
for (size_t pin_id = 0; pin_id < src_cb_port.pins().size(); ++pin_id) {
|
2022-10-06 19:08:50 -05:00
|
|
|
ModuleNetId net = create_module_source_pin_net(
|
|
|
|
module_manager, top_module, src_cb_module, src_cb_instance,
|
|
|
|
src_cb_port_id, src_cb_port.pins()[pin_id]);
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Configure the net sink */
|
2022-10-06 19:08:50 -05:00
|
|
|
module_manager.add_module_net_sink(
|
|
|
|
top_module, net, sink_grid_module, sink_grid_instance,
|
|
|
|
sink_grid_port_id, sink_grid_port.pins()[pin_id]);
|
2020-02-14 11:45:24 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* This function will create nets for the connections
|
|
|
|
* between connection block and switch block pins
|
|
|
|
* Two cases should be considered:
|
|
|
|
* a. The switch block pin denotes an input of a routing track
|
|
|
|
* The net source is an output of a routing track of connection block
|
|
|
|
* while the net sink is an input of a routing track of switch block
|
|
|
|
* b. The switch block pin denotes an output of a routing track
|
2022-10-06 19:08:50 -05:00
|
|
|
* The net source is an output of routing track of switch block
|
2020-02-14 11:45:24 -06:00
|
|
|
* while the net sink is an input of a routing track of connection block
|
|
|
|
*
|
|
|
|
* +------------+ +------------------+ +------------+
|
|
|
|
* | | | | | |
|
|
|
|
* | Grid | | Connection Block | | Grid |
|
2022-10-06 19:08:50 -05:00
|
|
|
* | [x][y+1] | | Y-direction | | [x+1][y+1] |
|
2020-02-14 11:45:24 -06:00
|
|
|
* | | | [x][y+1] | | |
|
|
|
|
* +------------+ +------------------+ +------------+
|
|
|
|
* | ^
|
|
|
|
* v |
|
|
|
|
* +------------+ +------------------+ +------------+
|
|
|
|
* | Connection |----->| |----->| Connection |
|
|
|
|
* | Block | | Switch Block | | Block |
|
|
|
|
* | X-direction|<-----| [x][y] |<-----| X-direction|
|
|
|
|
* | [x][y] | | | | [x+1][y] |
|
|
|
|
* +------------+ +------------------+ +------------+
|
|
|
|
* | ^
|
|
|
|
* v |
|
|
|
|
* +------------+ +------------------+ +------------+
|
|
|
|
* | | | | | |
|
|
|
|
* | Grid | | Connection Block | | Grid |
|
|
|
|
* | [x][y] | | Y-direction | | [x][y+1] |
|
|
|
|
* | | | [x][y] | | |
|
|
|
|
* +------------+ +------------------+ +------------+
|
|
|
|
*
|
2022-10-06 19:08:50 -05:00
|
|
|
* Here, to achieve the purpose, we can simply iterate over the
|
|
|
|
* four sides of switch block and make connections to adjancent
|
2020-02-14 11:45:24 -06:00
|
|
|
* connection blocks
|
|
|
|
*
|
|
|
|
*******************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
static void add_top_module_nets_connect_sb_and_cb(
|
|
|
|
ModuleManager& module_manager, const ModuleId& top_module,
|
|
|
|
const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb,
|
|
|
|
const RRGSB& rr_gsb, const vtr::Matrix<size_t>& sb_instance_ids,
|
|
|
|
const std::map<t_rr_type, vtr::Matrix<size_t>>& cb_instance_ids,
|
|
|
|
const bool& compact_routing_hierarchy) {
|
|
|
|
/* We could have two different coordinators, one is the instance, the other is
|
|
|
|
* the module */
|
|
|
|
vtr::Point<size_t> instance_sb_coordinate(rr_gsb.get_sb_x(),
|
|
|
|
rr_gsb.get_sb_y());
|
2020-02-14 11:45:24 -06:00
|
|
|
vtr::Point<size_t> module_gsb_sb_coordinate(rr_gsb.get_x(), rr_gsb.get_y());
|
|
|
|
|
|
|
|
/* Skip those Switch blocks that do not exist */
|
|
|
|
if (false == rr_gsb.is_sb_exist()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* If we use compact routing hierarchy, we should find the unique module of
|
|
|
|
* CB, which is added to the top module */
|
2020-02-14 11:45:24 -06:00
|
|
|
if (true == compact_routing_hierarchy) {
|
|
|
|
vtr::Point<size_t> gsb_coord(rr_gsb.get_x(), rr_gsb.get_y());
|
|
|
|
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord);
|
2022-10-06 19:08:50 -05:00
|
|
|
module_gsb_sb_coordinate.set_x(unique_mirror.get_x());
|
|
|
|
module_gsb_sb_coordinate.set_y(unique_mirror.get_y());
|
|
|
|
}
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* This is the source cb that is added to the top module */
|
|
|
|
const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_sb_coordinate);
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::Point<size_t> module_sb_coordinate(module_sb.get_sb_x(),
|
|
|
|
module_sb.get_sb_y());
|
|
|
|
std::string sb_module_name =
|
|
|
|
generate_switch_block_module_name(module_sb_coordinate);
|
2020-02-14 11:45:24 -06:00
|
|
|
ModuleId sb_module_id = module_manager.find_module(sb_module_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(sb_module_id));
|
2022-10-06 19:08:50 -05:00
|
|
|
size_t sb_instance =
|
|
|
|
sb_instance_ids[instance_sb_coordinate.x()][instance_sb_coordinate.y()];
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Connect grid output pins (OPIN) to switch block grid pins */
|
|
|
|
for (size_t side = 0; side < module_sb.get_num_sides(); ++side) {
|
|
|
|
SideManager side_manager(side);
|
|
|
|
/* Iterate over the routing tracks on this side */
|
|
|
|
/* Early skip: if there is no routing tracks at this side */
|
|
|
|
if (0 == module_sb.get_chan_width(side_manager.get_side())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Find the Connection Block module */
|
2022-10-06 19:08:50 -05:00
|
|
|
/* We find the original connection block and then spot its unique mirror!
|
2020-02-14 11:45:24 -06:00
|
|
|
* Do NOT use module_sb here!!!
|
|
|
|
*/
|
2022-10-06 19:08:50 -05:00
|
|
|
t_rr_type cb_type =
|
|
|
|
find_top_module_cb_type_by_sb_side(side_manager.get_side());
|
|
|
|
vtr::Point<size_t> instance_gsb_cb_coordinate =
|
|
|
|
find_top_module_gsb_coordinate_by_sb_side(rr_gsb,
|
|
|
|
side_manager.get_side());
|
|
|
|
vtr::Point<size_t> module_gsb_cb_coordinate =
|
|
|
|
find_top_module_gsb_coordinate_by_sb_side(rr_gsb,
|
|
|
|
side_manager.get_side());
|
2020-02-14 11:45:24 -06:00
|
|
|
|
|
|
|
/* Skip those Connection blocks that do not exist:
|
2022-10-06 19:08:50 -05:00
|
|
|
* 1. The CB does not exist in the device level! We should skip!
|
|
|
|
* 2. The CB does exist but we need to make sure if the GSB includes such
|
|
|
|
* CBs For TOP and LEFT side, check the existence using RRGSB method
|
|
|
|
* is_cb_exist() FOr RIGHT and BOTTOM side, find the adjacent RRGSB and then
|
|
|
|
* use is_cb_exist()
|
2020-02-14 11:45:24 -06:00
|
|
|
*/
|
2022-10-06 19:08:50 -05:00
|
|
|
if (TOP == side_manager.get_side() || LEFT == side_manager.get_side()) {
|
|
|
|
if (false == rr_gsb.is_cb_exist(cb_type)) {
|
2020-02-14 11:45:24 -06:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
if (RIGHT == side_manager.get_side() || BOTTOM == side_manager.get_side()) {
|
|
|
|
const RRGSB& adjacent_gsb =
|
|
|
|
device_rr_gsb.get_gsb(module_gsb_cb_coordinate);
|
|
|
|
if (false == adjacent_gsb.is_cb_exist(cb_type)) {
|
2020-02-14 11:45:24 -06:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* If we use compact routing hierarchy, we should find the unique module of
|
|
|
|
* CB, which is added to the top module */
|
2020-02-14 11:45:24 -06:00
|
|
|
if (true == compact_routing_hierarchy) {
|
2022-10-06 19:08:50 -05:00
|
|
|
const RRGSB& unique_mirror =
|
|
|
|
device_rr_gsb.get_cb_unique_module(cb_type, module_gsb_cb_coordinate);
|
|
|
|
module_gsb_cb_coordinate.set_x(unique_mirror.get_x());
|
|
|
|
module_gsb_cb_coordinate.set_y(unique_mirror.get_y());
|
|
|
|
}
|
|
|
|
|
2020-02-14 11:45:24 -06:00
|
|
|
const RRGSB& module_cb = device_rr_gsb.get_gsb(module_gsb_cb_coordinate);
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::Point<size_t> module_cb_coordinate(module_cb.get_cb_x(cb_type),
|
|
|
|
module_cb.get_cb_y(cb_type));
|
|
|
|
std::string cb_module_name =
|
|
|
|
generate_connection_block_module_name(cb_type, module_cb_coordinate);
|
2020-02-14 11:45:24 -06:00
|
|
|
ModuleId cb_module_id = module_manager.find_module(cb_module_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(cb_module_id));
|
2022-10-06 19:08:50 -05:00
|
|
|
const RRGSB& instance_cb =
|
|
|
|
device_rr_gsb.get_gsb(instance_gsb_cb_coordinate);
|
|
|
|
vtr::Point<size_t> instance_cb_coordinate(instance_cb.get_cb_x(cb_type),
|
|
|
|
instance_cb.get_cb_y(cb_type));
|
|
|
|
size_t cb_instance = cb_instance_ids.at(
|
|
|
|
cb_type)[instance_cb_coordinate.x()][instance_cb_coordinate.y()];
|
|
|
|
|
|
|
|
for (size_t itrack = 0;
|
|
|
|
itrack < module_sb.get_chan_width(side_manager.get_side()); ++itrack) {
|
|
|
|
std::string sb_port_name = generate_sb_module_track_port_name(
|
|
|
|
rr_graph.node_type(
|
|
|
|
module_sb.get_chan_node(side_manager.get_side(), itrack)),
|
|
|
|
side_manager.get_side(),
|
|
|
|
module_sb.get_chan_node_direction(side_manager.get_side(), itrack));
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Prepare SB-related port information */
|
2022-10-06 19:08:50 -05:00
|
|
|
ModulePortId sb_port_id =
|
|
|
|
module_manager.find_module_port(sb_module_id, sb_port_name);
|
|
|
|
VTR_ASSERT(true ==
|
|
|
|
module_manager.valid_module_port_id(sb_module_id, sb_port_id));
|
2020-02-14 11:45:24 -06:00
|
|
|
BasicPort sb_port = module_manager.module_port(sb_module_id, sb_port_id);
|
2022-10-06 19:08:50 -05:00
|
|
|
|
|
|
|
/* Prepare CB-related port information */
|
2020-02-14 11:45:24 -06:00
|
|
|
PORTS cb_port_direction = OUT_PORT;
|
|
|
|
/* The cb port direction should be opposite to the sb port !!! */
|
2022-10-06 19:08:50 -05:00
|
|
|
if (OUT_PORT ==
|
|
|
|
module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
|
2020-02-14 11:45:24 -06:00
|
|
|
cb_port_direction = IN_PORT;
|
|
|
|
} else {
|
2022-10-06 19:08:50 -05:00
|
|
|
VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(
|
|
|
|
side_manager.get_side(), itrack));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Upper CB port is required if the routing tracks are on the top or right
|
|
|
|
* sides of the switch block, which indicated bottom and left sides of the
|
|
|
|
* connection blocks
|
2020-07-01 15:44:40 -05:00
|
|
|
*/
|
2022-10-06 19:08:50 -05:00
|
|
|
bool use_cb_upper_port =
|
|
|
|
(TOP == side_manager.get_side()) || (RIGHT == side_manager.get_side());
|
|
|
|
std::string cb_port_name = generate_cb_module_track_port_name(
|
|
|
|
cb_type, cb_port_direction, use_cb_upper_port);
|
|
|
|
ModulePortId cb_port_id =
|
|
|
|
module_manager.find_module_port(cb_module_id, cb_port_name);
|
|
|
|
VTR_ASSERT(true ==
|
|
|
|
module_manager.valid_module_port_id(cb_module_id, cb_port_id));
|
2020-02-14 11:45:24 -06:00
|
|
|
BasicPort cb_port = module_manager.module_port(cb_module_id, cb_port_id);
|
|
|
|
|
2020-06-30 18:50:53 -05:00
|
|
|
/* Configure the net source and sink:
|
2022-10-06 19:08:50 -05:00
|
|
|
* If sb port is an output (source), cb port is an input (sink)
|
|
|
|
* If sb port is an input (sink), cb port is an output (source)
|
2020-06-30 18:50:53 -05:00
|
|
|
*/
|
2022-10-06 19:08:50 -05:00
|
|
|
if (OUT_PORT ==
|
|
|
|
module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
|
|
|
|
ModuleNetId net =
|
|
|
|
create_module_source_pin_net(module_manager, top_module, sb_module_id,
|
|
|
|
sb_instance, sb_port_id, itrack / 2);
|
|
|
|
module_manager.add_module_net_sink(top_module, net, cb_module_id,
|
|
|
|
cb_instance, cb_port_id, itrack / 2);
|
2020-06-30 18:50:53 -05:00
|
|
|
} else {
|
2022-10-06 19:08:50 -05:00
|
|
|
VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(
|
|
|
|
side_manager.get_side(), itrack));
|
|
|
|
ModuleNetId net =
|
|
|
|
create_module_source_pin_net(module_manager, top_module, cb_module_id,
|
|
|
|
cb_instance, cb_port_id, itrack / 2);
|
|
|
|
module_manager.add_module_net_sink(top_module, net, sb_module_id,
|
|
|
|
sb_instance, sb_port_id, itrack / 2);
|
2020-02-14 11:45:24 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* Add module nets to connect the grid ports/pins to Connection Blocks
|
|
|
|
* and Switch Blocks
|
|
|
|
* To make it easy, this function will iterate over all the General
|
|
|
|
* Switch Blocks (GSBs), through which we can obtain the coordinates
|
2022-10-06 19:08:50 -05:00
|
|
|
* of all the grids, connection blocks and switch blocks that are
|
2020-02-14 11:45:24 -06:00
|
|
|
* supposed to be connected tightly.
|
|
|
|
*
|
|
|
|
* As such, we have completed all the connection for each grid.
|
|
|
|
* There is no need to iterate over the grids
|
|
|
|
*
|
|
|
|
* +-------------------------+ +---------------------------------+
|
|
|
|
* | | | Y-direction CB |
|
|
|
|
* | Grid[x][y+1] | | [x][y + 1] |
|
|
|
|
* | | +---------------------------------+
|
|
|
|
* +-------------------------+
|
|
|
|
* TOP SIDE
|
|
|
|
* +-------------+ +---------------------------------+
|
|
|
|
* | | | OPIN_NODE CHAN_NODES OPIN_NODES |
|
|
|
|
* | | | |
|
|
|
|
* | | | OPIN_NODES OPIN_NODES |
|
|
|
|
* | X-direction | | |
|
|
|
|
* | CB | LEFT SIDE | Switch Block | RIGHT SIDE
|
|
|
|
* | [x][y] | | [x][y] |
|
|
|
|
* | | | |
|
|
|
|
* | | | CHAN_NODES CHAN_NODES |
|
|
|
|
* | | | |
|
|
|
|
* | | | OPIN_NODES OPIN_NODES |
|
|
|
|
* | | | |
|
|
|
|
* | | | OPIN_NODE CHAN_NODES OPIN_NODES |
|
|
|
|
* +-------------+ +---------------------------------+
|
|
|
|
* BOTTOM SIDE
|
|
|
|
*******************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
void add_top_module_nets_connect_grids_and_gsbs(
|
|
|
|
ModuleManager& module_manager, const ModuleId& top_module,
|
|
|
|
const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids,
|
|
|
|
const vtr::Matrix<size_t>& grid_instance_ids, const RRGraphView& rr_graph,
|
|
|
|
const DeviceRRGSB& device_rr_gsb, const vtr::Matrix<size_t>& sb_instance_ids,
|
|
|
|
const std::map<t_rr_type, vtr::Matrix<size_t>>& cb_instance_ids,
|
|
|
|
const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin) {
|
2020-06-30 00:17:03 -05:00
|
|
|
vtr::ScopedStartFinishTimer timer("Add module nets between grids and GSBs");
|
|
|
|
|
2020-02-14 11:45:24 -06:00
|
|
|
vtr::Point<size_t> gsb_range = device_rr_gsb.get_gsb_range();
|
|
|
|
|
|
|
|
for (size_t ix = 0; ix < gsb_range.x(); ++ix) {
|
|
|
|
for (size_t iy = 0; iy < gsb_range.y(); ++iy) {
|
|
|
|
vtr::Point<size_t> gsb_coordinate(ix, iy);
|
|
|
|
const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy);
|
2020-03-24 18:39:26 -05:00
|
|
|
|
2020-02-14 11:45:24 -06:00
|
|
|
/* Connect the grid pins of the GSB to adjacent grids */
|
|
|
|
if (false == duplicate_grid_pin) {
|
2022-10-06 19:08:50 -05:00
|
|
|
add_top_module_nets_connect_grids_and_sb(
|
|
|
|
module_manager, top_module, vpr_device_annotation, grids,
|
|
|
|
grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, sb_instance_ids,
|
|
|
|
compact_routing_hierarchy);
|
2020-02-14 11:45:24 -06:00
|
|
|
} else {
|
|
|
|
VTR_ASSERT_SAFE(true == duplicate_grid_pin);
|
2022-10-06 19:08:50 -05:00
|
|
|
add_top_module_nets_connect_grids_and_sb_with_duplicated_pins(
|
|
|
|
module_manager, top_module, vpr_device_annotation, grids,
|
|
|
|
grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, sb_instance_ids,
|
|
|
|
compact_routing_hierarchy);
|
2020-02-14 11:45:24 -06:00
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
add_top_module_nets_connect_grids_and_cb(
|
|
|
|
module_manager, top_module, vpr_device_annotation, grids,
|
|
|
|
grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, CHANX,
|
|
|
|
cb_instance_ids.at(CHANX), compact_routing_hierarchy);
|
2020-02-14 11:45:24 -06:00
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
add_top_module_nets_connect_grids_and_cb(
|
|
|
|
module_manager, top_module, vpr_device_annotation, grids,
|
|
|
|
grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, CHANY,
|
|
|
|
cb_instance_ids.at(CHANY), compact_routing_hierarchy);
|
2020-02-14 11:45:24 -06:00
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
add_top_module_nets_connect_sb_and_cb(
|
|
|
|
module_manager, top_module, rr_graph, device_rr_gsb, rr_gsb,
|
|
|
|
sb_instance_ids, cb_instance_ids, compact_routing_hierarchy);
|
2020-02-14 11:45:24 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-11 16:09:40 -06:00
|
|
|
/********************************************************************
|
|
|
|
* Add global port connection for a given port of a physical tile
|
2022-10-06 19:08:50 -05:00
|
|
|
* that are defined as global in tile annotation
|
2020-11-11 16:09:40 -06:00
|
|
|
*******************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
static int build_top_module_global_net_for_given_grid_module(
|
|
|
|
ModuleManager& module_manager, const ModuleId& top_module,
|
|
|
|
const ModulePortId& top_module_port, const TileAnnotation& tile_annotation,
|
|
|
|
const TileGlobalPortId& tile_global_port,
|
|
|
|
const BasicPort& tile_port_to_connect,
|
|
|
|
const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids,
|
|
|
|
const vtr::Point<size_t>& grid_coordinate, const e_side& border_side,
|
|
|
|
const vtr::Matrix<size_t>& grid_instance_ids) {
|
|
|
|
t_physical_tile_type_ptr physical_tile =
|
|
|
|
grids[grid_coordinate.x()][grid_coordinate.y()].type;
|
|
|
|
/* Find the module name for this type of grid */
|
|
|
|
std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX);
|
|
|
|
std::string grid_module_name = generate_grid_block_module_name(
|
|
|
|
grid_module_name_prefix, std::string(physical_tile->name),
|
|
|
|
is_io_type(physical_tile), border_side);
|
|
|
|
ModuleId grid_module = module_manager.find_module(grid_module_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(grid_module));
|
|
|
|
size_t grid_instance =
|
|
|
|
grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()];
|
|
|
|
/* Find the source port at the top-level module */
|
|
|
|
BasicPort src_port = module_manager.module_port(top_module, top_module_port);
|
|
|
|
|
|
|
|
/* Walk through each instance considering the unique sub tile and capacity
|
|
|
|
* range, each instance may have an independent pin to be driven by a global
|
|
|
|
* net! */
|
2022-08-17 18:25:12 -05:00
|
|
|
for (const t_sub_tile& sub_tile : physical_tile->sub_tiles) {
|
2022-08-23 13:58:44 -05:00
|
|
|
VTR_ASSERT(1 == sub_tile.equivalent_sites.size());
|
|
|
|
int grid_pin_start_index = physical_tile->num_pins;
|
|
|
|
t_physical_tile_port physical_tile_port;
|
|
|
|
physical_tile_port.num_pins = 0;
|
|
|
|
|
|
|
|
/* Count the total number of pins for this type of sub tile */
|
2022-08-23 14:35:04 -05:00
|
|
|
int sub_tile_num_pins = sub_tile.num_phy_pins / sub_tile.capacity.total();
|
2022-08-23 13:58:44 -05:00
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* For each instance of the same sub tile type, find the port of the grid
|
|
|
|
* module according to the tile annotation A tile may consist of multiple
|
|
|
|
* subtile, connect to all the pins from sub tiles */
|
|
|
|
for (int subtile_index = sub_tile.capacity.low;
|
|
|
|
subtile_index <= sub_tile.capacity.high; subtile_index++) {
|
|
|
|
for (const t_physical_tile_port& tile_port : sub_tile.ports) {
|
2022-08-23 13:58:44 -05:00
|
|
|
if (std::string(tile_port.name) == tile_port_to_connect.get_name()) {
|
|
|
|
BasicPort ref_tile_port(tile_port.name, tile_port.num_pins);
|
|
|
|
/* Port size must match!!! */
|
|
|
|
if (false == ref_tile_port.contained(tile_port_to_connect)) {
|
2022-10-06 19:08:50 -05:00
|
|
|
VTR_LOG_ERROR(
|
|
|
|
"Tile annotation '%s' port '%s[%lu:%lu]' is out of the range of "
|
|
|
|
"physical tile port '%s[%lu:%lu]'!",
|
|
|
|
tile_annotation.global_port_name(tile_global_port).c_str(),
|
|
|
|
tile_port_to_connect.get_name().c_str(),
|
|
|
|
tile_port_to_connect.get_lsb(), tile_port_to_connect.get_msb(),
|
|
|
|
ref_tile_port.get_name().c_str(), ref_tile_port.get_lsb(),
|
|
|
|
ref_tile_port.get_msb());
|
2022-08-23 13:58:44 -05:00
|
|
|
return CMD_EXEC_FATAL_ERROR;
|
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
grid_pin_start_index =
|
|
|
|
(subtile_index - sub_tile.capacity.low) * sub_tile_num_pins +
|
|
|
|
tile_port.absolute_first_pin_index;
|
2022-08-23 13:58:44 -05:00
|
|
|
physical_tile_port = tile_port;
|
|
|
|
break;
|
2022-08-17 18:25:12 -05:00
|
|
|
}
|
2021-01-09 19:47:12 -06:00
|
|
|
}
|
2022-08-23 13:58:44 -05:00
|
|
|
/* Ensure the pin index is valid */
|
|
|
|
VTR_ASSERT(grid_pin_start_index < physical_tile->num_pins);
|
|
|
|
/* Ensure port width is in range */
|
|
|
|
VTR_ASSERT(src_port.get_width() == tile_port_to_connect.get_width());
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Create a pin id mapping between the source port (top module) and the
|
|
|
|
* sink port (grid module) */
|
2022-08-23 13:58:44 -05:00
|
|
|
std::map<size_t, size_t> sink2src_pin_map;
|
|
|
|
for (size_t ipin = 0; ipin < tile_port_to_connect.get_width(); ++ipin) {
|
|
|
|
size_t sink_pin = tile_port_to_connect.pins()[ipin];
|
|
|
|
size_t src_pin = src_port.pins()[ipin];
|
|
|
|
sink2src_pin_map[sink_pin] = src_pin;
|
|
|
|
}
|
2021-01-12 19:38:00 -06:00
|
|
|
|
2022-08-23 13:58:44 -05:00
|
|
|
/* Create the connections */
|
2022-10-06 19:08:50 -05:00
|
|
|
for (size_t pin_id = tile_port_to_connect.get_lsb();
|
|
|
|
pin_id < tile_port_to_connect.get_msb() + 1; ++pin_id) {
|
2022-08-23 13:58:44 -05:00
|
|
|
int grid_pin_index = grid_pin_start_index + pin_id;
|
2022-08-17 18:25:12 -05:00
|
|
|
/* Find the module pin */
|
|
|
|
size_t grid_pin_width = physical_tile->pin_width_offset[grid_pin_index];
|
2022-10-06 19:08:50 -05:00
|
|
|
size_t grid_pin_height =
|
|
|
|
physical_tile->pin_height_offset[grid_pin_index];
|
|
|
|
std::vector<e_side> pin_sides = find_physical_tile_pin_side(
|
|
|
|
physical_tile, grid_pin_index, border_side);
|
|
|
|
|
|
|
|
BasicPort grid_pin_info =
|
|
|
|
vpr_device_annotation.physical_tile_pin_port_info(physical_tile,
|
|
|
|
grid_pin_index);
|
2022-08-17 18:25:12 -05:00
|
|
|
VTR_ASSERT(true == grid_pin_info.is_valid());
|
|
|
|
|
|
|
|
/* Build nets */
|
|
|
|
for (const e_side& pin_side : pin_sides) {
|
2022-10-06 19:08:50 -05:00
|
|
|
std::string grid_port_name =
|
|
|
|
generate_grid_port_name(grid_pin_width, grid_pin_height,
|
|
|
|
subtile_index, pin_side, grid_pin_info);
|
|
|
|
ModulePortId grid_port_id =
|
|
|
|
module_manager.find_module_port(grid_module, grid_port_name);
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module,
|
|
|
|
grid_port_id));
|
|
|
|
|
|
|
|
VTR_ASSERT(
|
|
|
|
1 ==
|
|
|
|
module_manager.module_port(grid_module, grid_port_id).get_width());
|
|
|
|
|
|
|
|
ModuleNetId net = create_module_source_pin_net(
|
|
|
|
module_manager, top_module, top_module, 0, top_module_port,
|
|
|
|
src_port.pins()[sink2src_pin_map[pin_id]]);
|
2022-08-17 18:25:12 -05:00
|
|
|
VTR_ASSERT(ModuleNetId::INVALID() != net);
|
2022-10-06 19:08:50 -05:00
|
|
|
|
2022-08-17 18:25:12 -05:00
|
|
|
/* Configure the net sink */
|
2022-10-06 19:08:50 -05:00
|
|
|
BasicPort sink_port =
|
|
|
|
module_manager.module_port(grid_module, grid_port_id);
|
|
|
|
module_manager.add_module_net_sink(top_module, net, grid_module,
|
|
|
|
grid_instance, grid_port_id,
|
|
|
|
sink_port.pins()[0]);
|
2022-08-17 18:25:12 -05:00
|
|
|
}
|
2021-01-10 12:52:38 -06:00
|
|
|
}
|
2021-01-09 19:47:12 -06:00
|
|
|
}
|
2020-11-11 16:09:40 -06:00
|
|
|
}
|
2021-01-09 19:47:12 -06:00
|
|
|
|
|
|
|
return CMD_EXEC_SUCCESS;
|
2020-11-11 16:09:40 -06:00
|
|
|
}
|
|
|
|
|
2023-03-01 18:08:15 -06:00
|
|
|
/********************************************************************
|
|
|
|
* Add nets between a global port and its sinks at each grid modules
|
|
|
|
*******************************************************************/
|
2023-03-02 14:33:26 -06:00
|
|
|
static int build_top_module_global_net_from_grid_modules(
|
|
|
|
ModuleManager& module_manager, const ModuleId& top_module,
|
|
|
|
const ModulePortId& top_module_port, const TileAnnotation& tile_annotation,
|
|
|
|
const TileGlobalPortId& tile_global_port,
|
2023-03-01 18:08:15 -06:00
|
|
|
const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids,
|
|
|
|
const vtr::Matrix<size_t>& grid_instance_ids) {
|
|
|
|
int status = CMD_EXEC_SUCCESS;
|
2023-03-02 14:33:26 -06:00
|
|
|
|
|
|
|
std::map<e_side, std::vector<vtr::Point<size_t>>> io_coordinates =
|
|
|
|
generate_perimeter_grid_coordinates(grids);
|
|
|
|
|
2023-03-01 18:08:15 -06:00
|
|
|
for (size_t tile_info_id = 0;
|
|
|
|
tile_info_id <
|
|
|
|
tile_annotation.global_port_tile_names(tile_global_port).size();
|
|
|
|
++tile_info_id) {
|
|
|
|
std::string tile_name =
|
|
|
|
tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id];
|
|
|
|
BasicPort tile_port =
|
|
|
|
tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id];
|
|
|
|
/* Find the coordinates for the wanted tiles */
|
|
|
|
vtr::Point<size_t> start_coord(1, 1);
|
|
|
|
vtr::Point<size_t> end_coord(grids.width() - 1, grids.height() - 1);
|
|
|
|
vtr::Point<size_t> range = tile_annotation.global_port_tile_coordinates(
|
|
|
|
tile_global_port)[tile_info_id];
|
|
|
|
bool out_of_range = false;
|
|
|
|
|
|
|
|
/* -1 means all the x should be considered */
|
|
|
|
if (size_t(-1) != range.x()) {
|
|
|
|
if ((range.x() < start_coord.x()) || (range.x() > end_coord.x())) {
|
|
|
|
out_of_range = true;
|
|
|
|
} else {
|
|
|
|
/* Set the range */
|
|
|
|
start_coord.set_x(range.x());
|
|
|
|
end_coord.set_x(range.x());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -1 means all the y should be considered */
|
|
|
|
if (size_t(-1) != range.y()) {
|
|
|
|
if ((range.y() < start_coord.y()) || (range.y() > end_coord.y())) {
|
|
|
|
out_of_range = true;
|
|
|
|
} else {
|
|
|
|
/* Set the range */
|
|
|
|
start_coord.set_y(range.y());
|
|
|
|
end_coord.set_y(range.y());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Error out immediately if the coordinate is not valid! */
|
|
|
|
if (true == out_of_range) {
|
|
|
|
VTR_LOG_ERROR(
|
|
|
|
"Coordinate (%lu, %lu) in tile annotation for tile '%s' is out of "
|
|
|
|
"range (%lu:%lu, %lu:%lu)!",
|
2023-03-02 14:33:26 -06:00
|
|
|
range.x(), range.y(), tile_name.c_str(), start_coord.x(), end_coord.x(),
|
|
|
|
start_coord.y(), end_coord.y());
|
2023-03-01 18:08:15 -06:00
|
|
|
return CMD_EXEC_FATAL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Spot the port from child modules from core grids */
|
|
|
|
for (size_t ix = start_coord.x(); ix < end_coord.x(); ++ix) {
|
|
|
|
for (size_t iy = start_coord.y(); iy < end_coord.y(); ++iy) {
|
|
|
|
/* Bypass EMPTY tiles */
|
|
|
|
if (true == is_empty_type(grids[ix][iy].type)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
|
|
|
|
if ((0 < grids[ix][iy].width_offset) ||
|
|
|
|
(0 < grids[ix][iy].height_offset)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Bypass the tiles whose names do not match */
|
|
|
|
if (std::string(grids[ix][iy].type->name) != tile_name) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create nets and finish connection build-up */
|
|
|
|
status = build_top_module_global_net_for_given_grid_module(
|
|
|
|
module_manager, top_module, top_module_port, tile_annotation,
|
|
|
|
tile_global_port, tile_port, vpr_device_annotation, grids,
|
|
|
|
vtr::Point<size_t>(ix, iy), NUM_SIDES, grid_instance_ids);
|
|
|
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Walk through all the grids on the perimeter, which are I/O grids */
|
|
|
|
for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) {
|
2023-03-02 14:33:26 -06:00
|
|
|
for (const vtr::Point<size_t>& io_coordinate : io_coordinates[io_side]) {
|
2023-03-01 18:08:15 -06:00
|
|
|
/* Bypass EMPTY grid */
|
|
|
|
if (true ==
|
|
|
|
is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
|
|
|
|
if ((0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) ||
|
|
|
|
(0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Bypass the tiles whose names do not match */
|
|
|
|
if (std::string(
|
|
|
|
grids[io_coordinate.x()][io_coordinate.y()].type->name) !=
|
|
|
|
tile_name) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if the coordinate satisfy the tile coordinate defintion
|
|
|
|
* - Bypass if the x is a specific number (!= -1), and io_coordinate
|
|
|
|
* is different
|
|
|
|
* - Bypass if the y is a specific number (!= -1), and io_coordinate
|
|
|
|
* is different
|
|
|
|
*/
|
|
|
|
if ((size_t(-1) != range.x()) && (range.x() != io_coordinate.x())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((size_t(-1) != range.y()) && (range.y() != io_coordinate.y())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create nets and finish connection build-up */
|
|
|
|
status = build_top_module_global_net_for_given_grid_module(
|
|
|
|
module_manager, top_module, top_module_port, tile_annotation,
|
|
|
|
tile_global_port, tile_port, vpr_device_annotation, grids,
|
|
|
|
io_coordinate, io_side, grid_instance_ids);
|
|
|
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* Add nets between a global port and its sinks at an entry point of clock tree
|
|
|
|
*******************************************************************/
|
2023-03-02 14:33:26 -06:00
|
|
|
static int build_top_module_global_net_from_clock_arch_tree(
|
|
|
|
ModuleManager& module_manager, const ModuleId& top_module,
|
|
|
|
const ModulePortId& top_module_port, const RRGraphView& rr_graph,
|
|
|
|
const DeviceRRGSB& device_rr_gsb,
|
2023-03-02 01:27:29 -06:00
|
|
|
const std::map<t_rr_type, vtr::Matrix<size_t>>& cb_instance_ids,
|
2023-03-02 14:33:26 -06:00
|
|
|
const ClockNetwork& clk_ntwk, const std::string& clk_tree_name,
|
|
|
|
const RRClockSpatialLookup& rr_clock_lookup) {
|
2023-03-01 18:08:15 -06:00
|
|
|
int status = CMD_EXEC_SUCCESS;
|
|
|
|
|
|
|
|
/* Ensure the clock arch tree name is valid */
|
|
|
|
ClockTreeId clk_tree = clk_ntwk.find_tree(clk_tree_name);
|
|
|
|
if (!clk_ntwk.valid_tree_id(clk_tree)) {
|
2023-03-02 14:33:26 -06:00
|
|
|
VTR_LOG(
|
|
|
|
"Fail to find a matched clock tree '%s' in the clock architecture "
|
|
|
|
"definition",
|
|
|
|
clk_tree_name.c_str());
|
2023-03-01 18:08:15 -06:00
|
|
|
return CMD_EXEC_FATAL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ensure the clock tree width matches the global port size */
|
2023-03-02 14:33:26 -06:00
|
|
|
if (clk_ntwk.tree_width(clk_tree) !=
|
|
|
|
module_manager.module_port(top_module, top_module_port).get_width()) {
|
|
|
|
VTR_LOG(
|
|
|
|
"Clock tree '%s' does not have the same width '%lu' as the port '%'s of "
|
|
|
|
"FPGA top module",
|
|
|
|
clk_tree_name.c_str(), clk_ntwk.tree_width(clk_tree),
|
|
|
|
module_manager.module_port(top_module, top_module_port)
|
|
|
|
.get_name()
|
|
|
|
.c_str());
|
2023-03-01 18:08:15 -06:00
|
|
|
return CMD_EXEC_FATAL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ClockTreePinId pin : clk_ntwk.pins(clk_tree)) {
|
2023-03-02 14:33:26 -06:00
|
|
|
BasicPort src_port =
|
|
|
|
module_manager.module_port(top_module, top_module_port);
|
|
|
|
/* Add the module net */
|
|
|
|
ModuleNetId net = create_module_source_pin_net(
|
|
|
|
module_manager, top_module, top_module, 0, top_module_port,
|
|
|
|
src_port.pins()[size_t(pin)]);
|
|
|
|
VTR_ASSERT(ModuleNetId::INVALID() != net);
|
|
|
|
|
2023-03-02 01:27:29 -06:00
|
|
|
for (ClockSpineId spine : clk_ntwk.tree_top_spines(clk_tree)) {
|
2023-03-02 14:33:26 -06:00
|
|
|
vtr::Point<int> entry_point = clk_ntwk.spine_start_point(spine);
|
|
|
|
Direction entry_dir = clk_ntwk.spine_direction(spine);
|
|
|
|
t_rr_type entry_track_type = clk_ntwk.spine_track_type(spine);
|
|
|
|
/* Find the routing resource node of the entry point */
|
|
|
|
RRNodeId entry_rr_node =
|
|
|
|
rr_clock_lookup.find_node(entry_point.x(), entry_point.y(), clk_tree,
|
|
|
|
clk_ntwk.spine_level(spine), pin, entry_dir);
|
|
|
|
|
|
|
|
/* Get the connection block module and instance at the entry point */
|
|
|
|
const RRGSB& rr_gsb = device_rr_gsb.get_gsb_by_cb_coordinate(
|
|
|
|
entry_track_type, vtr::Point<size_t>(entry_point.x(), entry_point.y()));
|
|
|
|
ModuleId cb_module =
|
|
|
|
module_manager.find_module(generate_connection_block_module_name(
|
|
|
|
entry_track_type,
|
|
|
|
vtr::Point<size_t>(entry_point.x(), entry_point.y())));
|
|
|
|
size_t cb_instance =
|
|
|
|
cb_instance_ids.at(entry_track_type)[entry_point.x()][entry_point.y()];
|
|
|
|
ModulePinInfo des_pin_info = find_connection_block_module_chan_port(
|
|
|
|
module_manager, cb_module, rr_graph, rr_gsb, entry_track_type,
|
|
|
|
entry_rr_node);
|
|
|
|
|
|
|
|
/* Configure the net sink */
|
|
|
|
BasicPort sink_port =
|
|
|
|
module_manager.module_port(cb_module, des_pin_info.first);
|
|
|
|
module_manager.add_module_net_sink(top_module, net, cb_module,
|
|
|
|
cb_instance, des_pin_info.first,
|
|
|
|
sink_port.pins()[des_pin_info.second]);
|
2023-03-02 01:27:29 -06:00
|
|
|
}
|
2023-03-01 18:08:15 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2020-11-10 17:59:00 -06:00
|
|
|
/********************************************************************
|
2022-10-06 19:08:50 -05:00
|
|
|
* Add global ports from grid ports that are defined as global in tile
|
|
|
|
*annotation
|
2020-11-10 17:59:00 -06:00
|
|
|
*******************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
int add_top_module_global_ports_from_grid_modules(
|
|
|
|
ModuleManager& module_manager, const ModuleId& top_module,
|
|
|
|
const TileAnnotation& tile_annotation,
|
|
|
|
const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids,
|
2023-03-02 14:33:26 -06:00
|
|
|
const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb,
|
|
|
|
const std::map<t_rr_type, vtr::Matrix<size_t>>& cb_instance_ids,
|
|
|
|
const vtr::Matrix<size_t>& grid_instance_ids, const ClockNetwork& clk_ntwk,
|
|
|
|
const RRClockSpatialLookup& rr_clock_lookup) {
|
2021-01-09 19:47:12 -06:00
|
|
|
int status = CMD_EXEC_SUCCESS;
|
2020-11-10 17:59:00 -06:00
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Add the global ports which are NOT yet added to the top-level module
|
2020-11-10 17:59:00 -06:00
|
|
|
* (in different names than the global ports defined in circuit library
|
|
|
|
*/
|
|
|
|
std::vector<BasicPort> global_ports_to_add;
|
2022-10-06 19:08:50 -05:00
|
|
|
for (const TileGlobalPortId& tile_global_port :
|
|
|
|
tile_annotation.global_ports()) {
|
|
|
|
ModulePortId module_port = module_manager.find_module_port(
|
|
|
|
top_module, tile_annotation.global_port_name(tile_global_port));
|
|
|
|
/* The global port size is derived from the maximum port size among all the
|
|
|
|
* tile port defintion */
|
2020-11-10 17:59:00 -06:00
|
|
|
if (ModulePortId::INVALID() == module_port) {
|
2022-10-06 19:08:50 -05:00
|
|
|
BasicPort global_port_to_add;
|
|
|
|
global_port_to_add.set_name(
|
|
|
|
tile_annotation.global_port_name(tile_global_port));
|
2021-01-09 19:47:12 -06:00
|
|
|
size_t max_port_size = 0;
|
2022-10-06 19:08:50 -05:00
|
|
|
for (const BasicPort& tile_port :
|
|
|
|
tile_annotation.global_port_tile_ports(tile_global_port)) {
|
2021-01-09 19:47:12 -06:00
|
|
|
max_port_size = std::max(tile_port.get_width(), max_port_size);
|
|
|
|
}
|
|
|
|
global_port_to_add.set_width(max_port_size);
|
2020-11-10 17:59:00 -06:00
|
|
|
global_ports_to_add.push_back(global_port_to_add);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const BasicPort& global_port_to_add : global_ports_to_add) {
|
2022-10-06 19:08:50 -05:00
|
|
|
module_manager.add_port(top_module, global_port_to_add,
|
|
|
|
ModuleManager::MODULE_GLOBAL_PORT);
|
2020-11-10 17:59:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Add module nets */
|
2022-10-06 19:08:50 -05:00
|
|
|
for (const TileGlobalPortId& tile_global_port :
|
|
|
|
tile_annotation.global_ports()) {
|
2020-11-10 17:59:00 -06:00
|
|
|
/* Must found one valid port! */
|
2022-10-06 19:08:50 -05:00
|
|
|
ModulePortId top_module_port = module_manager.find_module_port(
|
|
|
|
top_module, tile_annotation.global_port_name(tile_global_port));
|
2020-11-10 21:31:14 -06:00
|
|
|
VTR_ASSERT(ModulePortId::INVALID() != top_module_port);
|
2020-11-11 16:09:40 -06:00
|
|
|
|
2023-03-01 18:08:15 -06:00
|
|
|
/* There are two cases when building the nets:
|
2023-03-02 14:33:26 -06:00
|
|
|
* - If the net will go through a dedicated clock tree network, the net will
|
|
|
|
* drive an input of a routing block
|
|
|
|
* - If the net will be directly wired to tiles, the net will drive an input
|
|
|
|
* of a tile
|
2023-03-01 18:08:15 -06:00
|
|
|
*/
|
2023-03-02 14:33:26 -06:00
|
|
|
if (!tile_annotation.global_port_clock_arch_tree_name(tile_global_port)
|
|
|
|
.empty()) {
|
|
|
|
status = build_top_module_global_net_from_clock_arch_tree(
|
|
|
|
module_manager, top_module, top_module_port, rr_graph, device_rr_gsb,
|
|
|
|
cb_instance_ids, clk_ntwk,
|
|
|
|
tile_annotation.global_port_clock_arch_tree_name(tile_global_port),
|
|
|
|
rr_clock_lookup);
|
2023-03-01 18:08:15 -06:00
|
|
|
} else {
|
2023-03-02 14:33:26 -06:00
|
|
|
status = build_top_module_global_net_from_grid_modules(
|
|
|
|
module_manager, top_module, top_module_port, tile_annotation,
|
|
|
|
tile_global_port, vpr_device_annotation, grids, grid_instance_ids);
|
2023-03-01 18:08:15 -06:00
|
|
|
}
|
|
|
|
if (status == CMD_EXEC_FATAL_ERROR) {
|
|
|
|
return status;
|
2020-11-10 17:59:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-09 19:47:12 -06:00
|
|
|
return status;
|
2020-11-10 17:59:00 -06:00
|
|
|
}
|
|
|
|
|
2023-04-23 00:57:37 -05:00
|
|
|
/********************************************************************
|
|
|
|
* Build the connection between the programming clock port at the top module and each configurable children
|
|
|
|
* Note that each programming clock pin drive one or more configuration regions
|
|
|
|
* For example:
|
|
|
|
* - pin[0] -> region 0, 1
|
|
|
|
* - pin[1] -> region 2, 3
|
|
|
|
*******************************************************************/
|
|
|
|
void add_top_module_nets_prog_clock(ModuleManager& module_manager,
|
|
|
|
const ModuleId& top_module,
|
|
|
|
const ModulePortId& src_port,
|
|
|
|
const ConfigProtocol& config_protocol) {
|
|
|
|
BasicPort src_port_info = module_manager.module_port(top_module, src_port);
|
|
|
|
for (size_t pin : src_port_info.pins()) {
|
|
|
|
/* Create the net */
|
|
|
|
ModuleNetId net = create_module_source_pin_net(
|
|
|
|
module_manager, top_module, top_module, 0,
|
|
|
|
src_port, src_port_info.pins()[pin_id]);
|
|
|
|
/* Find all the sink nodes and build the connection one by one */
|
|
|
|
for (size_t iregion : config_protocol.prog_clock_port_ccff_head_indices(BasicPort(src_port_info.get_name(), pin, pin))) {
|
|
|
|
ConfigRegionId config_region = ConfigRegionId(iregion);
|
|
|
|
for (size_t mem_index = 0; mem_index < module_manager
|
|
|
|
.region_configurable_children(
|
|
|
|
top_module, config_region)
|
|
|
|
.size();
|
|
|
|
++mem_index) {
|
|
|
|
ModuleId net_sink_module_id = module_manager.region_configurable_children(
|
|
|
|
top_module, config_region)[mem_index];
|
|
|
|
size_t net_sink_instance_id =
|
|
|
|
module_manager.region_configurable_child_instances(
|
|
|
|
top_module, config_region)[mem_index];
|
|
|
|
ModulePortId net_sink_port_id =
|
|
|
|
module_manager.find_module_port(net_sink_module_id, src_port_info.get_name());
|
|
|
|
BasicPort net_sink_port =
|
|
|
|
module_manager.module_port(net_sink_module_id, net_sink_port_id);
|
|
|
|
VTR_ASSERT(1 == net_sink_port.get_width());
|
|
|
|
for (size_t net_sink_pin_id : net_sink_port.pins()) {
|
|
|
|
/* Add net sink */
|
|
|
|
module_manager.add_module_net_sink(top_module, net, net_sink_module_id,
|
|
|
|
net_sink_instance_id, net_sink_port_id,
|
|
|
|
net_sink_port.pins()[net_sink_pin_id])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-14 11:45:24 -06:00
|
|
|
} /* end namespace openfpga */
|