Skip to content

[WIP] 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

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
46 changes: 21 additions & 25 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,14 +329,9 @@ 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);

e_rr_type rr_type = rr_graph.node_type(rr_node);
Expand Down Expand Up @@ -437,6 +432,14 @@ void check_rr_node(const RRGraphView& rr_graph,
}
break;

case e_rr_type::CHANZ:
if (xhigh != xlow || yhigh != ylow || xhigh > int(grid.width()) - 2 || ylow < 1 || yhigh > int(grid.height()) - 2) {
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);
Expand Down Expand Up @@ -481,20 +484,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 +495,18 @@ void check_rr_node(const RRGraphView& rr_graph,
}
break;

case e_rr_type::CHANZ:
// TODO: do checks for CHANZ type
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
23 changes: 10 additions & 13 deletions libs/librrgraph/src/base/rr_graph_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,18 @@ static void rr_walk_cluster_recursive(const RRGraphView& rr_graph,
}

std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
const RRNodeId& from_node,
const RRNodeId& to_node) {
RRNodeId from_node,
RRNodeId to_node) {
std::vector<RRSwitchId> switches;
std::vector<RREdgeId> edges = rr_graph.find_edges(from_node, to_node);
if (true == edges.empty()) {
if (edges.empty()) {
/* edge is open, we return an empty vector of switches */
return switches;
}

/* Reach here, edge list is not empty, find switch id one by one
* and update the switch list
*/
for (auto edge : edges) {
// Reach here, edge list is not empty, find switch id one by one
// and update the switch list
for (RREdgeId edge : edges) {
switches.push_back(rr_graph.edge_switch(edge));
}

Expand All @@ -82,10 +81,8 @@ int seg_index_of_cblock(const RRGraphView& rr_graph, e_rr_type from_rr_type, int
}

int seg_index_of_sblock(const RRGraphView& rr_graph, int from_node, int to_node) {
e_rr_type from_rr_type, to_rr_type;

from_rr_type = rr_graph.node_type(RRNodeId(from_node));
to_rr_type = rr_graph.node_type(RRNodeId(to_node));
e_rr_type from_rr_type = rr_graph.node_type(RRNodeId(from_node));
e_rr_type to_rr_type = rr_graph.node_type(RRNodeId(to_node));

if (from_rr_type == e_rr_type::CHANX) {
if (to_rr_type == e_rr_type::CHANY) {
Expand Down Expand Up @@ -135,7 +132,7 @@ vtr::vector<RRNodeId, std::vector<RREdgeId>> get_fan_in_list(const RRGraphView&
node_fan_in_list.resize(rr_graph.num_nodes(), std::vector<RREdgeId>(0));
node_fan_in_list.shrink_to_fit();

//Walk the graph and increment fanin on all dwnstream nodes
// Walk the graph and increment fanin on all downstream nodes
rr_graph.rr_nodes().for_each_edge(
[&](RREdgeId edge, RRNodeId src, RRNodeId sink) -> void {
(void) src;
Expand Down Expand Up @@ -238,7 +235,7 @@ void rr_set_sink_locs(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_buil

bool inter_layer_connections_limited_to_opin(const RRGraphView& rr_graph) {
bool limited_to_opin = true;
for (const auto& from_node : rr_graph.nodes()) {
for (const RRNodeId from_node : rr_graph.nodes()) {
for (t_edge_size edge : rr_graph.edges(from_node)) {
RRNodeId to_node = rr_graph.edge_sink_node(from_node, edge);
int from_layer = rr_graph.node_layer(from_node);
Expand Down
4 changes: 2 additions & 2 deletions libs/librrgraph/src/base/rr_graph_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ struct t_cluster_pin_chain {
* @return A vector of switch IDs
*/
std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
const RRNodeId& from_node,
const RRNodeId& to_node);
RRNodeId from_node,
RRNodeId to_node);

/**
* @brief This function generates and returns a vector indexed by RRNodeId containing a vector of fan-in edges for each node.
Expand Down
15 changes: 11 additions & 4 deletions libs/librrgraph/src/base/rr_graph_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,19 @@ class RRGraphView {
}

/** @brief Return the length (number of grid tile units spanned by the wire, including the endpoints) of a specified node.
* @note node_length() only applies to CHANX or CHANY and is always a positive number
* @note node_length() only applies to CHANX or CHANY or CHANZ and is always a positive number
*/
inline int node_length(RRNodeId node) const {
VTR_ASSERT(node_type(node) == e_rr_type::CHANX || node_type(node) == e_rr_type::CHANY);
VTR_ASSERT(node_type(node) == e_rr_type::CHANX || node_type(node) == e_rr_type::CHANY || node_type(node) == e_rr_type::CHANZ);

if (node_type(node) == e_rr_type::CHANZ) {
return 1;
}

if (node_direction(node) == Direction::NONE) {
return 0; //length zero wire
}

int length = 1 + node_xhigh(node) - node_xlow(node) + node_yhigh(node) - node_ylow(node);
VTR_ASSERT_SAFE(length > 0);
return length;
Expand All @@ -257,7 +263,8 @@ class RRGraphView {
}

/** @brief Check if two routing resource nodes are adjacent (must be a CHANX and a CHANY).
* @note This function performs error checking by determining whether two nodes are physically adjacent based on their geometry. It does not verify the routing edges to confirm if a connection is feasible within the current routing graph.
* @note This function performs error checking by determining whether two nodes are physically adjacent based on their geometry.
* It does not verify the routing edges to confirm if a connection is feasible within the current routing graph.
*/
inline bool nodes_are_adjacent(RRNodeId chanx_node, RRNodeId chany_node) const {
VTR_ASSERT(node_type(chanx_node) == e_rr_type::CHANX && node_type(chany_node) == e_rr_type::CHANY);
Expand Down Expand Up @@ -332,7 +339,7 @@ class RRGraphView {
start_x = " (" + std::to_string(node_xhigh(node)) + ",";
start_y = std::to_string(node_yhigh(node)) + ",";
start_layer_str = std::to_string(node_layer_num) + ")";
} else if (node_type(node) == e_rr_type::CHANX || node_type(node) == e_rr_type::CHANY) { //for channels, we would like to describe the component with segment specific information
} else if (node_type(node) == e_rr_type::CHANX || node_type(node) == e_rr_type::CHANY || node_type(node) == e_rr_type::CHANZ) { //for channels, we would like to describe the component with segment specific information
RRIndexedDataId cost_index = node_cost_index(node);
int seg_index = rr_indexed_data_[cost_index].seg_index;
coordinate_string += rr_segments(RRSegmentId(seg_index)).name; //Write the segment name
Expand Down
10 changes: 7 additions & 3 deletions libs/librrgraph/src/base/rr_node_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,22 @@ enum class e_rr_type : unsigned char {
OPIN, ///<Output pin of a block
CHANX, ///<x-directed routing wire, or an x-directed segment of a channel for global routing
CHANY, ///<y-directed routing wire, or a y-directed segment of a channel for global routing
CHANZ, ///<z-directed routing wire used to connect two different layers
NUM_RR_TYPES
};

/// Used to iterate for different e_rr_type values in range-based for loops.
constexpr std::array<e_rr_type, (size_t)e_rr_type::NUM_RR_TYPES> RR_TYPES = {{e_rr_type::SOURCE, e_rr_type::SINK, e_rr_type::IPIN,
e_rr_type::OPIN, e_rr_type::CHANX, e_rr_type::CHANY}};
constexpr std::array<e_rr_type, (size_t)e_rr_type::NUM_RR_TYPES> RR_TYPES = {{e_rr_type::SOURCE, e_rr_type::SINK,
e_rr_type::IPIN, e_rr_type::OPIN,
e_rr_type::CHANX, e_rr_type::CHANY, e_rr_type::CHANZ}};

/**
* @brief Lookup for the string representation of the given node type. This is useful
* for logging the type of an RR node.
*/
constexpr vtr::array<e_rr_type, const char*, (size_t)e_rr_type::NUM_RR_TYPES> rr_node_typename {"SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY"};
constexpr vtr::array<e_rr_type, const char*, (size_t)e_rr_type::NUM_RR_TYPES> rr_node_typename {"SOURCE", "SINK",
"IPIN", "OPIN",
"CHANX", "CHANY", "CHANZ"};

/**
* @enum Direction
Expand Down
12 changes: 6 additions & 6 deletions libs/librrgraph/src/base/rr_spatial_lookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ std::vector<RRNodeId> RRSpatialLookup::find_channel_nodes(int layer,
int x,
int y,
e_rr_type type) const {
/* Pre-check: node type should be routing tracks! */
if (type != e_rr_type::CHANX && type != e_rr_type::CHANY) {
return std::vector<RRNodeId>();
// Pre-check: node type should be routing tracks.
if (type != e_rr_type::CHANX && type != e_rr_type::CHANY && type != e_rr_type::CHANZ) {
return {};
}

return find_nodes(layer, x, y, type);
Expand All @@ -167,7 +167,7 @@ std::vector<RRNodeId> RRSpatialLookup::find_nodes_at_all_sides(int layer,
/* TODO: Consider to access the raw data like find_node() rather than calling find_node() many times, which hurts runtime */
if (rr_type == e_rr_type::IPIN || rr_type == e_rr_type::OPIN) {
indices.reserve(NUM_2D_SIDES);
//For pins, we need to look at all the sides of the current grid tile
// For pins, we need to look at all the sides of the current grid tile
for (e_side side : TOTAL_2D_SIDES) {
RRNodeId rr_node_index = find_node(layer, x, y, rr_type, ptc, side);
if (rr_node_index) {
Expand All @@ -176,7 +176,7 @@ std::vector<RRNodeId> RRSpatialLookup::find_nodes_at_all_sides(int layer,
}
indices.shrink_to_fit();
} else {
//Sides do not affect non-pins so there should only be one per ptc
// Sides do not affect non-pins so there should only be one per ptc
RRNodeId rr_node_index = find_node(layer, x, y, rr_type, ptc);
if (rr_node_index) {
indices.push_back(rr_node_index);
Expand All @@ -196,7 +196,7 @@ std::vector<RRNodeId> RRSpatialLookup::find_grid_nodes_at_all_sides(int layer,
}

std::vector<RRNodeId> nodes;
/* Reserve space to avoid memory fragmentation */
// Reserve space to avoid memory fragmentation
size_t num_nodes = 0;
for (e_side node_side : TOTAL_2D_SIDES) {
num_nodes += find_nodes(layer,x, y, rr_type, node_side).size();
Expand Down
Loading
Loading