vpr/src/device/create_rr_graph.cpp
/********************************************************************
 * TODO: remove when this conversion (from traditional to new data structure)
 * is no longer needed
 * This function will convert an existing rr_graph in device_ctx to the RRGraph
 *object
 * This function is used to test our RRGraph if it is acceptable in downstream
 *routers
 ********************************************************************/
remove when this conversion (from traditional to new data structure)
is no longer needed
This function will convert an existing rr_graph in device_ctx to the RRGraph
object
This function is used to test our RRGraph if it is acceptable in downstream
routers
remove when this conversion ( from traditional to new data structure ) is no longer needed This function will convert an existing rr_graph in device_ctx to the RRGraph object This function is used to test our RRGraph if it is acceptable in downstream routers
void convert_rr_graph(std::vector<t_segment_inf>& vpr_segments) {
    vtr::malloc_trim(0);
    vtr::ScopedStartFinishTimer timer("Conversion to routing resource graph object");
    auto& device_ctx = g_vpr_ctx.mutable_device();
    device_ctx.rr_graph.reserve_switches(device_ctx.rr_switch_inf.size());
    for (size_t iswitch = 0; iswitch < device_ctx.rr_switch_inf.size(); ++iswitch) {
        device_ctx.rr_graph.create_switch(device_ctx.rr_switch_inf[iswitch]);
    }
    device_ctx.rr_graph.reserve_segments(vpr_segments.size());
    for (size_t iseg = 0; iseg < vpr_segments.size(); ++iseg) {
        device_ctx.rr_graph.create_segment(vpr_segments[iseg]);
    }
    device_ctx.rr_graph.reserve_nodes((unsigned long)device_ctx.rr_nodes.size());
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
        auto& node = device_ctx.rr_nodes[inode];
        RRNodeId rr_node = device_ctx.rr_graph.create_node(node.type());
        device_ctx.rr_graph.set_node_xlow(rr_node, node.xlow());
        device_ctx.rr_graph.set_node_ylow(rr_node, node.ylow());
        device_ctx.rr_graph.set_node_xhigh(rr_node, node.xhigh());
        device_ctx.rr_graph.set_node_yhigh(rr_node, node.yhigh());
        device_ctx.rr_graph.set_node_capacity(rr_node, node.capacity());
        device_ctx.rr_graph.set_node_ptc_num(rr_node, node.ptc_num());
        device_ctx.rr_graph.set_node_cost_index(rr_node, node.cost_index());
        if (CHANX == node.type() || CHANY == node.type()) {
            device_ctx.rr_graph.set_node_direction(rr_node, node.direction());
        }
        if (IPIN == node.type() || OPIN == node.type()) {
            device_ctx.rr_graph.set_node_side(rr_node, node.side());
        }
        device_ctx.rr_graph.set_node_R(rr_node, node.R());
        device_ctx.rr_graph.set_node_C(rr_node, node.C());
        short irc_data = node.cost_index();
        short iseg = device_ctx.rr_indexed_data[irc_data].seg_index;
        device_ctx.rr_graph.set_node_segment(rr_node, RRSegmentId(iseg));
    }
    unsigned long num_edges_to_reserve = 0;
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
        const auto& node = device_ctx.rr_nodes[inode];
        num_edges_to_reserve += node.num_edges();
    }
    device_ctx.rr_graph.reserve_edges(num_edges_to_reserve);
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
        const auto& node = device_ctx.rr_nodes[inode];
        for (int iedge = 0; iedge < node.num_edges(); ++iedge) {
            size_t isink_node = node.edge_sink_node(iedge);
            int iswitch = node.edge_switch(iedge);
            device_ctx.rr_graph.create_edge(RRNodeId(inode),
                                            RRNodeId(isink_node),
                                            RRSwitchId(iswitch));
        }
    }
    VTR_ASSERT(num_edges_to_reserve == (unsigned long)device_ctx.rr_graph.edges().size());
    device_ctx.rr_graph.rebuild_node_edges();
    if (false == device_ctx.rr_graph.validate()) {
        vpr_throw(VPR_ERROR_ROUTE,
                  __FILE__,
                  __LINE__,
                  "Fundamental errors occurred when validating rr_graph object!\n");
    }
    if (false == check_rr_graph(device_ctx.rr_graph)) {
        vpr_throw(VPR_ERROR_ROUTE,
                  __FILE__,
                  __LINE__,
                  "Advanced checking rr_graph object fails! Routing may still work "
                  "but not smooth\n");
    }
}
void convert_rr_graph ( std :: vector < t_segment_inf > & vpr_segments ) { vtr :: malloc_trim ( 0 ) ; vtr :: ScopedStartFinishTimer timer ( " " ) ; auto & device_ctx = g_vpr_ctx . mutable_device ( ) ; device_ctx . rr_graph . reserve_switches ( device_ctx . rr_switch_inf . size ( ) ) ; for ( size_t iswitch = 0 ; iswitch < device_ctx . rr_switch_inf . size ( ) ; ++ iswitch ) { device_ctx . rr_graph . create_switch ( device_ctx . rr_switch_inf [ iswitch ] ) ; } device_ctx . rr_graph . reserve_segments ( vpr_segments . size ( ) ) ; for ( size_t iseg = 0 ; iseg < vpr_segments . size ( ) ; ++ iseg ) { device_ctx . rr_graph . create_segment ( vpr_segments [ iseg ] ) ; } device_ctx . rr_graph . reserve_nodes ( ( unsigned long ) device_ctx . rr_nodes . size ( ) ) ; for ( size_t inode = 0 ; inode < device_ctx . rr_nodes . size ( ) ; ++ inode ) { auto & node = device_ctx . rr_nodes [ inode ] ; RRNodeId rr_node = device_ctx . rr_graph . create_node ( node . type ( ) ) ; device_ctx . rr_graph . set_node_xlow ( rr_node , node . xlow ( ) ) ; device_ctx . rr_graph . set_node_ylow ( rr_node , node . ylow ( ) ) ; device_ctx . rr_graph . set_node_xhigh ( rr_node , node . xhigh ( ) ) ; device_ctx . rr_graph . set_node_yhigh ( rr_node , node . yhigh ( ) ) ; device_ctx . rr_graph . set_node_capacity ( rr_node , node . capacity ( ) ) ; device_ctx . rr_graph . set_node_ptc_num ( rr_node , node . ptc_num ( ) ) ; device_ctx . rr_graph . set_node_cost_index ( rr_node , node . cost_index ( ) ) ; if ( CHANX == node . type ( ) || CHANY == node . type ( ) ) { device_ctx . rr_graph . set_node_direction ( rr_node , node . direction ( ) ) ; } if ( IPIN == node . type ( ) || OPIN == node . type ( ) ) { device_ctx . rr_graph . set_node_side ( rr_node , node . side ( ) ) ; } device_ctx . rr_graph . set_node_R ( rr_node , node . R ( ) ) ; device_ctx . rr_graph . set_node_C ( rr_node , node . C ( ) ) ; short irc_data = node . cost_index ( ) ; short iseg = device_ctx . rr_indexed_data [ irc_data ] . seg_index ; device_ctx . rr_graph . set_node_segment ( rr_node , RRSegmentId ( iseg ) ) ; } unsigned long num_edges_to_reserve = 0 ; for ( size_t inode = 0 ; inode < device_ctx . rr_nodes . size ( ) ; ++ inode ) { const auto & node = device_ctx . rr_nodes [ inode ] ; num_edges_to_reserve += node . num_edges ( ) ; } device_ctx . rr_graph . reserve_edges ( num_edges_to_reserve ) ; for ( size_t inode = 0 ; inode < device_ctx . rr_nodes . size ( ) ; ++ inode ) { const auto & node = device_ctx . rr_nodes [ inode ] ; for ( int iedge = 0 ; iedge < node . num_edges ( ) ; ++ iedge ) { size_t isink_node = node . edge_sink_node ( iedge ) ; int iswitch = node . edge_switch ( iedge ) ; device_ctx . rr_graph . create_edge ( RRNodeId ( inode ) , RRNodeId ( isink_node ) , RRSwitchId ( iswitch ) ) ; } } VTR_ASSERT ( num_edges_to_reserve == ( unsigned long ) device_ctx . rr_graph . edges ( ) . size ( ) ) ; device_ctx . rr_graph . rebuild_node_edges ( ) ; if ( false == device_ctx . rr_graph . validate ( ) ) { vpr_throw ( VPR_ERROR_ROUTE , __FILE__ , __LINE__ , " \n " ) ; } if ( false == check_rr_graph ( device_ctx . rr_graph ) ) { vpr_throw ( VPR_ERROR_ROUTE , __FILE__ , __LINE__ , " " " \n " ) ; } }
TODO: remove when this conversion (from traditional to new data structure)
 is no longer needed
 This function will convert an existing rr_graph in device_ctx to the RRGraph
