Skip to content

Add CHANZ type #3170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Jul 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
de9d16c
add chanz rr type
soheilshahrouz Jun 26, 2025
98fedf7
use CHANZ in alloc_and_load_inter_die_rr_node_indices()
soheilshahrouz Jun 26, 2025
b534741
update build_inter_die_custom_sb_rr_chan() to use CHANZ
soheilshahrouz Jun 26, 2025
76cd4fa
use CHANZ in get_switchblocks_edges()
soheilshahrouz Jun 26, 2025
6700da8
update verify_rr_node_indices() to check for CHANZ
soheilshahrouz Jun 26, 2025
b4dd148
handled CHANZ in some RR checks
soheilshahrouz Jun 27, 2025
0f394fc
consider CHANZ in RRSpatialLookup::find_channel_nodes()
soheilshahrouz Jun 27, 2025
330cad7
fix errors related to CHANZ connectivity in check_route.cpp
soheilshahrouz Jun 27, 2025
b9e25c6
ignore chanz in rr_graph_area.cpp
soheilshahrouz Jun 27, 2025
790b867
make format
soheilshahrouz Jun 27, 2025
d2ce164
add comment on how we handle chanz nodes
soheilshahrouz Jun 27, 2025
f9a5f1f
Merge branch 'master' into temp_add_chanz
soheilshahrouz Jun 27, 2025
385e95b
add CHANZ to rrgraph serializer
soheilshahrouz Jun 27, 2025
9079e49
added CHANZ to rr_graph.xsd
soheilshahrouz Jun 29, 2025
539aa56
auto generate uxsdcx files and update the interface implementation to…
soheilshahrouz Jun 29, 2025
08950f5
consider CHANZ nodes in map lookahead
soheilshahrouz Jun 29, 2025
3aeb6fb
Merge branch 'master' into temp_add_chanz
soheilshahrouz Jul 3, 2025
9b35d59
add chanz to is_inter_cluster_node
soheilshahrouz Jul 4, 2025
a39be3e
CHANZ is treated similar to CHANX/CHANY in area estimation
soheilshahrouz Jul 5, 2025
fff2dc5
refactor chan node adjacency checks
soheilshahrouz Jul 6, 2025
4213c3a
is_chan --> is_chanxy && handle chanz in get_adjusted_rr_position()
soheilshahrouz Jul 6, 2025
e3f7513
add comment explaining why the length of CHANZ nodes are 1
soheilshahrouz Jul 6, 2025
fc411bd
widened the x/y limit for chanz nodes from w/h-2 to w/h-1
soheilshahrouz Jul 6, 2025
d0cc966
check that node layer matches between indices and graph
soheilshahrouz Jul 6, 2025
c9eb503
factor out the code at the end of this routine that checks rr_node_co…
soheilshahrouz Jul 6, 2025
9f08030
comment for chanz type ++ set number of track for chanz when checking…
soheilshahrouz Jul 6, 2025
641de49
make format
soheilshahrouz Jul 6, 2025
a79a4c3
widen CHANX and CHANY limits in check_rr_node()
soheilshahrouz Jul 7, 2025
8cb6d7b
update golden results under strong/3d_sb
soheilshahrouz Jul 7, 2025
3feadb9
Merge branch 'master' into temp_add_chanz
soheilshahrouz Jul 8, 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
73 changes: 40 additions & 33 deletions libs/librrgraph/src/base/check_rr_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ void check_rr_graph(const RRGraphView& rr_graph,
route_type = e_route_type::GLOBAL;
}

auto total_edges_to_node = std::vector<int>(rr_graph.num_nodes());
auto switch_types_from_current_to_node = std::vector<unsigned char>(rr_graph.num_nodes());
std::vector<int> total_edges_to_node(rr_graph.num_nodes());
std::vector<unsigned char> switch_types_from_current_to_node(rr_graph.num_nodes());
const int num_rr_switches = rr_graph.num_rr_switches();

std::vector<std::pair<int, int>> edges;

