Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
85b82b1
[test] add a strong test where clb, dsp and bram in a same tile, to v…
tangxifan Oct 24, 2025
1009339
[test] deploy new test to strong reg test
tangxifan Oct 24, 2025
6672c7a
[test] add new test
tangxifan Oct 24, 2025
9da2e46
[test] add new arch from openfpga
tangxifan Oct 24, 2025
83540ce
[test] add new blif benchmark for tileable direct connection strong t…
tangxifan Oct 24, 2025
90de0e8
[test] add new example arch to validate tileable direct connections
tangxifan Oct 24, 2025
615eb82
[test] reorg tasks
tangxifan Oct 24, 2025
da7c322
[test] deploy new tests to validate supertile with z_offset in direct…
tangxifan Oct 24, 2025
cafdcd1
[test] debug
tangxifan Oct 24, 2025
27d3040
[test] debug
tangxifan Oct 24, 2025
6fc15ec
[core] debug
tangxifan Oct 24, 2025
881255c
[core] now search all the sub tiles which contains the ports defined …
tangxifan Oct 24, 2025
df2a7de
[core] syntax
tangxifan Oct 24, 2025
2ea4ad0
[test] debug
tangxifan Oct 24, 2025
2107714
[test] update golden
tangxifan Oct 24, 2025
55ad286
[test] add missing golden results
tangxifan Oct 24, 2025
1067e11
Merge branch 'master' into xt_tileable_direct_strong
tangxifan Oct 24, 2025
e8ebafb
[core] add doxygen-style comments to vpr utility function
tangxifan Oct 24, 2025
d93f036
[core] simplify swap in if condition
tangxifan Oct 24, 2025
97c7bc8
Merge branch 'master' into xt_tileable_direct_strong
tangxifan Oct 24, 2025
9baa66e
[test] add arch file to validate direct connections across subtiles f…
tangxifan Oct 24, 2025
dcbe115
[test] add new testcases for strong reg tests about direct connection…
tangxifan Oct 24, 2025
bd589a9
[core] fixed the bug where IPIN coordinate does not consider pin offs…
tangxifan Oct 24, 2025
2ffbff3
[core] should sit with root location for IPIN
tangxifan Oct 24, 2025
68d6e23
[core] debug
tangxifan Oct 24, 2025
e11a7ee
[core] debug
tangxifan Oct 24, 2025
daa754f
[core] debug
tangxifan Oct 24, 2025
4c9b8fa
[test] update golden
tangxifan Oct 24, 2025
8d3ab0e
Merge branch 'xt_tileable_direct_strong' of github.com:verilog-to-rou…
tangxifan Oct 24, 2025
aa76d71
[doc] add examples
tangxifan Oct 24, 2025
35eeb2e
[doc] typo
tangxifan Oct 24, 2025
07e8b6f
[core] typo
tangxifan Oct 24, 2025
7ffcdf0
[doc] typo
tangxifan Oct 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions vpr/src/route/rr_graph_generation/clb2clb_directs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ std::vector<t_clb_to_clb_directs> alloc_and_load_clb_to_clb_directs(const std::v
clb_to_clb_directs[i].from_clb_type = physical_tile;

t_physical_tile_port tile_port = find_tile_port_by_name(physical_tile, port_name);
/* Find the sub tile indices */
clb_to_clb_directs[i].from_sub_tiles = find_sub_tile_indices_by_port_name(physical_tile, port_name);
if (clb_to_clb_directs[i].from_sub_tiles.empty()) {
VPR_THROW(VPR_ERROR_ARCH, "Unable to find sub tile under tile '%s' which contains the port %s.\n", tile_name.c_str(), port_name.data());
}

if (start_pin_index == UNDEFINED) {
VTR_ASSERT(start_pin_index == end_pin_index);
Expand Down
1 change: 1 addition & 0 deletions vpr/src/route/rr_graph_generation/clb2clb_directs.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/
struct t_clb_to_clb_directs {
t_physical_tile_type_ptr from_clb_type;
std::vector<int> from_sub_tiles;
int from_clb_pin_start_index;
int from_clb_pin_end_index;
t_physical_tile_type_ptr to_clb_type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1722,74 +1722,81 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph,
}

/* get every opin in the range */
for (int opin = min_index; opin <= max_index; ++opin) {
int offset = opin - min_index;
for (int relative_opin = min_index; relative_opin <= max_index; ++relative_opin) {
int offset = relative_opin - min_index;
//Capacity location determined by pin number relative to pins per capacity instance
auto [z, relative_opin] = get_capacity_location_from_physical_pin(grid_type, opin);
VTR_ASSERT(z >= 0 && z < grid_type->capacity);

if ((to_grid_coordinate.x() < grids.width() - 1)
&& (to_grid_coordinate.y() < grids.height() - 1)) {
int relative_ipin = UNDEFINED;
if (clb_to_clb_directs[i].to_clb_pin_start_index
> clb_to_clb_directs[i].to_clb_pin_end_index) {
if (true == swap) {
relative_ipin = clb_to_clb_directs[i].to_clb_pin_end_index + offset;
for (int z : clb_to_clb_directs[i].from_sub_tiles) {
int opin = get_physical_pin_from_capacity_location(grid_type, relative_opin, z);
VTR_ASSERT(z >= 0 && z < grid_type->capacity);

if ((to_grid_coordinate.x() < grids.width() - 1)
&& (to_grid_coordinate.y() < grids.height() - 1)) {
int relative_ipin = UNDEFINED;
if (clb_to_clb_directs[i].to_clb_pin_start_index
> clb_to_clb_directs[i].to_clb_pin_end_index) {
if (swap) {
relative_ipin = clb_to_clb_directs[i].to_clb_pin_end_index + offset;
} else {
relative_ipin = clb_to_clb_directs[i].to_clb_pin_start_index - offset;
}
} else {
relative_ipin = clb_to_clb_directs[i].to_clb_pin_start_index - offset;
if (swap) {
relative_ipin = clb_to_clb_directs[i].to_clb_pin_end_index - offset;
} else {
relative_ipin = clb_to_clb_directs[i].to_clb_pin_start_index + offset;
}
}
} else {
if (true == swap) {
relative_ipin = clb_to_clb_directs[i].to_clb_pin_end_index - offset;
} else {
relative_ipin = clb_to_clb_directs[i].to_clb_pin_start_index + offset;

/* Get the pin index in the rr_graph */
t_physical_tile_loc from_tile_loc(from_grid_coordinate.x(), from_grid_coordinate.y(), layer);
t_physical_tile_loc to_tile_loc(to_grid_coordinate.x(), to_grid_coordinate.y(), layer);

/* Find the side of grid pins, the pin location should be unique!
* Pin location is required by searching a node in rr_graph
*/
std::vector<e_side> opin_grid_side = find_grid_pin_sides(grids, layer, from_grid_coordinate.x() + grid_type->pin_width_offset[opin], from_grid_coordinate.y() + grid_type->pin_height_offset[opin], opin);
if (1 != opin_grid_side.size()) {
VPR_FATAL_ERROR(VPR_ERROR_ARCH, "[Arch LINE %d] From pin (index=%d) of direct connection '%s' does not exist on any side of the programmable block '%s'.\n", directs[i].line, opin, directs[i].from_pin.c_str());
}
}

/* Get the pin index in the rr_graph */
t_physical_tile_loc from_tile_loc(from_grid_coordinate.x(), from_grid_coordinate.y(), layer);
t_physical_tile_loc to_tile_loc(to_grid_coordinate.x(), to_grid_coordinate.y(), layer);
/* directs[i].sub_tile_offset is added to from_capacity(z) to get the target_capacity */
int to_subtile_cap = z + directs[i].sub_tile_offset;
/* Iterate over all sub_tiles to get the sub_tile which the target_cap belongs to. */
const t_sub_tile* to_sub_tile = nullptr;
for (const t_sub_tile& sub_tile : to_grid_type->sub_tiles) {
if (sub_tile.capacity.is_in_range(to_subtile_cap)) {
to_sub_tile = &sub_tile;
break;
}
}
VTR_ASSERT(to_sub_tile != nullptr);
if (relative_ipin >= to_sub_tile->num_phy_pins) continue;
// If this block has capacity > 1 then the pins of z position > 0 are offset
// by the number of pins per capacity instance
int ipin = get_physical_pin_from_capacity_location(to_grid_type, relative_ipin, to_subtile_cap);
std::vector<e_side> ipin_grid_side = find_grid_pin_sides(grids, layer, to_grid_coordinate.x() + to_grid_type->pin_width_offset[ipin], to_grid_coordinate.y() + to_grid_type->pin_height_offset[ipin], ipin);
if (1 != ipin_grid_side.size()) {
VPR_FATAL_ERROR(VPR_ERROR_ARCH, "[Arch LINE %d] To pin (index=%d) of direct connection '%s' does not exist on any side of the programmable block '%s'.\n", directs[i].line, relative_ipin, directs[i].to_pin.c_str());
}

/* Find the side of grid pins, the pin location should be unique!
* Pin location is required by searching a node in rr_graph
*/
std::vector<e_side> opin_grid_side = find_grid_pin_sides(grids, layer, from_grid_coordinate.x() + grid_type->pin_width_offset[opin], from_grid_coordinate.y() + grid_type->pin_height_offset[opin], opin);
if (1 != opin_grid_side.size()) {
VPR_FATAL_ERROR(VPR_ERROR_ARCH, "[Arch LINE %d] From pin (index=%d) of direct connection '%s' does not exist on any side of the programmable block '%s'.\n", directs[i].line, opin, directs[i].from_pin.c_str());
}

/* directs[i].sub_tile_offset is added to from_capacity(z) to get the target_capacity */
int to_subtile_cap = z + directs[i].sub_tile_offset;
/* Iterate over all sub_tiles to get the sub_tile which the target_cap belongs to. */
const t_sub_tile* to_sub_tile = nullptr;
for (const t_sub_tile& sub_tile : to_grid_type->sub_tiles) {
if (sub_tile.capacity.is_in_range(to_subtile_cap)) {
to_sub_tile = &sub_tile;
break;
RRNodeId opin_node_id = rr_graph.node_lookup().find_node(layer,
from_grid_coordinate.x() + grid_type->pin_width_offset[opin],
from_grid_coordinate.y() + grid_type->pin_height_offset[opin],
e_rr_type::OPIN, opin, opin_grid_side[0]);
RRNodeId ipin_node_id = rr_graph.node_lookup().find_node(layer,
to_grid_coordinate.x() + to_grid_type->pin_width_offset[ipin],
to_grid_coordinate.y() + to_grid_type->pin_height_offset[ipin],
e_rr_type::IPIN, ipin, ipin_grid_side[0]);

/* add edges to the opin_node */
if (!opin_node_id) {
VTR_ASSERT(opin_node_id);
}
if (!ipin_node_id) {
VTR_ASSERT(opin_node_id);
}
rr_graph_builder.create_edge_in_cache(opin_node_id, ipin_node_id, RRSwitchId(clb_to_clb_directs[i].switch_index), false);
}
VTR_ASSERT(to_sub_tile != nullptr);
if (relative_ipin >= to_sub_tile->num_phy_pins) continue;
// If this block has capacity > 1 then the pins of z position > 0 are offset
// by the number of pins per capacity instance
int ipin = get_physical_pin_from_capacity_location(to_grid_type, relative_ipin, to_subtile_cap);
std::vector<e_side> ipin_grid_side = find_grid_pin_sides(grids, layer, to_grid_coordinate.x() + to_grid_type->pin_width_offset[ipin], to_grid_coordinate.y() + to_grid_type->pin_height_offset[ipin], ipin);
if (1 != ipin_grid_side.size()) {
VPR_FATAL_ERROR(VPR_ERROR_ARCH, "[Arch LINE %d] To pin (index=%d) of direct connection '%s' does not exist on any side of the programmable block '%s'.\n", directs[i].line, relative_ipin, directs[i].to_pin.c_str());
}

RRNodeId opin_node_id = rr_graph.node_lookup().find_node(layer,
from_grid_coordinate.x() + grid_type->pin_width_offset[opin],
from_grid_coordinate.y() + grid_type->pin_height_offset[opin],
e_rr_type::OPIN, opin, opin_grid_side[0]);
RRNodeId ipin_node_id = rr_graph.node_lookup().find_node(layer,
to_grid_coordinate.x() + to_grid_type->pin_width_offset[ipin],
to_grid_coordinate.y() + to_grid_type->pin_height_offset[ipin],
e_rr_type::IPIN, ipin, ipin_grid_side[0]);

/* add edges to the opin_node */
VTR_ASSERT(opin_node_id && ipin_node_id);
rr_graph_builder.create_edge_in_cache(opin_node_id, ipin_node_id, RRSwitchId(clb_to_clb_directs[i].switch_index), false);
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions vpr/src/util/vpr_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,25 @@ int get_atom_pin_class_num(const AtomPinId atom_pin_id) {
return get_class_num_from_pin_physical_num(physical_type, pin_physical_num);
}

std::vector<int> find_sub_tile_indices_by_port_name(t_physical_tile_type_ptr type, std::string_view port_name) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tangxifan: I’m a little confused here. Let’s say I have a tile that has 5 subtiles of the same type. All of those subtiles would have the same port name… How would you get the index of a subtile then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will get all the indices of the subtiles as long as the subtile has a port in the required name. These subtiles can all be the starting point of a direct connection.

std::vector<int> ret;
for (const t_sub_tile& sub_tile : type->sub_tiles) {
bool matched = false;
for (const t_physical_tile_port& port : sub_tile.ports) {
if (port_name == port.name) {
matched = true;
break;
}
}
if (matched) {
for (int idx = sub_tile.capacity.low; idx <= sub_tile.capacity.high; ++idx) {
ret.push_back(idx);
}
}
}
return ret;
}

t_physical_tile_port find_tile_port_by_name(t_physical_tile_type_ptr type, std::string_view port_name) {
for (const t_sub_tile& sub_tile : type->sub_tiles) {
for (const t_physical_tile_port& port : sub_tile.ports) {
Expand Down
9 changes: 9 additions & 0 deletions vpr/src/util/vpr_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ bool is_clb_external_pin(ClusterBlockId blk_id, int pb_pin_id);
bool is_empty_type(t_physical_tile_type_ptr type);
bool is_empty_type(t_logical_block_type_ptr type);

/**
* @brief Returns the indices of sub tiles in a given physical type which contains the ports in a specified name. It will return all the sub tiles that contain the required port. Note that the sub tiles may be in different types
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nits: I think this should be:
"which contain the specified port name."
"Note that the sub tiles may be of different types"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

*
* @param type the pointer to the physical tile type descriptor
* @param port_name the name of the port as a qualifier to match sub tiles
* @return A vector of the indices of qualified sub tiles in the specified physical tile
*/
std::vector<int> find_sub_tile_indices_by_port_name(t_physical_tile_type_ptr type, std::string_view port_name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have a doxygen comment describing the function purpose, return type and parameters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code comments have been added.


/**
* @brief Returns the corresponding physical type given the location in the grid.
* @param loc The block location in the grid.
Expand Down
Loading