object
 This function is used to test our RRGraph if it is acceptable in downstream
routers
TODO : remove when this conversion ( from traditional to new data structure ) is no longer needed This function will convert an existing rr_graph in device_ctx to the RRGraph object This function is used to test our RRGraph if it is acceptable in downstream routers
/* Release freed memory before start building rr_graph */ /* IMPORTANT: to build clock tree,
     * vpr added segments to the original arch segments
     * This is why to use vpr_segments as an inputs!!!
     */ /* The number of switches are in general small,
     * reserve switches may not bring significant memory efficiency
     * So, we just use create_switch to push_back each time
     */ // Create the switches /* The number of segments are in general small, reserve segments may not bring
     * significant memory efficiency */ // Create the segments /* Reserve list of nodes to be memory efficient */ // Create the nodes /* Set up segment id */ /* Reserve list of edges to be memory efficient */ /* Add edges for each node */ /* Ensure that we reserved what we want */ /* Partition edges to be two class: configurable (1st part) and
     * non-configurable (2nd part)
     * See how the router will use the edges and determine the strategy
     * if we want to partition the edges first or depends on the routing needs
     */ /* Essential check for rr_graph, build look-up and  */ /* Error out if built-in validator of rr_graph fails */ /* Error out if advanced checker of rr_graph fails */