for (const RRNodeId& rr_node : rr_graph.nodes()) {
for (const RRNodeId rr_node : rr_graph.nodes()) {
size_t inode = (size_t)rr_node;
rr_graph.validate_node(rr_node);

Expand All @@ -83,7 +83,7 @@ void check_rr_graph(const RRGraphView& rr_graph,

check_rr_node(rr_graph, rr_indexed_data, grid, chan_width, route_type, inode, is_flat);

/* Check all the connectivity (edges, etc.) information. */
// Check all the connectivity (edges, etc.) information.
edges.resize(0);
edges.reserve(num_edges);

Expand Down Expand Up @@ -329,16 +329,15 @@ void check_rr_node(const RRGraphView& rr_graph,
const enum e_route_type route_type,
const int inode,
bool is_flat) {
/* This routine checks that the rr_node is inside the grid and has a valid
* pin number, etc.
*/

//Make sure over-flow doesn't happen
VTR_ASSERT(inode >= 0);
int nodes_per_chan, tracks_per_node;
float C, R;
int tracks_per_node;
RRNodeId rr_node = RRNodeId(inode);

const int grid_width = grid.width();
const int grid_height = grid.height();
const int grid_layers = grid.get_num_layers();

e_rr_type rr_type = rr_graph.node_type(rr_node);
int xlow = rr_graph.node_xlow(rr_node);
int xhigh = rr_graph.node_xhigh(rr_node);
Expand All @@ -348,19 +347,18 @@ void check_rr_node(const RRGraphView& rr_graph,
int ptc_num = rr_graph.node_ptc_num(rr_node);
int capacity = rr_graph.node_capacity(rr_node);
RRIndexedDataId cost_index = rr_graph.node_cost_index(rr_node);
t_physical_tile_type_ptr type = nullptr;

if (xlow > xhigh || ylow > yhigh) {
VPR_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: rr endpoints are (%d,%d) and (%d,%d).\n", xlow, ylow, xhigh, yhigh);
}

if (xlow < 0 || xhigh > int(grid.width()) - 1 || ylow < 0 || yhigh > int(grid.height()) - 1) {
if (xlow < 0 || xhigh > grid_width - 1 || ylow < 0 || yhigh > grid_height - 1) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: rr endpoints (%d,%d) and (%d,%d) are out of range.\n", xlow, ylow, xhigh, yhigh);
}

if (layer_num < 0 || layer_num > int(grid.get_num_layers()) - 1) {
if (layer_num < 0 || layer_num > grid_layers - 1) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: rr endpoints layer_num (%d) is out of range.\n", layer_num);
}
Expand All @@ -375,8 +373,8 @@ void check_rr_node(const RRGraphView& rr_graph,
"in check_rr_node: node %d cost index (%d) is out of range.\n", inode, cost_index);
}

/* Check that the segment is within the array and such. */
type = grid.get_physical_type({xlow, ylow, layer_num});
// Check that the segment is within the array and such.
t_physical_tile_type_ptr type = grid.get_physical_type({xlow, ylow, layer_num});

switch (rr_type) {
case e_rr_type::SOURCE:
Expand Down Expand Up @@ -416,7 +414,7 @@ void check_rr_node(const RRGraphView& rr_graph,
break;

case e_rr_type::CHANX:
if (xlow < 1 || xhigh > int(grid.width()) - 2 || yhigh > int(grid.height()) - 2 || yhigh != ylow) {
if (xlow < 1 || xhigh > grid_width - 1 || yhigh > grid_height - 1 || yhigh != ylow) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: CHANX out of range for endpoints (%d,%d) and (%d,%d)\n", xlow, ylow, xhigh, yhigh);
}
Expand All @@ -427,7 +425,7 @@ void check_rr_node(const RRGraphView& rr_graph,
break;

case e_rr_type::CHANY:
if (xhigh > int(grid.width()) - 2 || ylow < 1 || yhigh > int(grid.height()) - 2 || xlow != xhigh) {
if (xhigh > grid_width - 1 || ylow < 1 || yhigh > grid_height - 1 || xlow != xhigh) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"Error in check_rr_node: CHANY out of range for endpoints (%d,%d) and (%d,%d)\n", xlow, ylow, xhigh, yhigh);
}
Expand All @@ -437,12 +435,20 @@ void check_rr_node(const RRGraphView& rr_graph,
}
break;

case e_rr_type::CHANZ:
if (xhigh != xlow || yhigh != ylow || xhigh > grid_width - 1 || ylow < 1 || yhigh > grid_height - 1) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"Error in check_rr_node: CHANZ out of range for endpoints (%d,%d) and (%d,%d)\n", xlow, ylow, xhigh, yhigh);
}
// TODO: handle global routing case
break;

default:
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: Unexpected segment type: %d\n", rr_type);
}

/* Check that it's capacities and such make sense. */
// Check that its capacities and such make sense.

int class_max_ptc = get_tile_class_max_ptc(type, is_flat);
int pin_max_ptc = get_tile_pin_max_ptc(type, is_flat);
Expand Down Expand Up @@ -481,20 +487,9 @@ void check_rr_node(const RRGraphView& rr_graph,
case e_rr_type::CHANX:
case e_rr_type::CHANY:
if (route_type == e_route_type::DETAILED) {
nodes_per_chan = chan_width.max;
tracks_per_node = 1;
} else {
nodes_per_chan = 1;
tracks_per_node = ((rr_type == e_rr_type::CHANX) ? chan_width.x_list[ylow] : chan_width.y_list[xlow]);
}

//if a chanx/chany has length 0, it means it is used to connect different dice together
//hence, the ptc number can be larger than nodes_per_chan
if(xlow != xhigh || ylow != yhigh) {
if (ptc_num >= nodes_per_chan) {
VPR_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: inode %d (type %d) has a ptc_num of %d.\n", inode, rr_type, ptc_num);
}
tracks_per_node = (rr_type == e_rr_type::CHANX) ? chan_width.x_list[ylow] : chan_width.y_list[xlow];
}

if (capacity != tracks_per_node) {
Expand All @@ -503,14 +498,26 @@ void check_rr_node(const RRGraphView& rr_graph,
}
break;

case e_rr_type::CHANZ:
if (route_type == e_route_type::DETAILED) {
tracks_per_node = 1;
} else {
// TODO: do checks for CHANZ type when global routing is enabled
// This can be done once we have a way to specify how many chanz
// nodes per switch block exist.
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: Global routing is not supported in 3D architectures.\n");
}
break;

default:
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: Unexpected segment type: %d\n", rr_type);
}

/* Check that the capacitance and resistance are reasonable. */
C = rr_graph.node_C(rr_node);
R = rr_graph.node_R(rr_node);
// Check that the capacitance and resistance are reasonable.
float C = rr_graph.node_C(rr_node);
float R = rr_graph.node_R(rr_node);

if (rr_type == e_rr_type::CHANX || rr_type == e_rr_type::CHANY) {
if (C < 0. || R < 0.) {
Expand Down
21 changes: 21 additions & 0 deletions libs/librrgraph/src/base/check_rr_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,27 @@ void check_rr_graph(const RRGraphView& rr_graph,
const e_graph_type graph_type,
bool is_flat);

/**
* @brief Validates the internal consistency of a single RR node in the routing resource graph.
*
* This function performs a series of checks on the specified RR node to ensure it conforms
* to architectural and routing constraints. It verifies:
* - That the node's bounding box is valid and within the device grid bounds.
* - That the node's PTC number, capacity, and cost index are within legal limits.
* - That IPINs, OPINs, SOURCEs, and SINKs correspond to valid physical locations and types.
* - That CHANX, CHANY, and CHANZ nodes have legal coordinate bounds and track indices.
* - That electrical characteristics (resistance and capacitance) are appropriate for the node type.
*
* Errors or inconsistencies will cause fatal errors or logged messages, depending on severity.
*
* @param rr_graph The read-only view of the routing resource graph.
* @param rr_indexed_data Indexed data for RR node cost metrics.
* @param grid The device grid.
* @param chan_width The channel widths for different channels
* @param route_type The routing type (GLOBAL or DETAILED).
* @param inode The index of the RR node to be checked.
* @param is_flat Flag indicating if flat routing is enabled.
*/
void check_rr_node(const RRGraphView& rr_graph,
const vtr::vector<RRIndexedDataId, t_rr_indexed_data>& rr_indexed_data,
const DeviceGrid& grid,
Expand Down
1 change: 1 addition & 0 deletions libs/librrgraph/src/base/rr_graph_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void RRGraphBuilder::add_node_to_all_locs(RRNodeId node) {
switch (node_type) {
case e_rr_type::SOURCE:
case e_rr_type::SINK:
case e_rr_type::CHANZ:
case e_rr_type::CHANY:
case e_rr_type::CHANX:
node_lookup_.add_node(node, node_layer, ix, iy, node_type, node_ptc_num, TOTAL_2D_SIDES[0]);
Expand Down
31 changes: 14 additions & 17 deletions libs/librrgraph/src/base/rr_graph_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,8 @@ void t_rr_graph_storage::set_node_pin_num(RRNodeId id, int new_pin_num) {
}

void t_rr_graph_storage::set_node_track_num(RRNodeId id, int new_track_num) {
if (node_type(id) != e_rr_type::CHANX && node_type(id) != e_rr_type::CHANY) {
VTR_LOG_ERROR("Attempted to set RR node 'track_num' for non-CHANX/CHANY type '%s'", node_type_string(id));
if (node_type(id) != e_rr_type::CHANX && node_type(id) != e_rr_type::CHANY && node_type(id) != e_rr_type::CHANZ) {
VTR_LOG_ERROR("Attempted to set RR node 'track_num' for non-CHANX/CHANY/CHANZ type '%s'", node_type_string(id));
}
node_ptc_[id].ptc_.track_num = new_track_num;
}
Expand All @@ -663,32 +663,29 @@ int t_rr_graph_storage::node_ptc_num(RRNodeId id) const {
return node_ptc_[id].ptc_.pin_num;
}

static int get_node_pin_num(
vtr::array_view_id<RRNodeId, const t_rr_node_data> node_storage,
vtr::array_view_id<RRNodeId, const t_rr_node_ptc_data> node_ptc,
RRNodeId id) {
static int get_node_pin_num(vtr::array_view_id<RRNodeId, const t_rr_node_data> node_storage,
vtr::array_view_id<RRNodeId, const t_rr_node_ptc_data> node_ptc,
RRNodeId id) {
e_rr_type node_type = node_storage[id].type_;
if (node_type != e_rr_type::IPIN && node_type != e_rr_type::OPIN) {
VTR_LOG_ERROR("Attempted to access RR node 'pin_num' for non-IPIN/OPIN type '%s'", rr_node_typename[node_type]);
}
return node_ptc[id].ptc_.pin_num;
}

static int get_node_track_num(
vtr::array_view_id<RRNodeId, const t_rr_node_data> node_storage,
vtr::array_view_id<RRNodeId, const t_rr_node_ptc_data> node_ptc,
RRNodeId id) {
static int get_node_track_num(vtr::array_view_id<RRNodeId, const t_rr_node_data> node_storage,
vtr::array_view_id<RRNodeId, const t_rr_node_ptc_data> node_ptc,
RRNodeId id) {
e_rr_type node_type = node_storage[id].type_;
if (node_type != e_rr_type::CHANX && node_type != e_rr_type::CHANY) {
VTR_LOG_ERROR("Attempted to access RR node 'track_num' for non-CHANX/CHANY type '%s'", rr_node_typename[node_type]);
if (node_type != e_rr_type::CHANX && node_type != e_rr_type::CHANY && node_type != e_rr_type::CHANZ) {
VTR_LOG_ERROR("Attempted to access RR node 'track_num' for non-CHANX/CHANY/CHANZ type '%s'", rr_node_typename[node_type]);
}
return node_ptc[id].ptc_.track_num;
}

static int get_node_class_num(
vtr::array_view_id<RRNodeId, const t_rr_node_data> node_storage,
vtr::array_view_id<RRNodeId, const t_rr_node_ptc_data> node_ptc,
RRNodeId id) {
static int get_node_class_num(vtr::array_view_id<RRNodeId, const t_rr_node_data> node_storage,
vtr::array_view_id<RRNodeId, const t_rr_node_ptc_data> node_ptc,
RRNodeId id) {
e_rr_type node_type = node_storage[id].type_;
if (node_type != e_rr_type::SOURCE && node_type != e_rr_type::SINK) {
VTR_LOG_ERROR("Attempted to access RR node 'class_num' for non-SOURCE/SINK type '%s'", rr_node_typename[node_type]);
Expand Down Expand Up @@ -760,7 +757,7 @@ void t_rr_graph_storage::set_node_capacity(RRNodeId id, short new_capacity) {
}

void t_rr_graph_storage::set_node_direction(RRNodeId id, Direction new_direction) {
if (node_type(id) != e_rr_type::CHANX && node_type(id) != e_rr_type::CHANY) {
if (node_type(id) != e_rr_type::CHANX && node_type(id) != e_rr_type::CHANY && node_type(id) != e_rr_type::CHANZ) {
VTR_LOG_ERROR("Attempted to set RR node 'direction' for non-channel type '%s'", node_type_string(id));
}
node_storage_[id].dir_side_.direction = new_direction;
Expand Down
Loading