| /************************************************************************ |
| * Member Functions of RRGraph |
| * include mutators, accessors and utility functions |
| ***********************************************************************/ |
| #include <cmath> |
| #include <algorithm> |
| #include <map> |
| #include <limits> |
| |
| #include "vtr_vector_map.h" |
| #include "vtr_log.h" |
| #include "vtr_util.h" |
| #include "vtr_assert.h" |
| #include "rr_graph_obj.h" |
| #include "rr_graph_obj_utils.h" |
| |
| //Accessors |
| RRGraph::node_range RRGraph::nodes() const { |
| return vtr::make_range(node_ids_.begin(), node_ids_.end()); |
| } |
| |
| RRGraph::edge_range RRGraph::edges() const { |
| return vtr::make_range(edge_ids_.begin(), edge_ids_.end()); |
| } |
| |
| RRGraph::switch_range RRGraph::switches() const { |
| return vtr::make_range(switch_ids_.begin(), switch_ids_.end()); |
| } |
| |
| RRGraph::segment_range RRGraph::segments() const { |
| return vtr::make_range(segment_ids_.begin(), segment_ids_.end()); |
| } |
| |
| //Node attributes |
| t_rr_type RRGraph::node_type(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return node_types_[node]; |
| } |
| |
| size_t RRGraph::node_index(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return size_t(node); |
| } |
| |
| short RRGraph::node_xlow(const RRNodeId& node) const { |
| return node_bounding_box(node).xmin(); |
| } |
| |
| short RRGraph::node_ylow(const RRNodeId& node) const { |
| return node_bounding_box(node).ymin(); |
| } |
| |
| short RRGraph::node_xhigh(const RRNodeId& node) const { |
| return node_bounding_box(node).xmax(); |
| } |
| |
| short RRGraph::node_yhigh(const RRNodeId& node) const { |
| return node_bounding_box(node).ymax(); |
| } |
| |
| short RRGraph::node_length(const RRNodeId& node) const { |
| return std::max(node_xhigh(node) - node_xlow(node), node_yhigh(node) - node_ylow(node)); |
| } |
| |
| vtr::Rect<short> RRGraph::node_bounding_box(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return node_bounding_boxes_[node]; |
| } |
| |
| /* Node starting and ending points */ |
| /************************************************************************ |
| * Get the coordinator of a starting point of a routing track |
| * For routing tracks in INC_DIRECTION |
| * (xlow, ylow) should be the starting point |
| * |
| * For routing tracks in DEC_DIRECTION |
| * (xhigh, yhigh) should be the starting point |
| * |
| * For routing tracks in BI_DIRECTION |
| * we always use (xhigh, yhigh) |
| ***********************************************************************/ |
| vtr::Point<short> RRGraph::node_start_coordinate(const RRNodeId& node) const { |
| /* Make sure we have CHANX or CHANY */ |
| VTR_ASSERT((CHANX == node_type(node)) || (CHANY == node_type(node))); |
| |
| vtr::Point<short> start_coordinate(node_xlow(node), node_ylow(node)); |
| |
| if (DEC_DIRECTION == node_direction(node)) { |
| start_coordinate.set(node_xhigh(node), node_yhigh(node)); |
| } |
| |
| return start_coordinate; |
| } |
| |
| /************************************************************************ |
| * Get the coordinator of a end point of a routing track |
| * For routing tracks in INC_DIRECTION |
| * (xhigh, yhigh) should be the ending point |
| * |
| * For routing tracks in DEC_DIRECTION |
| * (xlow, ylow) should be the ending point |
| * |
| * For routing tracks in BI_DIRECTION |
| * we always use (xhigh, yhigh) |
| ***********************************************************************/ |
| vtr::Point<short> RRGraph::node_end_coordinate(const RRNodeId& node) const { |
| /* Make sure we have CHANX or CHANY */ |
| VTR_ASSERT((CHANX == node_type(node)) || (CHANY == node_type(node))); |
| |
| vtr::Point<short> end_coordinate(node_xhigh(node), node_yhigh(node)); |
| |
| if (DEC_DIRECTION == node_direction(node)) { |
| end_coordinate.set(node_xlow(node), node_ylow(node)); |
| } |
| |
| return end_coordinate; |
| } |
| |
| short RRGraph::node_fan_in(const RRNodeId& node) const { |
| return node_in_edges(node).size(); |
| } |
| |
| short RRGraph::node_fan_out(const RRNodeId& node) const { |
| return node_out_edges(node).size(); |
| } |
| |
| short RRGraph::node_capacity(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return node_capacities_[node]; |
| } |
| |
| short RRGraph::node_ptc_num(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return node_ptc_nums_[node]; |
| } |
| |
| short RRGraph::node_pin_num(const RRNodeId& node) const { |
| VTR_ASSERT_MSG(node_type(node) == IPIN || node_type(node) == OPIN, |
| "Pin number valid only for IPIN/OPIN RR nodes"); |
| return node_ptc_num(node); |
| } |
| |
| short RRGraph::node_track_num(const RRNodeId& node) const { |
| VTR_ASSERT_MSG(node_type(node) == CHANX || node_type(node) == CHANY, |
| "Track number valid only for CHANX/CHANY RR nodes"); |
| return node_ptc_num(node); |
| } |
| |
| short RRGraph::node_class_num(const RRNodeId& node) const { |
| VTR_ASSERT_MSG(node_type(node) == SOURCE || node_type(node) == SINK, "Class number valid only for SOURCE/SINK RR nodes"); |
| return node_ptc_num(node); |
| } |
| |
| short RRGraph::node_cost_index(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return node_cost_indices_[node]; |
| } |
| |
| e_direction RRGraph::node_direction(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| VTR_ASSERT_MSG(node_type(node) == CHANX || node_type(node) == CHANY, "Direction valid only for CHANX/CHANY RR nodes"); |
| return node_directions_[node]; |
| } |
| |
| e_side RRGraph::node_side(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| VTR_ASSERT_MSG(node_type(node) == IPIN || node_type(node) == OPIN, "Side valid only for IPIN/OPIN RR nodes"); |
| return node_sides_[node]; |
| } |
| |
| /* Get the resistance of a node */ |
| float RRGraph::node_R(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return node_Rs_[node]; |
| } |
| |
| /* Get the capacitance of a node */ |
| float RRGraph::node_C(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return node_Cs_[node]; |
| } |
| |
| /* |
| * Get a segment id of a node in rr_graph |
| */ |
| RRSegmentId RRGraph::node_segment(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| |
| return node_segments_[node]; |
| } |
| |
| /* |
| * Get the number of configurable input edges of a node |
| * TODO: we would use the node_num_configurable_in_edges() |
| * when the rr_graph edges have been partitioned |
| * This can avoid unneccessary walkthrough |
| */ |
| short RRGraph::node_num_configurable_in_edges(const RRNodeId& node) const { |
| return node_configurable_in_edges(node).size(); |
| } |
| |
| /* |
| * Get the number of configurable output edges of a node |
| * TODO: we would use the node_num_configurable_out_edges() |
| * when the rr_graph edges have been partitioned |
| * This can avoid unneccessary walkthrough |
| */ |
| short RRGraph::node_num_configurable_out_edges(const RRNodeId& node) const { |
| return node_configurable_out_edges(node).size(); |
| } |
| |
| /* |
| * Get the number of non-configurable input edges of a node |
| * TODO: we would use the node_num_configurable_in_edges() |
| * when the rr_graph edges have been partitioned |
| * This can avoid unneccessary walkthrough |
| */ |
| short RRGraph::node_num_non_configurable_in_edges(const RRNodeId& node) const { |
| return node_non_configurable_in_edges(node).size(); |
| } |
| |
| /* |
| * Get the number of non-configurable output edges of a node |
| * TODO: we would use the node_num_configurable_out_edges() |
| * when the rr_graph edges have been partitioned |
| * This can avoid unneccessary walkthrough |
| */ |
| short RRGraph::node_num_non_configurable_out_edges(const RRNodeId& node) const { |
| return node_non_configurable_out_edges(node).size(); |
| } |
| |
| /* Get the list of configurable edges from the input edges of a given node |
| * And return the range(iterators) of the list |
| */ |
| RRGraph::edge_range RRGraph::node_configurable_in_edges(const RRNodeId& node) const { |
| /* Make sure we will access a valid node */ |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| |
| /* By default the configurable edges will be stored at the first part of the edge list (0 to XX) */ |
| auto begin = node_in_edges(node).begin(); |
| |
| /* By default the non-configurable edges will be stored at second part of the edge list (XX to end) */ |
| auto end = node_in_edges(node).end() - node_num_non_configurable_in_edges_[node]; |
| |
| return vtr::make_range(begin, end); |
| } |
| |
| /* Get the list of configurable edges from the input edges of a given node |
| * And return the range(iterators) of the list |
| */ |
| RRGraph::edge_range RRGraph::node_non_configurable_in_edges(const RRNodeId& node) const { |
| /* Make sure we will access a valid node */ |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| |
| /* By default the configurable edges will be stored at the first part of the edge list (0 to XX) */ |
| auto begin = node_in_edges(node).end() - node_num_non_configurable_in_edges_[node]; |
| |
| /* By default the non-configurable edges will be stored at second part of the edge list (XX to end) */ |
| auto end = node_in_edges(node).end(); |
| |
| return vtr::make_range(begin, end); |
| } |
| |
| /* Get the list of configurable edges from the input edges of a given node |
| * And return the range(iterators) of the list |
| */ |
| RRGraph::edge_range RRGraph::node_configurable_out_edges(const RRNodeId& node) const { |
| /* Make sure we will access a valid node */ |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| |
| /* By default the configurable edges will be stored at the first part of the edge list (0 to XX) */ |
| auto begin = node_out_edges(node).begin(); |
| |
| /* By default the non-configurable edges will be stored at second part of the edge list (XX to end) */ |
| auto end = node_out_edges(node).end() - node_num_non_configurable_out_edges_[node]; |
| |
| return vtr::make_range(begin, end); |
| } |
| |
| /* Get the list of configurable edges from the input edges of a given node |
| * And return the range(iterators) of the list |
| */ |
| RRGraph::edge_range RRGraph::node_non_configurable_out_edges(const RRNodeId& node) const { |
| /* Make sure we will access a valid node */ |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| |
| /* By default the configurable edges will be stored at the first part of the edge list (0 to XX) */ |
| auto begin = node_out_edges(node).end() - node_num_non_configurable_out_edges_[node]; |
| |
| /* By default the non-configurable edges will be stored at second part of the edge list (XX to end) */ |
| auto end = node_out_edges(node).end(); |
| |
| return vtr::make_range(begin, end); |
| } |
| |
| RRGraph::edge_range RRGraph::node_out_edges(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return vtr::make_range(node_out_edges_[node].begin(), node_out_edges_[node].end()); |
| } |
| |
| RRGraph::edge_range RRGraph::node_in_edges(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| return vtr::make_range(node_in_edges_[node].begin(), node_in_edges_[node].end()); |
| } |
| |
| //Edge attributes |
| size_t RRGraph::edge_index(const RREdgeId& edge) const { |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| return size_t(edge); |
| } |
| |
| RRNodeId RRGraph::edge_src_node(const RREdgeId& edge) const { |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| return edge_src_nodes_[edge]; |
| } |
| RRNodeId RRGraph::edge_sink_node(const RREdgeId& edge) const { |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| return edge_sink_nodes_[edge]; |
| } |
| |
| RRSwitchId RRGraph::edge_switch(const RREdgeId& edge) const { |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| return edge_switches_[edge]; |
| } |
| |
| /* Check if the edge is a configurable edge (programmble) */ |
| bool RRGraph::edge_is_configurable(const RREdgeId& edge) const { |
| /* Make sure we have a valid edge id */ |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| |
| auto iswitch = edge_switch(edge); |
| |
| return switches_[iswitch].configurable(); |
| } |
| |
| /* Check if the edge is a non-configurable edge (hardwired) */ |
| bool RRGraph::edge_is_non_configurable(const RREdgeId& edge) const { |
| /* Make sure we have a valid edge id */ |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| return !edge_is_configurable(edge); |
| } |
| |
| size_t RRGraph::switch_index(const RRSwitchId& switch_id) const { |
| VTR_ASSERT_SAFE(valid_switch_id(switch_id)); |
| return size_t(switch_id); |
| } |
| |
| /* |
| * Get a switch from the rr_switch list with a given id |
| */ |
| const t_rr_switch_inf& RRGraph::get_switch(const RRSwitchId& switch_id) const { |
| VTR_ASSERT_SAFE(valid_switch_id(switch_id)); |
| return switches_[switch_id]; |
| } |
| |
| size_t RRGraph::segment_index(const RRSegmentId& segment_id) const { |
| VTR_ASSERT_SAFE(valid_segment_id(segment_id)); |
| return size_t(segment_id); |
| } |
| |
| /* |
| * Get a segment from the segment list with a given id |
| */ |
| const t_segment_inf& RRGraph::get_segment(const RRSegmentId& segment_id) const { |
| VTR_ASSERT_SAFE(valid_segment_id(segment_id)); |
| return segments_[segment_id]; |
| } |
| |
| /************************************************************************ |
| * Find all the edges interconnecting two nodes |
| * Return a vector of the edge ids |
| ***********************************************************************/ |
| std::vector<RREdgeId> RRGraph::find_edges(const RRNodeId& src_node, const RRNodeId& sink_node) const { |
| std::vector<RREdgeId> edges; |
| |
| /* Iterate over the outgoing edges of the source node */ |
| for (auto edge : node_out_edges(src_node)) { |
| if (edge_sink_node(edge) == sink_node) { |
| /* Update edge list to return */ |
| edges.push_back(edge); |
| } |
| } |
| |
| return edges; |
| } |
| |
| RRNodeId RRGraph::find_node(const short& x, const short& y, const t_rr_type& type, const int& ptc, const e_side& side) const { |
| initialize_fast_node_lookup(); |
| |
| size_t itype = type; |
| size_t iside = side; |
| |
| /* Check if x, y, type and ptc, side is valid */ |
| if ((x < 0) /* See if x is smaller than the index of first element */ |
| || (size_t(x) > node_lookup_.size() - 1)) { /* See if x is large than the index of last element */ |
| /* Return a zero range! */ |
| return RRNodeId::INVALID(); |
| } |
| |
| /* Check if x, y, type and ptc, side is valid */ |
| if ((y < 0) /* See if y is smaller than the index of first element */ |
| || (size_t(y) > node_lookup_[x].size() - 1)) { /* See if y is large than the index of last element */ |
| /* Return a zero range! */ |
| return RRNodeId::INVALID(); |
| } |
| |
| /* Check if x, y, type and ptc, side is valid */ |
| /* itype is always larger than -1, we can skip checking */ |
| if (itype > node_lookup_[x][y].size() - 1) { /* See if type is large than the index of last element */ |
| /* Return a zero range! */ |
| return RRNodeId::INVALID(); |
| } |
| |
| /* Check if x, y, type and ptc, side is valid */ |
| if ((ptc < 0) /* See if ptc is smaller than the index of first element */ |
| || (size_t(ptc) > node_lookup_[x][y][type].size() - 1)) { /* See if ptc is large than the index of last element */ |
| /* Return a zero range! */ |
| return RRNodeId::INVALID(); |
| } |
| |
| /* Check if x, y, type and ptc, side is valid */ |
| /* iside is always larger than -1, we can skip checking */ |
| if (iside > node_lookup_[x][y][type][ptc].size() - 1) { /* See if side is large than the index of last element */ |
| /* Return a zero range! */ |
| return RRNodeId::INVALID(); |
| } |
| |
| return node_lookup_[x][y][itype][ptc][iside]; |
| } |
| |
| /* Find the channel width (number of tracks) of a channel [x][y] */ |
| short RRGraph::chan_num_tracks(const short& x, const short& y, const t_rr_type& type) const { |
| /* Must be CHANX or CHANY */ |
| VTR_ASSERT_MSG(CHANX == type || CHANY == type, |
| "Required node_type to be CHANX or CHANY!"); |
| initialize_fast_node_lookup(); |
| |
| /* Check if x, y, type and ptc is valid */ |
| if ((x < 0) /* See if x is smaller than the index of first element */ |
| || (size_t(x) > node_lookup_.size() - 1)) { /* See if x is large than the index of last element */ |
| /* Return a zero range! */ |
| return 0; |
| } |
| |
| /* Check if x, y, type and ptc is valid */ |
| if ((y < 0) /* See if y is smaller than the index of first element */ |
| || (size_t(y) > node_lookup_[x].size() - 1)) { /* See if y is large than the index of last element */ |
| /* Return a zero range! */ |
| return 0; |
| } |
| |
| /* Check if x, y, type and ptc is valid */ |
| if ((size_t(type) > node_lookup_[x][y].size() - 1)) { /* See if type is large than the index of last element */ |
| /* Return a zero range! */ |
| return 0; |
| } |
| |
| const auto& matching_nodes = node_lookup_[x][y][type]; |
| |
| return vtr::make_range(matching_nodes.begin(), matching_nodes.end()).size(); |
| } |
| |
| /* This function aims to print basic information about a node */ |
| void RRGraph::print_node(const RRNodeId& node) const { |
| VTR_LOG("Node id: %d\n", node_index(node)); |
| VTR_LOG("Node type: %s\n", rr_node_typename[node_type(node)]); |
| VTR_LOG("Node xlow: %d\n", node_xlow(node)); |
| VTR_LOG("Node ylow: %d\n", node_ylow(node)); |
| VTR_LOG("Node xhigh: %d\n", node_xhigh(node)); |
| VTR_LOG("Node yhigh: %d\n", node_yhigh(node)); |
| VTR_LOG("Node ptc: %d\n", node_ptc_num(node)); |
| VTR_LOG("Node num in_edges: %d\n", node_in_edges(node).size()); |
| VTR_LOG("Node num out_edges: %d\n", node_out_edges(node).size()); |
| } |
| |
| /* Check if the segment id of a node is in range */ |
| bool RRGraph::validate_node_segment(const RRNodeId& node) const { |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| /* Only CHANX and CHANY requires a valid segment id */ |
| if ((CHANX == node_type(node)) |
| || (CHANY == node_type(node))) { |
| return valid_segment_id(node_segments_[node]); |
| } else { |
| return true; |
| } |
| } |
| |
| /* Check if the segment id of every node is in range */ |
| bool RRGraph::validate_node_segments() const { |
| bool all_valid = true; |
| for (auto node : nodes()) { |
| if (true == validate_node_segment(node)) { |
| continue; |
| } |
| /* Reach here it means we find an invalid segment id */ |
| all_valid = false; |
| /* Print a warning! */ |
| VTR_LOG_WARN("Node %d has an invalid segment id (%d)!\n", |
| size_t(node), size_t(node_segment(node))); |
| } |
| return all_valid; |
| } |
| |
| /* Check if the switch id of a edge is in range */ |
| bool RRGraph::validate_edge_switch(const RREdgeId& edge) const { |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| return valid_switch_id(edge_switches_[edge]); |
| } |
| |
| /* Check if the switch id of every edge is in range */ |
| bool RRGraph::validate_edge_switches() const { |
| bool all_valid = true; |
| for (auto edge : edges()) { |
| if (true == validate_edge_switch(edge)) { |
| continue; |
| } |
| /* Reach here it means we find an invalid segment id */ |
| all_valid = false; |
| /* Print a warning! */ |
| VTR_LOG_WARN("Edge %d has an invalid switch id (%d)!\n", |
| size_t(edge), size_t(edge_switch(edge))); |
| } |
| return all_valid; |
| } |
| |
| /* Check if a node is in the list of source_nodes of a edge */ |
| bool RRGraph::validate_node_is_edge_src(const RRNodeId& node, const RREdgeId& edge) const { |
| /* Assure a valid node id */ |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| /* assure a valid edge id */ |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| /* find if the node is the src */ |
| if (node == edge_src_node(edge)) { |
| return true; /* confirmed source node*/ |
| } else { |
| return false; /* not a source */ |
| } |
| } |
| |
| /* Check if a node is in the list of sink_nodes of a edge */ |
| bool RRGraph::validate_node_is_edge_sink(const RRNodeId& node, const RREdgeId& edge) const { |
| /* Assure a valid node id */ |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| /* assure a valid edge id */ |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| /* find if the node is the sink */ |
| if (node == edge_sink_node(edge)) { |
| return true; /* confirmed source node*/ |
| } else { |
| return false; /* not a source */ |
| } |
| } |
| |
| /* This function will check if a node has valid input edges |
| * 1. Check the edge ids are valid |
| * 2. Check the node is in the list of edge_sink_node |
| */ |
| bool RRGraph::validate_node_in_edges(const RRNodeId& node) const { |
| bool all_valid = true; |
| /* Assure a valid node id */ |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| /* Check each edge */ |
| for (auto edge : node_in_edges(node)) { |
| /* assure a valid edge id */ |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| /* check the node is in the list of edge_sink_node */ |
| if (true == validate_node_is_edge_sink(node, edge)) { |
| continue; |
| } |
| /* Reach here, it means there is something wrong! |
| * Print a warning |
| */ |
| VTR_LOG_WARN("Edge %d is in the input edge list of node %d while the node is not in edge's sink node list!\n", |
| size_t(edge), size_t(node)); |
| all_valid = false; |
| } |
| |
| return all_valid; |
| } |
| |
| /* This function will check if a node has valid output edges |
| * 1. Check the edge ids are valid |
| * 2. Check the node is in the list of edge_source_node |
| */ |
| bool RRGraph::validate_node_out_edges(const RRNodeId& node) const { |
| bool all_valid = true; |
| /* Assure a valid node id */ |
| VTR_ASSERT_SAFE(valid_node_id(node)); |
| /* Check each edge */ |
| for (auto edge : node_out_edges(node)) { |
| /* assure a valid edge id */ |
| VTR_ASSERT_SAFE(valid_edge_id(edge)); |
| /* check the node is in the list of edge_sink_node */ |
| if (true == validate_node_is_edge_src(node, edge)) { |
| continue; |
| } |
| /* Reach here, it means there is something wrong! |
| * Print a warning |
| */ |
| VTR_LOG_WARN("Edge %d is in the output edge list of node %d while the node is not in edge's source node list!\n", |
| size_t(edge), size_t(node)); |
| all_valid = false; |
| } |
| |
| return all_valid; |
| } |
| |
| /* check all the edges of a node */ |
| bool RRGraph::validate_node_edges(const RRNodeId& node) const { |
| bool all_valid = true; |
| |
| if (false == validate_node_in_edges(node)) { |
| all_valid = false; |
| } |
| if (false == validate_node_out_edges(node)) { |
| all_valid = false; |
| } |
| |
| return all_valid; |
| } |
| |
| /* check if all the nodes' input edges are valid */ |
| bool RRGraph::validate_nodes_in_edges() const { |
| bool all_valid = true; |
| for (auto node : nodes()) { |
| if (true == validate_node_in_edges(node)) { |
| continue; |
| } |
| /* Reach here, it means there is something wrong! |
| * Print a warning |
| */ |
| all_valid = false; |
| } |
| return all_valid; |
| } |
| |
| /* check if all the nodes' output edges are valid */ |
| bool RRGraph::validate_nodes_out_edges() const { |
| bool all_valid = true; |
| for (auto node : nodes()) { |
| if (true == validate_node_out_edges(node)) { |
| continue; |
| } |
| /* Reach here, it means there is something wrong! |
| * Print a warning |
| */ |
| all_valid = false; |
| } |
| return all_valid; |
| } |
| |
| /* check all the edges of every node */ |
| bool RRGraph::validate_nodes_edges() const { |
| bool all_valid = true; |
| |
| if (false == validate_nodes_in_edges()) { |
| all_valid = false; |
| } |
| if (false == validate_nodes_out_edges()) { |
| all_valid = false; |
| } |
| |
| return all_valid; |
| } |
| |
| /* Check if source node of a edge is valid */ |
| bool RRGraph::validate_edge_src_node(const RREdgeId& edge) const { |
| return valid_node_id(edge_src_node(edge)); |
| } |
| |
| /* Check if sink node of a edge is valid */ |
| bool RRGraph::validate_edge_sink_node(const RREdgeId& edge) const { |
| return valid_node_id(edge_sink_node(edge)); |
| } |
| |
| /* Check if source nodes of a edge are all valid */ |
| bool RRGraph::validate_edge_src_nodes() const { |
| bool all_valid = true; |
| for (auto edge : edges()) { |
| if (true == validate_edge_src_node(edge)) { |
| continue; |
| } |
| /* Reach here, it means there is something wrong! |
| * Print a warning |
| */ |
| VTR_LOG_WARN("Edge %d has a invalid source node %d!\n", |
| size_t(edge), size_t(edge_src_node(edge))); |
| all_valid = false; |
| } |
| return all_valid; |
| } |
| |
| /* Check if source nodes of a edge are all valid */ |
| bool RRGraph::validate_edge_sink_nodes() const { |
| bool all_valid = true; |
| for (auto edge : edges()) { |
| if (true == validate_edge_sink_node(edge)) { |
| continue; |
| } |
| /* Reach here, it means there is something wrong! |
| * Print a warning |
| */ |
| VTR_LOG_WARN("Edge %d has a invalid sink node %d!\n", |
| size_t(edge), size_t(edge_sink_node(edge))); |
| all_valid = false; |
| } |
| return all_valid; |
| } |
| |
| /* This function should be used when nodes, edges, switches and segments have been used after |
| * We will build the fast_lookup, partition edges and check |
| * This function run fundamental and optional checks on internal data |
| * Errors are thrown if fundamental checking fails |
| * Warnings are thrown if optional checking fails |
| */ |
| bool RRGraph::validate() const { |
| bool check_flag = true; |
| size_t num_err = 0; |
| |
| initialize_fast_node_lookup(); |
| |
| /* Validate the sizes of nodes and node-related vectors |
| * Validate the sizes of edges and edge-related vectors |
| */ |
| if (false == validate_sizes()) { |
| VTR_LOG_WARN("Fail in validating node- and edge-related vector sizes!\n"); |
| check_flag = false; |
| num_err++; |
| } |
| |
| /* Fundamental check */ |
| if (false == validate_nodes_edges()) { |
| VTR_LOG_WARN("Fail in validating edges connected to each node!\n"); |
| check_flag = false; |
| num_err++; |
| } |
| |
| if (false == validate_node_segments()) { |
| VTR_LOG_WARN("Fail in validating segment IDs of nodes !\n"); |
| check_flag = false; |
| num_err++; |
| } |
| |
| if (false == validate_edge_switches()) { |
| VTR_LOG_WARN("Fail in validating switch IDs of edges !\n"); |
| check_flag = false; |
| num_err++; |
| } |
| |
| /* Error out if there is any fatal errors found */ |
| VTR_LOG_ERROR("Routing Resource graph is not valid due to %d fatal errors !\n", |
| num_err); |
| |
| return check_flag; |
| } |
| |
| bool RRGraph::is_dirty() const { |
| return dirty_; |
| } |
| |
| void RRGraph::set_dirty() { |
| dirty_ = true; |
| } |
| |
| void RRGraph::clear_dirty() { |
| dirty_ = false; |
| } |
| |
| /* Reserve a list of nodes */ |
| void RRGraph::reserve_nodes(const int& num_nodes) { |
| /* Reserve the full set of vectors related to nodes */ |
| /* Basic information */ |
| this->node_ids_.reserve(num_nodes); |
| this->node_types_.reserve(num_nodes); |
| this->node_bounding_boxes_.reserve(num_nodes); |
| this->node_capacities_.reserve(num_nodes); |
| this->node_ptc_nums_.reserve(num_nodes); |
| this->node_directions_.reserve(num_nodes); |
| this->node_sides_.reserve(num_nodes); |
| this->node_Rs_.reserve(num_nodes); |
| this->node_Cs_.reserve(num_nodes); |
| this->node_segments_.reserve(num_nodes); |
| this->node_num_non_configurable_in_edges_.reserve(num_nodes); |
| this->node_num_non_configurable_out_edges_.reserve(num_nodes); |
| |
| /* Edge-relate vectors */ |
| this->node_in_edges_.reserve(num_nodes); |
| this->node_out_edges_.reserve(num_nodes); |
| } |
| |
| /* Reserve a list of edges */ |
| void RRGraph::reserve_edges(const int& num_edges) { |
| /* Reserve the full set of vectors related to edges */ |
| this->edge_ids_.reserve(num_edges); |
| this->edge_src_nodes_.reserve(num_edges); |
| this->edge_sink_nodes_.reserve(num_edges); |
| this->edge_switches_.reserve(num_edges); |
| } |
| |
| /* Reserve a list of switches */ |
| void RRGraph::reserve_switches(const int& num_switches) { |
| this->switch_ids_.reserve(num_switches); |
| this->switches_.reserve(num_switches); |
| } |
| |
| /* Reserve a list of segments */ |
| void RRGraph::reserve_segments(const int& num_segments) { |
| this->segment_ids_.reserve(num_segments); |
| this->segments_.reserve(num_segments); |
| } |
| |
| /* Mutators */ |
| RRNodeId RRGraph::create_node(const t_rr_type& type) { |
| //Allocate an ID |
| RRNodeId node_id = RRNodeId(node_ids_.size()); |
| |
| //Initialize the attributes |
| node_ids_.push_back(node_id); |
| node_types_.push_back(type); |
| |
| node_bounding_boxes_.emplace_back(-1, -1, -1, -1); |
| |
| node_capacities_.push_back(-1); |
| node_ptc_nums_.push_back(-1); |
| node_cost_indices_.push_back(-1); |
| node_directions_.push_back(NO_DIRECTION); |
| node_sides_.push_back(NUM_SIDES); |
| node_Rs_.push_back(0.); |
| node_Cs_.push_back(0.); |
| |
| node_in_edges_.emplace_back(); //Initially empty |
| node_out_edges_.emplace_back(); //Initially empty |
| |
| node_num_non_configurable_in_edges_.emplace_back(); //Initially empty |
| node_num_non_configurable_out_edges_.emplace_back(); //Initially empty |
| |
| invalidate_fast_node_lookup(); |
| |
| VTR_ASSERT(validate_sizes()); |
| |
| return node_id; |
| } |
| |
| RREdgeId RRGraph::create_edge(const RRNodeId& source, const RRNodeId& sink, const RRSwitchId& switch_id) { |
| VTR_ASSERT(valid_node_id(source)); |
| VTR_ASSERT(valid_node_id(sink)); |
| VTR_ASSERT(valid_switch_id(switch_id)); |
| |
| //Allocate an ID |
| RREdgeId edge_id = RREdgeId(edge_ids_.size()); |
| |
| //Initialize the attributes |
| edge_ids_.push_back(edge_id); |
| |
| edge_src_nodes_.push_back(source); |
| edge_sink_nodes_.push_back(sink); |
| edge_switches_.push_back(switch_id); |
| |
| //Add the edge to the nodes |
| node_out_edges_[source].push_back(edge_id); |
| node_in_edges_[sink].push_back(edge_id); |
| |
| VTR_ASSERT(validate_sizes()); |
| |
| return edge_id; |
| } |
| |
| RRSwitchId RRGraph::create_switch(const t_rr_switch_inf& switch_info) { |
| //Allocate an ID |
| RRSwitchId switch_id = RRSwitchId(switch_ids_.size()); |
| switch_ids_.push_back(switch_id); |
| |
| switches_.push_back(switch_info); |
| |
| return switch_id; |
| } |
| |
| /* Create segment */ |
| RRSegmentId RRGraph::create_segment(const t_segment_inf& segment_info) { |
| //Allocate an ID |
| RRSegmentId segment_id = RRSegmentId(segment_ids_.size()); |
| segment_ids_.push_back(segment_id); |
| |
| segments_.push_back(segment_info); |
| |
| return segment_id; |
| } |
| |
| /* This function just marks the node to be removed with an INVALID id |
| * It also disconnects and mark the incoming and outcoming edges to be INVALID() |
| * And then set the RRGraph as polluted (dirty_flag = true) |
| * The compress() function should be called to physically remove the node |
| */ |
| void RRGraph::remove_node(const RRNodeId& node) { |
| //Invalidate all connected edges |
| // TODO: consider removal of self-loop edges? |
| for (auto edge : node_in_edges(node)) { |
| remove_edge(edge); |
| } |
| for (auto edge : node_out_edges(node)) { |
| remove_edge(edge); |
| } |
| |
| //Mark node invalid |
| node_ids_[node] = RRNodeId::INVALID(); |
| |
| //Invalidate the node look-up |
| invalidate_fast_node_lookup(); |
| |
| set_dirty(); |
| } |
| |
| /* This function just marks the edge to be removed with an INVALID id |
| * And then set the RRGraph as polluted (dirty_flag = true) |
| * The compress() function should be called to physically remove the edge |
| */ |
| void RRGraph::remove_edge(const RREdgeId& edge) { |
| RRNodeId src_node = edge_src_node(edge); |
| RRNodeId sink_node = edge_sink_node(edge); |
| |
| //Invalidate node to edge references |
| // TODO: consider making this optional (e.g. if called from remove_node) |
| for (size_t i = 0; i < node_out_edges_[src_node].size(); ++i) { |
| if (node_out_edges_[src_node][i] == edge) { |
| node_out_edges_[src_node][i] = RREdgeId::INVALID(); |
| break; |
| } |
| } |
| for (size_t i = 0; i < node_in_edges_[sink_node].size(); ++i) { |
| if (node_in_edges_[sink_node][i] == edge) { |
| node_in_edges_[sink_node][i] = RREdgeId::INVALID(); |
| break; |
| } |
| } |
| |
| //Mark edge invalid |
| edge_ids_[edge] = RREdgeId::INVALID(); |
| |
| set_dirty(); |
| } |
| |
| void RRGraph::set_node_xlow(const RRNodeId& node, const short& xlow) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| node_bounding_boxes_[node].set_xmin(xlow); |
| } |
| |
| void RRGraph::set_node_ylow(const RRNodeId& node, const short& ylow) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| node_bounding_boxes_[node].set_ymin(ylow); |
| } |
| |
| void RRGraph::set_node_xhigh(const RRNodeId& node, const short& xhigh) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| node_bounding_boxes_[node].set_xmax(xhigh); |
| } |
| |
| void RRGraph::set_node_yhigh(const RRNodeId& node, const short& yhigh) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| node_bounding_boxes_[node].set_ymax(yhigh); |
| } |
| |
| void RRGraph::set_node_bounding_box(const RRNodeId& node, const vtr::Rect<short>& bb) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| node_bounding_boxes_[node] = bb; |
| } |
| |
| void RRGraph::set_node_capacity(const RRNodeId& node, const short& capacity) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| node_capacities_[node] = capacity; |
| } |
| |
| void RRGraph::set_node_ptc_num(const RRNodeId& node, const short& ptc) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| node_ptc_nums_[node] = ptc; |
| } |
| |
| void RRGraph::set_node_pin_num(const RRNodeId& node, const short& pin_id) { |
| VTR_ASSERT(valid_node_id(node)); |
| VTR_ASSERT_MSG(node_type(node) == IPIN || node_type(node) == OPIN, "Pin number valid only for IPIN/OPIN RR nodes"); |
| |
| set_node_ptc_num(node, pin_id); |
| } |
| |
| void RRGraph::set_node_track_num(const RRNodeId& node, const short& track_id) { |
| VTR_ASSERT(valid_node_id(node)); |
| VTR_ASSERT_MSG(node_type(node) == CHANX || node_type(node) == CHANY, "Track number valid only for CHANX/CHANY RR nodes"); |
| |
| set_node_ptc_num(node, track_id); |
| } |
| |
| void RRGraph::set_node_class_num(const RRNodeId& node, const short& class_id) { |
| VTR_ASSERT(valid_node_id(node)); |
| VTR_ASSERT_MSG(node_type(node) == SOURCE || node_type(node) == SINK, "Class number valid only for SOURCE/SINK RR nodes"); |
| |
| set_node_ptc_num(node, class_id); |
| } |
| |
| void RRGraph::set_node_cost_index(const RRNodeId& node, const short& cost_index) { |
| VTR_ASSERT(valid_node_id(node)); |
| node_cost_indices_[node] = cost_index; |
| } |
| |
| void RRGraph::set_node_direction(const RRNodeId& node, const e_direction& direction) { |
| VTR_ASSERT(valid_node_id(node)); |
| VTR_ASSERT_MSG(node_type(node) == CHANX || node_type(node) == CHANY, "Direct can only be specified on CHANX/CNAY rr nodes"); |
| |
| node_directions_[node] = direction; |
| } |
| |
| void RRGraph::set_node_side(const RRNodeId& node, const e_side& side) { |
| VTR_ASSERT(valid_node_id(node)); |
| VTR_ASSERT_MSG(node_type(node) == IPIN || node_type(node) == OPIN, "Side can only be specified on IPIN/OPIN rr nodes"); |
| |
| node_sides_[node] = side; |
| } |
| |
| void RRGraph::set_node_R(const RRNodeId& node, const float& R) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| node_Rs_[node] = R; |
| } |
| |
| void RRGraph::set_node_C(const RRNodeId& node, const float& C) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| node_Cs_[node] = C; |
| } |
| |
| /* |
| * Set a segment id for a node in rr_graph |
| */ |
| void RRGraph::set_node_segment(const RRNodeId& node, const RRSegmentId& segment_id) { |
| VTR_ASSERT(valid_node_id(node)); |
| |
| /* Only CHANX and CHANY requires a valid segment id */ |
| if ((CHANX == node_type(node)) |
| || (CHANY == node_type(node))) { |
| VTR_ASSERT(valid_segment_id(segment_id)); |
| } |
| |
| node_segments_[node] = segment_id; |
| } |
| |
| /* For a given node in a rr_graph |
| * classify the edges of each node to be configurable (1st part) and non-configurable (2nd part) |
| */ |
| void RRGraph::partition_node_in_edges(const RRNodeId& node) { |
| //Partition the edges so the first set of edges are all configurable, and the later are not |
| auto first_non_config_edge = std::partition(node_in_edges_[node].begin(), node_in_edges_[node].end(), |
| [&](const RREdgeId edge) { return edge_is_configurable(edge); }); /* Condition to partition edges */ |
| |
| size_t num_conf_edges = std::distance(node_in_edges_[node].begin(), first_non_config_edge); |
| size_t num_non_conf_edges = node_in_edges_[node].size() - num_conf_edges; //Note we calculate using the size_t to get full range |
| |
| /* Check that within allowable range (no overflow when stored as num_non_configurable_edges_ |
| */ |
| VTR_ASSERT_MSG(num_non_conf_edges <= node_in_edges_[node].size(), |
| "Exceeded RR node maximum number of non-configurable input edges"); |
| |
| node_num_non_configurable_in_edges_[node] = num_non_conf_edges; //Narrowing |
| } |
| |
| /* For a given node in a rr_graph |
| * classify the edges of each node to be configurable (1st part) and non-configurable (2nd part) |
| */ |
| void RRGraph::partition_node_out_edges(const RRNodeId& node) { |
| //Partition the edges so the first set of edges are all configurable, and the later are not |
| auto first_non_config_edge = std::partition(node_out_edges_[node].begin(), node_out_edges_[node].end(), |
| [&](const RREdgeId edge) { return edge_is_configurable(edge); }); /* Condition to partition edges */ |
| |
| size_t num_conf_edges = std::distance(node_out_edges_[node].begin(), first_non_config_edge); |
| size_t num_non_conf_edges = node_out_edges_[node].size() - num_conf_edges; //Note we calculate using the size_t to get full range |
| |
| /* Check that within allowable range (no overflow when stored as num_non_configurable_edges_ |
| */ |
| VTR_ASSERT_MSG(num_non_conf_edges <= node_out_edges_[node].size(), |
| "Exceeded RR node maximum number of non-configurable output edges"); |
| |
| node_num_non_configurable_out_edges_[node] = num_non_conf_edges; //Narrowing |
| } |
| |
| /* For all nodes in a rr_graph |
| * classify the input edges of each node to be configurable (1st part) and non-configurable (2nd part) |
| */ |
| void RRGraph::partition_in_edges() { |
| /* For each node */ |
| for (auto node : nodes()) { |
| this->partition_node_in_edges(node); |
| } |
| } |
| |
| /* For all nodes in a rr_graph |
| * classify the output edges of each node to be configurable (1st part) and non-configurable (2nd part) |
| */ |
| void RRGraph::partition_out_edges() { |
| /* For each node */ |
| for (auto node : nodes()) { |
| this->partition_node_out_edges(node); |
| } |
| } |
| |
| /* For all nodes in a rr_graph |
| * classify both input and output edges of each node |
| * to be configurable (1st part) and non-configurable (2nd part) |
| */ |
| void RRGraph::partition_edges() { |
| /* Partition input edges */ |
| this->partition_in_edges(); |
| /* Partition output edges */ |
| this->partition_out_edges(); |
| } |
| |
| void RRGraph::build_fast_node_lookup() const { |
| invalidate_fast_node_lookup(); |
| |
| for (auto node : nodes()) { |
| size_t x = node_xlow(node); |
| if (x >= node_lookup_.size()) { |
| node_lookup_.resize(x + 1); |
| } |
| |
| size_t y = node_ylow(node); |
| if (y >= node_lookup_[x].size()) { |
| node_lookup_[x].resize(y + 1); |
| } |
| |
| size_t itype = node_type(node); |
| if (itype >= node_lookup_[x][y].size()) { |
| node_lookup_[x][y].resize(itype + 1); |
| } |
| |
| size_t ptc = node_ptc_num(node); |
| if (ptc >= node_lookup_[x][y][itype].size()) { |
| node_lookup_[x][y][itype].resize(ptc + 1); |
| } |
| |
| size_t iside = -1; |
| if (node_type(node) == OPIN || node_type(node) == IPIN) { |
| iside = node_side(node); |
| } else { |
| iside = NUM_SIDES; |
| } |
| |
| if (iside >= node_lookup_[x][y][itype][ptc].size()) { |
| node_lookup_[x][y][itype][ptc].resize(iside + 1); |
| } |
| |
| //Save node in lookup |
| node_lookup_[x][y][itype][ptc][iside] = node; |
| } |
| } |
| |
| void RRGraph::invalidate_fast_node_lookup() const { |
| node_lookup_.clear(); |
| } |
| |
| bool RRGraph::valid_fast_node_lookup() const { |
| return !node_lookup_.empty(); |
| } |
| |
| void RRGraph::initialize_fast_node_lookup() const { |
| if (!valid_fast_node_lookup()) { |
| build_fast_node_lookup(); |
| } |
| } |
| |
| bool RRGraph::valid_node_id(const RRNodeId& node) const { |
| return size_t(node) < node_ids_.size() && node_ids_[node] == node; |
| } |
| |
| bool RRGraph::valid_edge_id(const RREdgeId& edge) const { |
| return size_t(edge) < edge_ids_.size() && edge_ids_[edge] == edge; |
| } |
| |
| /* check if a given switch id is valid or not */ |
| bool RRGraph::valid_switch_id(const RRSwitchId& switch_id) const { |
| /* TODO: should we check the index of switch[id] matches ? */ |
| return size_t(switch_id) < switches_.size(); |
| } |
| |
| /* check if a given segment id is valid or not */ |
| bool RRGraph::valid_segment_id(const RRSegmentId& segment_id) const { |
| /* TODO: should we check the index of segment[id] matches ? */ |
| return size_t(segment_id) < segments_.size(); |
| } |
| |
| /** |
| * Internal checking codes to ensure data consistency |
| * If you add any internal data to RRGraph and update create_node/edge etc. |
| * you need to update the validate_sizes() here to make sure these |
| * internal vectors are aligned to the id vectors |
| */ |
| bool RRGraph::validate_sizes() const { |
| return validate_node_sizes() |
| && validate_edge_sizes() |
| && validate_switch_sizes() |
| && validate_segment_sizes(); |
| } |
| |
| bool RRGraph::validate_node_sizes() const { |
| return node_types_.size() == node_ids_.size() |
| && node_bounding_boxes_.size() == node_ids_.size() |
| && node_capacities_.size() == node_ids_.size() |
| && node_ptc_nums_.size() == node_ids_.size() |
| && node_cost_indices_.size() == node_ids_.size() |
| && node_directions_.size() == node_ids_.size() |
| && node_sides_.size() == node_ids_.size() |
| && node_Rs_.size() == node_ids_.size() |
| && node_Cs_.size() == node_ids_.size() |
| && node_segments_.size() == node_ids_.size() |
| && node_num_non_configurable_in_edges_.size() == node_ids_.size() |
| && node_num_non_configurable_out_edges_.size() == node_ids_.size() |
| && node_in_edges_.size() == node_ids_.size() |
| && node_out_edges_.size() == node_ids_.size(); |
| } |
| |
| bool RRGraph::validate_edge_sizes() const { |
| return edge_src_nodes_.size() == edge_ids_.size() |
| && edge_sink_nodes_.size() == edge_ids_.size() |
| && edge_switches_.size() == edge_ids_.size(); |
| } |
| |
| bool RRGraph::validate_switch_sizes() const { |
| return switches_.size() == switch_ids_.size(); |
| } |
| |
| bool RRGraph::validate_segment_sizes() const { |
| return segments_.size() == segment_ids_.size(); |
| } |
| |
| void RRGraph::compress() { |
| vtr::vector<RRNodeId, RRNodeId> node_id_map(node_ids_.size()); |
| vtr::vector<RREdgeId, RREdgeId> edge_id_map(edge_ids_.size()); |
| |
| build_id_maps(node_id_map, edge_id_map); |
| |
| clean_nodes(node_id_map); |
| clean_edges(edge_id_map); |
| |
| rebuild_node_refs(edge_id_map); |
| |
| invalidate_fast_node_lookup(); |
| |
| clear_dirty(); |
| } |
| |
| void RRGraph::build_id_maps(vtr::vector<RRNodeId, RRNodeId>& node_id_map, |
| vtr::vector<RREdgeId, RREdgeId>& edge_id_map) { |
| node_id_map = compress_ids(node_ids_); |
| edge_id_map = compress_ids(edge_ids_); |
| } |
| |
| void RRGraph::clean_nodes(const vtr::vector<RRNodeId, RRNodeId>& node_id_map) { |
| node_ids_ = clean_and_reorder_ids(node_id_map); |
| |
| node_types_ = clean_and_reorder_values(node_types_, node_id_map); |
| |
| node_bounding_boxes_ = clean_and_reorder_values(node_bounding_boxes_, node_id_map); |
| |
| node_capacities_ = clean_and_reorder_values(node_capacities_, node_id_map); |
| node_ptc_nums_ = clean_and_reorder_values(node_ptc_nums_, node_id_map); |
| node_cost_indices_ = clean_and_reorder_values(node_cost_indices_, node_id_map); |
| node_directions_ = clean_and_reorder_values(node_directions_, node_id_map); |
| node_sides_ = clean_and_reorder_values(node_sides_, node_id_map); |
| node_Rs_ = clean_and_reorder_values(node_Rs_, node_id_map); |
| node_Cs_ = clean_and_reorder_values(node_Cs_, node_id_map); |
| |
| VTR_ASSERT(validate_node_sizes()); |
| |
| VTR_ASSERT_MSG(are_contiguous(node_ids_), "Ids should be contiguous"); |
| VTR_ASSERT_MSG(all_valid(node_ids_), "All Ids should be valid"); |
| } |
| |
| void RRGraph::clean_edges(const vtr::vector<RREdgeId, RREdgeId>& edge_id_map) { |
| edge_ids_ = clean_and_reorder_ids(edge_id_map); |
| |
| edge_src_nodes_ = clean_and_reorder_values(edge_src_nodes_, edge_id_map); |
| edge_sink_nodes_ = clean_and_reorder_values(edge_sink_nodes_, edge_id_map); |
| edge_switches_ = clean_and_reorder_values(edge_switches_, edge_id_map); |
| |
| VTR_ASSERT(validate_edge_sizes()); |
| |
| VTR_ASSERT_MSG(are_contiguous(edge_ids_), "Ids should be contiguous"); |
| VTR_ASSERT_MSG(all_valid(edge_ids_), "All Ids should be valid"); |
| } |
| |
| void RRGraph::rebuild_node_refs(const vtr::vector<RREdgeId, RREdgeId>& edge_id_map) { |
| for (const auto& node : nodes()) { |
| node_in_edges_[node] = update_valid_refs(node_in_edges_[node], edge_id_map); |
| node_out_edges_[node] = update_valid_refs(node_out_edges_[node], edge_id_map); |
| |
| VTR_ASSERT_MSG(all_valid(node_in_edges_[node]), "All Ids should be valid"); |
| VTR_ASSERT_MSG(all_valid(node_out_edges_[node]), "All Ids should be valid"); |
| } |
| } |
| |
| /* Empty all the vectors related to nodes */ |
| void RRGraph::clear_nodes() { |
| node_ids_.clear(); |
| |
| node_types_.clear(); |
| node_bounding_boxes_.clear(); |
| |
| node_capacities_.clear(); |
| node_ptc_nums_.clear(); |
| node_cost_indices_.clear(); |
| node_directions_.clear(); |
| node_sides_.clear(); |
| node_Rs_.clear(); |
| node_Cs_.clear(); |
| node_segments_.clear(); |
| |
| node_num_non_configurable_in_edges_.clear(); |
| node_num_non_configurable_out_edges_.clear(); |
| |
| node_in_edges_.clear(); |
| node_out_edges_.clear(); |
| |
| /* clean node_look_up */ |
| node_lookup_.clear(); |
| } |
| |
| /* Empty all the vectors related to edges */ |
| void RRGraph::clear_edges() { |
| edge_ids_.clear(); |
| edge_src_nodes_.clear(); |
| edge_sink_nodes_.clear(); |
| edge_switches_.clear(); |
| } |
| |
| /* Empty all the vectors related to switches */ |
| void RRGraph::clear_switches() { |
| switch_ids_.clear(); |
| switches_.clear(); |
| } |
| |
| /* Empty all the vectors related to segments */ |
| void RRGraph::clear_segments() { |
| segment_ids_.clear(); |
| segments_.clear(); |
| } |
| |
| /* Clean the rr_graph */ |
| void RRGraph::clear() { |
| clear_nodes(); |
| clear_edges(); |
| clear_switches(); |
| clear_segments(); |
| } |