diff --git a/doc/src/api/vpr/rr_graph.rst b/doc/src/api/vpr/rr_graph.rst index 44f88548599..b9d653bedbb 100644 --- a/doc/src/api/vpr/rr_graph.rst +++ b/doc/src/api/vpr/rr_graph.rst @@ -7,7 +7,7 @@ RRGraphView .. doxygenfile:: rr_graph_view.h :project: librrgraph - :sections: detaileddescription + :sections: briefdescription detaileddescription func prototype user-defined public-func .. doxygenclass:: RRGraphView :project: librrgraph @@ -18,7 +18,7 @@ RRGraphBuilder .. doxygenfile:: rr_graph_builder.h :project: librrgraph - :sections: detaileddescription + :sections: briefdescription detaileddescription func prototype user-defined public-func .. doxygenclass:: RRGraphBuilder :project: librrgraph @@ -29,7 +29,7 @@ RRSpatialLookup .. doxygenfile:: rr_spatial_lookup.h :project: librrgraph - :sections: detaileddescription + :sections: briefdescription detaileddescription func prototype user-defined public-func .. doxygenclass:: RRSpatialLookup :project: librrgraph diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 2ad5cfba50b..cc367395bc6 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -38,7 +38,7 @@ class RRGraphBuilder { t_rr_graph_storage& rr_nodes(); /** @brief Return a writable object for update the fast look-up of rr_node */ RRSpatialLookup& node_lookup(); - /** .. warning:: The Metadata should stay as an independent data structure than rest of the internal data, + /** @warning The Metadata should stay as an independent data structure from the rest of the internal data, * e.g., node_lookup! */ /** @brief Return a writable object for the meta data on the nodes */ MetadataStorage& rr_node_metadata(); @@ -84,8 +84,12 @@ class RRGraphBuilder { return segment_id; } - /** TODO @brief Return a writable list of all the rr_segments - * .. warning:: It is not recommended to use this API unless you have to. The API may be deprecated later, and future APIs will designed to return a specific data from the rr_segments. + /** + * \internal + * TODO + * \endinternal + * @brief Return a writable list of all the rr_segments + * @warning It is not recommended to use this API unless you have to. The API may be deprecated later, and future APIs will designed to return a specific data from the rr_segments. */ inline vtr::vector& rr_segments() { return rr_segments_; @@ -103,8 +107,12 @@ class RRGraphBuilder { return switch_id; } - /** TODO @brief Return a writable list of all the rr_switches - * .. warning:: It is not recommended to use this API unless you have to. The API may be deprecated later, and future APIs will designed to return a specific data from the rr_switches. + /** + * \internal + * TODO + * \endinternal + * @brief Return a writable list of all the rr_switches + * @warning It is not recommended to use this API unless you have to. The API may be deprecated later, and future APIs will designed to return a specific data from the rr_switches. */ inline vtr::vector& rr_switch() { return rr_switch_inf_; @@ -388,7 +396,7 @@ class RRGraphBuilder { /* Detailed information about the switches, which are used in the RRGraph */ vtr::vector rr_switch_inf_; - /** .. warning:: The Metadata should stay as an independent data structure than rest of the internal data, + /** @warning The Metadata should stay as an independent data structure from the rest of the internal data, * e.g., node_lookup! */ /* Metadata is an extra data on rr-nodes and edges, respectively, that is not used by vpr * but simply passed through the flow so that it can be used by downstream tools. diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index b96c7a615b4..60f03a4b7e0 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -1,36 +1,64 @@ #ifndef RR_GRAPH_VIEW_H #define RR_GRAPH_VIEW_H -#include "rr_graph_builder.h" -#include "rr_node.h" -#include "physical_types.h" -/* An read-only routing resource graph - * which is an unified object including pointors to - * - node storage - * - TODO: edge_storage - * - TODO: node_ptc_storage - * - TODO: node_fan_in_storage - * - rr_node_indices +/** + * @file + * @brief The RRGraphView encapsulates a read-only routing resource graph as most + * clients (router, timing analyzer, etc.) only need to read a routing-resource graph (RRGraph). + * + * + * The RRGraph models the FPGA's programmable routing fabric as a graph consisting of nodes and edges. + * Each node and edge is supplemented with additional metadata, such as the physical location within + * the chip and electrical properties, to optimize algorithm efficiency, aid in visualizing the chip layout, + * and estimate signal delays. + * + * @par RRGraph nodes + * Each node represents a routing resource, which can be: + * 1. A routing track (CHANX or CHANY). + * 2. An input/output of a logic block (IPIN or OPIN). + * 3. A virtual source or sink node (SOURCE or SINK). + * + * @par RRGraph edges + * Each edge represents a switch between resources, which can be: + * 1. A multiplexer. + * 2. A tri-state buffer. + * 3. A pass gate. + * 4. A non-configurable buffer. + * 5. A short (metal connection). + * + * + * @note Despite the RRGraph containing millions of edges, there are only a few switch types. Therefore, all switch details, including R and C, are stored using a flyweight pattern (rr_switch_inf) rather than being directly embedded in the edge-related data of the RRGraph. Each edge stores the ID of its associated switch for easy lookup. + * + * + * \internal + * A unified object that includes pointers to: + * - Node storage + * - TODO: Edge storage + * - TODO: Node PTC storage + * - TODO: Node fan-in storage + * - RR node indices + * \endinternal + * - * Note that the RRGraphView does not own the storage - * It serves a virtual read-only protocol for - * - placer - * - router - * - timing analyzer + * @note The RRGraphView does not own the storage. It provides a virtual + * read-only protocol for: + * - Placer + * - Router + * - Timing analyzer * - GUI * - * Note that each client of rr_graph may get a frame view of the object - * The RRGraphView is the complete frame view of the routing resource graph - * - This helps to reduce the memory footprint for each client - * - This avoids massive changes for each client on using the APIs - * as each frame view provides adhoc APIs for each client - * - * TODO: more compact frame views will be created, e.g., - * - a mini frame view: contains only node and edges, representing the connectivity of the graph - * - a geometry frame view: an extended mini frame view with node-level attributes, - * in particular geometry information (type, x, y etc). - * + * \internal + * TODO: More compact frame views will be created, such as: + * - A mini frame view: Contains only nodes and edges, representing the + * connectivity of the graph. + * - A geometry frame view: An extended mini frame view with node-level + * attributes, particularly geometry information (type, x, y, etc.). + * \endinternal */ +#include "rr_graph_builder.h" +#include "rr_node.h" +#include "physical_types.h" + class RRGraphView { /* -- Constructors -- */ public: @@ -58,148 +86,166 @@ class RRGraphView { * kind of accessors */ public: - /* Aggregates: create range-based loops for nodes - * To iterate over the nodes in a RRGraph, - * using a range-based loop is suggested. - * ----------------------------------------------------------------- - * Example: iterate over all the nodes - * // Strongly suggest to use a read-only rr_graph object - * const RRGraph& rr_graph; - * for (const RRNodeId& node : rr_graph.nodes()) { - * // Do something with each node - * } + /** + * @brief Aggregates for creating range-based loops for nodes. + * + * To iterate over the nodes in an RRGraph, using a range-based loop is recommended. + * + * @code + * + * // Strongly suggest using a read-only rr_graph object const RRGraph& rr_graph; + * for (const RRNodeId& node : rr_graph.nodes()) { + * // Do something with each node + * } + * @endcode */ + inline vtr::StrongIdRange nodes() const { return vtr::StrongIdRange(RRNodeId(0), RRNodeId(num_nodes())); } - /** @brief Return number of nodes. This function is inlined for runtime optimization. */ + /** @brief Return number of routing resource nodes. + */ inline size_t num_nodes() const { return node_storage_.size(); } - /** @brief Is the RR graph currently empty? */ + /** @brief check whether the RR graph is currently empty + */ inline bool empty() const { return node_storage_.empty(); } - /** @brief Returns a range of RREdgeId's belonging to RRNodeId id. - * If this range is empty, then RRNodeId id has no edges.*/ + /** @brief Return a range of RREdgeIds that belong to a specified node. + * @note If this range is empty, then the specified node has no edges.*/ inline vtr::StrongIdRange edge_range(RRNodeId id) const { return vtr::StrongIdRange(node_storage_.first_edge(id), node_storage_.last_edge(id)); } - /** @brief Get the type of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the type of a specified node. + */ inline t_rr_type node_type(RRNodeId node) const { return node_storage_.node_type(node); } /** - * @brief Retrieve the name assigned to a given node ID. - * - * If no name is assigned, an empty optional is returned. - * - * @param id The id of the node. - * @return An optional pointer to the string representing the name if found, - * otherwise an empty optional. + * @brief Return the name of a specified node. + * @note If no name is assigned, an empty optional is returned. */ std::optional node_name(RRNodeId node) const { return node_storage_.node_name(node); } - /** @brief Get the type string of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return a string indicating the type of the specified node. + */ inline const char* node_type_string(RRNodeId node) const { return node_storage_.node_type_string(node); } - /** @brief Get the capacity of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the capacity of a specified node. + */ inline short node_capacity(RRNodeId node) const { return node_storage_.node_capacity(node); } - /** @brief Get the direction of a routing resource node. This function is inlined for runtime optimization. - * Direction::INC: wire driver is positioned at the low-coordinate end of the wire. - * Direction::DEC: wire_driver is positioned at the high-coordinate end of the wire. - * Direction::BIDIR: wire has multiple drivers, so signals can travel either way along the wire - * Direction::NONE: node does not have a direction, such as IPIN/OPIN + /** + * @brief Return the direction of a specified node. + * + * @note Direction Categories: + * - `Direction::INC`: Wire driver is positioned at the low-coordinate end of the wire. + * - `Direction::DEC`: Wire driver is positioned at the high-coordinate end of the wire. + * - `Direction::BIDIR`: Wire has multiple drivers, allowing signals to travel either way along the wire. + * - `Direction::NONE`: Node does not have a direction, such as IPIN/OPIN. */ inline Direction node_direction(RRNodeId node) const { return node_storage_.node_direction(node); } - /** @brief Get the direction string of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return a string representing the direction of the specified node. + */ inline const std::string& node_direction_string(RRNodeId node) const { return node_storage_.node_direction_string(node); } - /** @brief Get the capacitance of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the capacitance of a specified node. + */ inline float node_C(RRNodeId node) const { VTR_ASSERT(node_rc_index(node) < (short)rr_rc_data_.size()); return rr_rc_data_[node_rc_index(node)].C; } - /** @brief Get the resistance of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the resistance of a specified node. + */ inline float node_R(RRNodeId node) const { VTR_ASSERT(node_rc_index(node) < (short)rr_rc_data_.size()); return rr_rc_data_[node_rc_index(node)].R; } - /** @brief Get the rc_index of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the rc_index of a specified node. + */ inline int16_t node_rc_index(RRNodeId node) const { return node_storage_.node_rc_index(node); } - /** @brief Get the fan in of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the fan in count of a specified node. + */ inline t_edge_size node_fan_in(RRNodeId node) const { return node_storage_.fan_in(node); } - /** @brief Get the minimum x-coordinate of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the minimum x-coordinate of a specified node. + */ inline short node_xlow(RRNodeId node) const { return node_storage_.node_xlow(node); } - /** @brief Get the maximum x-coordinate of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the maximum x-coordinate of a specified node. + */ inline short node_xhigh(RRNodeId node) const { return node_storage_.node_xhigh(node); } - /** @brief Get the minimum y-coordinate of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the minimum y-coordinate of a specified node. + */ inline short node_ylow(RRNodeId node) const { return node_storage_.node_ylow(node); } - /** @brief Get the maximum y-coordinate of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the maximum y-coordinate of a specified node. + */ inline short node_yhigh(RRNodeId node) const { return node_storage_.node_yhigh(node); } - /** @brief Get the layer num of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the layer num of a specified node. + */ inline short node_layer(RRNodeId node) const { return node_storage_.node_layer(node); } - - /** @brief Get the ptc number twist of a routing resource node. This function is inlined for runtime optimization. */ - inline short node_ptc_twist(RRNodeId node) const{ + + /** @brief Return the ptc number twist of a specified node. + */ + inline short node_ptc_twist(RRNodeId node) const { return node_storage_.node_ptc_twist(node); } - /** @brief Get the first out coming edge of resource node. This function is inlined for runtime optimization. */ + /** @brief Return the first outgoing edge of a specified node. + */ inline RREdgeId node_first_edge(RRNodeId node) const { return node_storage_.first_edge(node); } - /** @brief Get the last out coming edge of resource node. This function is inlined for runtime optimization. */ + /** @brief Return the last outgoing edge of a specified node. + */ inline RREdgeId node_last_edge(RRNodeId node) const { return node_storage_.last_edge(node); } - /** @brief Get the length (number of grid tile units spanned by the wire, including the endpoints) of a routing resource node. - * node_length() only applies to CHANX or CHANY and is always a positive number - * This function is inlined for runtime optimization. + /** @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 */ inline int node_length(RRNodeId node) const { VTR_ASSERT(node_type(node) == CHANX || node_type(node) == CHANY); - if(node_direction(node) == Direction::NONE){ + 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); @@ -207,7 +253,8 @@ class RRGraphView { return length; } - /** @brief Check if routing resource node is initialized. This function is inlined for runtime optimization. */ + /** @brief Check if a routing resource node is initialized. + */ inline bool node_is_initialized(RRNodeId node) const { return !((node_type(node) == NUM_RR_TYPES) && (node_xlow(node) == -1) && (node_ylow(node) == -1) @@ -215,9 +262,8 @@ class RRGraphView { } /** @brief Check if two routing resource nodes are adjacent (must be a CHANX and a CHANY). - * This function is used for error checking; it checks if two nodes are physically adjacent (could be connected) based on their geometry. - * It does not check the routing edges to see if they are, in fact, possible to connect in the current routing graph. - * This function is inlined for runtime optimization. */ + * @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) == CHANX && node_type(chany_node) == CHANY); if (node_ylow(chany_node) > node_ylow(chanx_node) + 1 || // verifies that chany_node is not more than one unit above chanx_node @@ -229,9 +275,15 @@ class RRGraphView { return true; } - /** @brief Check if node is within bounding box. - * To return true, the RRNode must be completely contained within the specified bounding box, with the edges of the bounding box being inclusive. - *This function is inlined for runtime optimization. */ + /** + * @brief Check if the node is within the bounding box. + * + * @param node the id of the node. + * @param bounding_box a 2D rectangle that defines the bounding area. + * @note To return true, the RRNode must be completely contained within the specified bounding box, + * with the edges of the bounding box being inclusive. + */ + inline bool node_is_inside_bounding_box(RRNodeId node, vtr::Rect bounding_box) const { return (node_xhigh(node) <= bounding_box.xmax() && node_xlow(node) >= bounding_box.xmin() @@ -239,26 +291,28 @@ class RRGraphView { && node_ylow(node) >= bounding_box.ymin()); } - /** @brief Check if x is within x-range spanned by the node, inclusive of its endpoints. This function is inlined for runtime optimization. */ + /** @brief Check if x is within x-range spanned by a specified node, inclusive of its endpoints. + */ inline bool x_in_node_range(int x, RRNodeId node) const { return !(x < node_xlow(node) || x > node_xhigh(node)); } - /** @brief Check if y is within y-range spanned by the node, inclusive of its endpoints. This function is inlined for runtime optimization. */ + /** @brief Check if y is within y-range spanned by a specified node, inclusive of its endpoints. + */ inline bool y_in_node_range(int y, RRNodeId node) const { return !(y < node_ylow(node) || y > node_yhigh(node)); } - /** @brief Get string of information about routing resource node. The string will contain the following information. + /** @brief Return a string containing information about the specified node. + * @note The returned string can contain the following information: * type, side, x_low, x_high, y_low, y_high, length, direction, segment_name, layer num - * This function is inlined for runtime optimization. */ inline const std::string node_coordinate_to_string(RRNodeId node) const { std::string start_x; //start x-coordinate std::string start_y; //start y-coordinate std::string end_x; //end x-coordinate std::string end_y; //end y-coordinate - std::string start_layer_str; //layer number + std::string start_layer_str; //layer number std::string end_layer_str; //layer number std::string arrow; //direction arrow std::string coordinate_string = node_type_string(node); //write the component's type as a routing resource node @@ -276,7 +330,7 @@ class RRGraphView { coordinate_string += ")"; //add the side of the routing resource node // For OPINs and IPINs the starting and ending coordinate are identical, so we can just arbitrarily assign the start to larger values // and the end to the lower coordinate - start_x = " (" + std::to_string(node_xhigh(node)) + ","; //start and end coordinates are the same for OPINs and IPINs + start_x = " (" + std::to_string(node_xhigh(node)) + ","; //start and end coordinates are the same for OPINs and IPINs start_y = std::to_string(node_yhigh(node)) + ","; start_layer_str = std::to_string(node_layer_num) + ")"; } else if (node_type(node) == SOURCE || node_type(node) == SINK) { @@ -293,7 +347,7 @@ class RRGraphView { arrow = "->"; //we will point the coordinates from start to finish, left to right - if (node_direction(node) == Direction::DEC) { //signal travels along decreasing direction + if (node_direction(node) == Direction::DEC) { //signal travels along decreasing direction start_x = " (" + std::to_string(node_xhigh(node)) + ","; //start coordinates have large value start_y = std::to_string(node_yhigh(node)) + ","; @@ -316,144 +370,170 @@ class RRGraphView { } } - coordinate_string += start_x + start_y + start_layer_str; //Write the starting coordinates - coordinate_string += arrow; //Indicate the direction - coordinate_string += end_x + end_y + end_layer_str; //Write the end coordinates + coordinate_string += start_x + start_y + start_layer_str; //Write the starting coordinates + coordinate_string += arrow; //Indicate the direction + coordinate_string += end_x + end_y + end_layer_str; //Write the end coordinates return coordinate_string; } - /** @brief Check whether a routing node is on a specific side. This function is inlined for runtime optimization. */ + /** @brief Check whether a routing resource node is on a specific side. + */ inline bool is_node_on_specific_side(RRNodeId node, e_side side) const { return node_storage_.is_node_on_specific_side(node, side); } - /** @brief Get the side string of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return a string representing the side of a routing resource node. + */ inline const char* node_side_string(RRNodeId node) const { return node_storage_.node_side_string(node); } - /** @brief Get the node id of the clock network virtual sink */ + /** @brief Return the node id of the clock network virtual sink + */ inline RRNodeId virtual_clock_network_root_idx(const char* clock_network_name) const { return node_storage_.virtual_clock_network_root_idx(clock_network_name); } /** - * @brief Checks if the specified RRNode ID is a virtual sink for a clock network. - * @param id The ID of an RRNode. - * @return True if the node with the given ID is a virtual sink for a clock network, false otherwise. + * @brief Checks if the specified node is a virtual sink for a clock network. */ inline bool is_virtual_clock_network_root(RRNodeId id) const { return node_storage_.is_virtual_clock_network_root(id); } - /** @brief Get the switch id that represents the iedge'th outgoing edge from a specific node - * TODO: We may need to revisit this API and think about higher level APIs, like ``switch_delay()`` - **/ + /** @brief Return the switch id that represents the iedge'th outgoing edge from a specific node. + * @param id the id of the node. + * @param iedge the outgoing edge index of the node. + * @return the id of the switch used for the specified edge. + * \internal + * @todo We may need to revisit this API and think about higher level APIs, like ``switch_delay()``. + * \endinternal + */ inline short edge_switch(RRNodeId id, t_edge_size iedge) const { return node_storage_.edge_switch(id, iedge); } - /** @brief Get the source node for the specified edge. */ + /** @brief Return the source node for the specified edge. + */ inline RRNodeId edge_src_node(const RREdgeId edge_id) const { return node_storage_.edge_src_node(edge_id); } - /** @brief Get the destination node for the iedge'th edge from specified RRNodeId. - * This method should generally not be used, and instead first_edge and - * last_edge should be used.*/ + /** @brief Return the destination node for the iedge'th edge from specified RRNodeId. + * @param id the id of the node + * @param iedge the iedge'th edge of the node + * @return destination node id of the specified edge + * @note This method should generally not be used, and instead first_edge and + * last_edge should be used.*/ inline RRNodeId edge_sink_node(RRNodeId id, t_edge_size iedge) const { return node_storage_.edge_sink_node(id, iedge); } - /** @brief Detect if the edge is a configurable edge (controlled by a programmable routing multipler or a tri-state switch). */ + /** @brief Check if the edge is a configurable edge + * @note A configurable edge represents a programmable switch between routing resources, which could be + * - a multiplexer + * - a tri-state buffer + * - a pass gate + */ inline bool edge_is_configurable(RRNodeId id, t_edge_size iedge) const { return node_storage_.edge_is_configurable(id, iedge, rr_switch_inf_); } - /** @brief Get the number of configurable edges. This function is inlined for runtime optimization. */ + /** @brief Return the number of configurable edges. + */ inline t_edge_size num_configurable_edges(RRNodeId node) const { return node_storage_.num_configurable_edges(node, rr_switch_inf_); } - /** @brief Get the number of non-configurable edges. This function is inlined for runtime optimization. */ + /** @brief Return the number of non-configurable edges. + */ inline t_edge_size num_non_configurable_edges(RRNodeId node) const { return node_storage_.num_non_configurable_edges(node, rr_switch_inf_); } - /** @brief A configurable edge represents a programmable switch between routing resources, which could be - * a multiplexer - * a tri-state buffer - * a pass gate - * This API gets ID range for configurable edges. This function is inlined for runtime optimization. */ + /** @brief Return ID range for configurable edges. + */ inline edge_idx_range configurable_edges(RRNodeId node) const { return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(node_storage_.num_edges(node) - num_non_configurable_edges(node))); } - /** @brief A non-configurable edge represents a hard-wired connection between routing resources, which could be - * a non-configurable buffer that can not be turned off - * a short metal connection that can not be turned off - * This API gets ID range for non-configurable edges. This function is inlined for runtime optimization. */ + /** @brief Return ID range for non-configurable edges. + * @note A non-configurable edge represents a hard-wired connection between routing resources, which could be + * - a non-configurable buffer that can not be turned off + * - a short metal connection that can not be turned off + */ inline edge_idx_range non_configurable_edges(RRNodeId node) const { return vtr::make_range(edge_idx_iterator(node_storage_.num_edges(node) - num_non_configurable_edges(node)), edge_idx_iterator(num_edges(node))); } - /** @brief Get outgoing edges for a node. - * This API is designed to enable range-based loop to walk through the outgoing edges of a node - * Example: - * RRGraphView rr_graph; // A dummy rr_graph for a short example - * RRNodeId node; // A dummy node for a short example - * for (RREdgeId edge : rr_graph.edges(node)) { + /** + * @brief Retrieve the outgoing edges for a specified node. This API is designed to facilitate range-based loops for traversing the outgoing edges of a node. + * @param id the id of the node + * @return the range of outgoing edges for the given node + * @example + * RRGraphView rr_graph; // A dummy rr_graph for a short example + * RRNodeId node; // A dummy node for a short example + * for (RREdgeId edge : rr_graph.edges(node)) { * // Do something with the edge - * } + * } */ inline edge_idx_range edges(const RRNodeId& id) const { return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(num_edges(id))); } - /** @brief Get the number of edges. This function is inlined for runtime optimization. */ + /** @brief Return the number of edges. + */ inline t_edge_size num_edges(RRNodeId node) const { return node_storage_.num_edges(node); } - /** @brief The ptc_num carries different meanings for different node types - * (true in VPR RRG that is currently supported, may not be true in customized RRG) - * CHANX or CHANY: the track id in routing channels - * OPIN or IPIN: the index of pins in the logic block data structure - * SOURCE and SINK: the class id of a pin (indicating logic equivalence of pins) in the logic block data structure - * @note - * This API is very powerful and developers should not use it unless it is necessary, - * e.g the node type is unknown. If the node type is known, the more specific routines, `node_pin_num()`, - * `node_track_num()`and `node_class_num()`, for different types of nodes should be used.*/ + /** + * @brief Retrieve the `ptc_num` of a routing resource node. + * @note ptc_num (Pin, Track, or Class Number) allows for distinguishing overlapping routing elements that occupy the same (x, y) coordinate, ensuring they can be uniquely identified and managed without confusion. For instance, several routing wires or pins might overlap physically, but their ptc_num differentiates them. + * @note The meaning of `ptc_num` varies depending on the node type (relevant to VPR RRG, may not apply to custom RRGs): + * - **CHANX/CHANY**: Represents the track ID in routing channels. + * - **OPIN/IPIN**: Refers to the pin index within the logic block data structure. + * - **SOURCE/SINK**: Denotes the class ID of a pin, indicating logic equivalence in the logic block data structure. + * + * @warning This API is highly versatile and should only be used when necessary (e.g., when the node type is unknown). + * If the node type is known, prefer using more specific APIs such as `node_pin_num()`, `node_track_num()`, + * or `node_class_num()` based on the node type. + */ inline int node_ptc_num(RRNodeId node) const { return node_storage_.node_ptc_num(node); } - /** @brief Get the pin num of a routing resource node. This is designed for logic blocks, - * which are IPIN and OPIN nodes. This function is inlined for runtime optimization. */ + /** @brief Return the pin num of a routing resource node. + * @note This function is intended for logic blocks and should only be used with IPIN or OPIN nodes. + */ inline int node_pin_num(RRNodeId node) const { return node_storage_.node_pin_num(node); } - /** @brief Get the track num of a routing resource node. This is designed for routing tracks, - * which are CHANX and CHANY nodes. This function is inlined for runtime optimization. */ + /** @brief Return the track num of a routing resource node. + * @note This function should only be used with CHANX or CHANY nodes. + */ inline int node_track_num(RRNodeId node) const { return node_storage_.node_track_num(node); } - /** @brief Get the class num of a routing resource node. This is designed for routing source and sinks, - * which are SOURCE and SINK nodes. This function is inlined for runtime optimization. */ + /** @brief Return the class num of a routing resource node. + * @note This function should only be used with SOURCE or SINK nodes. + */ inline int node_class_num(RRNodeId node) const { return node_storage_.node_class_num(node); } - /** @brief Get the cost index of a routing resource node. This function is inlined for runtime optimization. */ + /** @brief Return the cost index of a routing resource node. + */ RRIndexedDataId node_cost_index(RRNodeId node) const { return node_storage_.node_cost_index(node); } - /** @brief Return detailed routing segment information with a given id* @note The routing segments here may not be exactly same as those defined in architecture file. They have been + + /** @brief Return detailed routing segment information of a specified segment + * @note The routing segments here may not be exactly same as those defined in architecture file. They have been * adapted to fit the context of routing resource graphs. */ - inline const t_segment_inf& rr_segments(RRSegmentId seg_id) const { return rr_segments_[seg_id]; } @@ -466,8 +546,8 @@ class RRGraphView { return rr_segments_; } - /** @brief Return the switch information that is categorized in the rr_switch_inf with a given id - * rr_switch_inf is created to minimize memory footprint of RRGraph class + /** @brief Return the switch information that is categorized in the rr_switch_inf with a given id. + * @note rr_switch_inf is created to minimize memory footprint of RRGraph class. * While the RRG could contain millions (even much larger) of edges, there are only * a limited number of types of switches. * Hence, we use a flyweight pattern to store switch-related information that differs @@ -502,18 +582,20 @@ class RRGraphView { return node_storage_; } - /** .. warning:: The Metadata should stay as an independent data structure than rest of the internal data, + /** @brief Return the metadata of rr nodes + * @warning The Metadata should stay as an independent data structure than rest of the internal data, * e.g., node_lookup! */ MetadataStorage rr_node_metadata_data() const { return rr_node_metadata_; } - + /** @brief Return the metadata of rr edges + */ MetadataStorage> rr_edge_metadata_data() const { return rr_edge_metadata_; } public: /* Validators */ - /** brief Validate that edge data is partitioned correctly + /** @brief Validate that edge data is partitioned correctly * @note This function is used to validate the correctness of the routing resource graph in terms * of graph attributes. Strongly recommend to call it when you finish the building a routing resource * graph. If you need more advance checks, which are related to architecture features, you should @@ -525,43 +607,43 @@ class RRGraphView { /* -- Internal data storage -- */ /* Note: only read-only object or data structures are allowed!!! */ private: - /* node-level storage including edge storages */ + /// node-level storage including edge storages const t_rr_graph_storage& node_storage_; - /* Fast look-up for rr nodes */ + /// Fast look-up for rr nodes const RRSpatialLookup& node_lookup_; - /** .. warning:: The Metadata should stay as an independent data structure than rest of the internal data, - * e.g., node_lookup! */ - /* Metadata is an extra data on rr-nodes and edges, respectively, that is not used by vpr - * but simply passed through the flow so that it can be used by downstream tools. - * The main (perhaps only) current use of this metadata is the fasm tool of symbiflow, - * which needs extra metadata on which programming bits control which switch in order to produce a bitstream.*/ + /** * @brief Attributes for each rr_node. * - * key: rr_node index - * value: map of - */ + * - key: rr_node index + * - value: map of + * @warning The Metadata should stay as an independent data structure than rest of the internal data, + * e.g., node_lookup! + * @note Metadata is an extra data on rr-nodes and edges, respectively, that is not used by vpr + * but simply passed through the flow so that it can be used by downstream tools. + * The main (perhaps only) current use of this metadata is the fasm tool of symbiflow, + * which needs extra metadata on which programming bits control which switch in order to produce a bitstream.*/ const MetadataStorage& rr_node_metadata_; /** * @brief Attributes for each rr_edge * - * key: - * iswitch: Index of the switch type used to go from this rr_node to + * - key: + * - iswitch: Index of the switch type used to go from this rr_node to * the next one in the routing. OPEN if there is no next node * (i.e. this node is the last one (a SINK) in a branch of the * net's routing). - * value: map of + * - value: map of */ const MetadataStorage>& rr_edge_metadata_; - /* rr_indexed_data_ and rr_segments_ are needed to lookup the segment information in node_coordinate_to_string() */ + /// rr_indexed_data_ and rr_segments_ are needed to lookup the segment information in node_coordinate_to_string() const vtr::vector& rr_indexed_data_; - /* RC data for nodes. This is a flyweight data */ + /// RC data for nodes. This is a flyweight data const std::vector& rr_rc_data_; - /* Segment info for rr nodes */ + /// Segment info for rr nodes const vtr::vector& rr_segments_; - /* switch info for rr nodes */ + /// switch info for rr nodes const vtr::vector& rr_switch_inf_; };