vpr/src/route/rr_graph.cpp
/* Does the actual work of allocating the rr_graph and filling all the *
 * appropriate values.  Everything up to this was just a prelude!      */
Does the actual work of allocating the rr_graph and filling all the
appropriate values.  Everything up to this was just a prelude!
Does the actual work of allocating the rr_graph and filling all the appropriate values . Everything up to this was just a prelude!
static void alloc_and_load_rr_graph(RRGraph& rr_graph,
                                    const int num_seg_types,
                                    const t_chan_details& chan_details_x,
                                    const t_chan_details& chan_details_y,
                                    const t_track_to_pin_lookup& track_to_pin_lookup,
                                    const t_pin_to_track_lookup& opin_to_track_map,
                                    const vtr::NdMatrix<std::vector<int>, 3>& switch_block_conn,
                                    t_sb_connection_map* sb_conn_map,
                                    const DeviceGrid& grid,
                                    const int Fs,
                                    t_sblock_pattern& sblock_pattern,
                                    const std::vector<vtr::Matrix<int>>& Fc_out,
                                    vtr::NdMatrix<int, 3>& Fc_xofs,
                                    vtr::NdMatrix<int, 3>& Fc_yofs,
                                    const t_rr_node_indices& L_rr_node_indices,
                                    const int max_chan_width,
                                    const t_chan_width& chan_width,
                                    const int wire_to_ipin_switch,
                                    const int delayless_switch,
                                    const enum e_directionality directionality,
                                    bool* Fc_clipped,
                                    const t_direct_inf* directs,
                                    const int num_directs,
                                    const t_clb_to_clb_directs* clb_to_clb_directs,
                                    bool is_global_graph) {
    In particular, all the following build_*() functions do not create the edges, but
    instead record the edges they wish to create in rr_edges_to_create.
    We uniquify the edges to be created (avoiding any duplicates), and create
    the edges in alloc_and_load_edges().
    By doing things in this manner we ensure we know exactly how many edges leave each RR
    node, which avoids resizing the RR edge arrays (which can cause significant memory
    fragmentation, and significantly increasing peak memory usage). This is important since
    RR graph creation is the high-watermark of VPR's memory use.
    t_rr_edge_info_set rr_edges_to_create;
    *Fc_clipped = false;
    for (size_t i = 0; i < grid.width(); ++i) {
        for (size_t j = 0; j < grid.height(); ++j) {
            build_rr_sinks_sources(i, j, rr_graph, rr_edges_to_create, L_rr_node_indices,
                                   delayless_switch, grid);
            Create the actual SOURCE->OPIN, IPIN->SINK edges
            uniquify_edges(rr_edges_to_create);
            alloc_and_load_edges(rr_graph, rr_edges_to_create);
            rr_edges_to_create.clear();
        }
    }
    for (size_t i = 0; i < grid.width(); ++i) {
        for (size_t j = 0; j < grid.height(); ++j) {
            for (e_side side : SIDES) {
                if (BI_DIRECTIONAL == directionality) {
                    build_bidir_rr_opins(i, j, side, L_rr_node_indices, rr_graph,
                                         opin_to_track_map, Fc_out, rr_edges_to_create, chan_details_x, chan_details_y,
                                         grid,
                                         directs, num_directs, clb_to_clb_directs, num_seg_types);
                } else {
                    VTR_ASSERT(UNI_DIRECTIONAL == directionality);
                    bool clipped;
                    build_unidir_rr_opins(i, j, side, grid, Fc_out, max_chan_width,
                                          chan_details_x, chan_details_y, Fc_xofs, Fc_yofs,
                                          rr_edges_to_create, &clipped, L_rr_node_indices, const_cast<const RRGraph&>(rr_graph),
                                          directs, num_directs, clb_to_clb_directs, num_seg_types);
                    if (clipped) {
                        *Fc_clipped = true;
                    }
                }
                Create the actual OPIN->CHANX/CHANY edges
                uniquify_edges(rr_edges_to_create);
                alloc_and_load_edges(rr_graph, rr_edges_to_create);
                rr_edges_to_create.clear();
            }
        }
    }
    VTR_ASSERT(Fs % 3 == 0);
    for (size_t i = 0; i < grid.width() - 1; ++i) {
        for (size_t j = 0; j < grid.height() - 1; ++j) {
            if (i > 0) {
                int tracks_per_chan = ((is_global_graph) ? 1 : chan_width.x_list[j]);
                build_rr_chan(i, j, CHANX, track_to_pin_lookup, sb_conn_map, switch_block_conn,
                              CHANX_COST_INDEX_START,
                              max_chan_width, grid, tracks_per_chan,
                              sblock_pattern, Fs / 3, chan_details_x, chan_details_y,
                              L_rr_node_indices, rr_edges_to_create, rr_graph,
                              wire_to_ipin_switch,
                              directionality);
                Create the actual CHAN->CHAN edges
                uniquify_edges(rr_edges_to_create);
                alloc_and_load_edges(rr_graph, rr_edges_to_create);
                rr_edges_to_create.clear();
            }
            if (j > 0) {
                int tracks_per_chan = ((is_global_graph) ? 1 : chan_width.y_list[i]);
                build_rr_chan(i, j, CHANY, track_to_pin_lookup, sb_conn_map, switch_block_conn,
                              CHANX_COST_INDEX_START + num_seg_types,
                              max_chan_width, grid, tracks_per_chan,
                              sblock_pattern, Fs / 3, chan_details_x, chan_details_y,
                              L_rr_node_indices, rr_edges_to_create, rr_graph,
                              wire_to_ipin_switch,
                              directionality);
                Create the actual CHAN->CHAN edges
                uniquify_edges(rr_edges_to_create);
                alloc_and_load_edges(rr_graph, rr_edges_to_create);
                rr_edges_to_create.clear();
            }
        }
    }
}
static void alloc_and_load_rr_graph ( RRGraph & rr_graph , const int num_seg_types , const t_chan_details & chan_details_x , const t_chan_details & chan_details_y , const t_track_to_pin_lookup & track_to_pin_lookup , const t_pin_to_track_lookup & opin_to_track_map , const vtr :: NdMatrix < std :: vector < int > , 3 > & switch_block_conn , t_sb_connection_map * sb_conn_map , const DeviceGrid & grid , const int Fs , t_sblock_pattern & sblock_pattern , const std :: vector < vtr :: Matrix < int > > & Fc_out , vtr :: NdMatrix < int , 3 > & Fc_xofs , vtr :: NdMatrix < int , 3 > & Fc_yofs , const t_rr_node_indices & L_rr_node_indices , const int max_chan_width , const t_chan_width & chan_width , const int wire_to_ipin_switch , const int delayless_switch , const enum e_directionality directionality , bool * Fc_clipped , const t_direct_inf * directs , const int num_directs , const t_clb_to_clb_directs * clb_to_clb_directs , bool is_global_graph ) { t_rr_edge_info_set rr_edges_to_create ; * Fc_clipped = false ; for ( size_t i = 0 ; i < grid . width ( ) ; ++ i ) { for ( size_t j = 0 ; j < grid . height ( ) ; ++ j ) { build_rr_sinks_sources ( i , j , rr_graph , rr_edges_to_create , L_rr_node_indices , delayless_switch , grid ) ; uniquify_edges ( rr_edges_to_create ) ; alloc_and_load_edges ( rr_graph , rr_edges_to_create ) ; rr_edges_to_create . clear ( ) ; } } for ( size_t i = 0 ; i < grid . width ( ) ; ++ i ) { for ( size_t j = 0 ; j < grid . height ( ) ; ++ j ) { for ( e_side side : SIDES ) { if ( BI_DIRECTIONAL == directionality ) { build_bidir_rr_opins ( i , j , side , L_rr_node_indices , rr_graph , opin_to_track_map , Fc_out , rr_edges_to_create , chan_details_x , chan_details_y , grid , directs , num_directs , clb_to_clb_directs , num_seg_types ) ; } else { VTR_ASSERT ( UNI_DIRECTIONAL == directionality ) ; bool clipped ; build_unidir_rr_opins ( i , j , side , grid , Fc_out , max_chan_width , chan_details_x , chan_details_y , Fc_xofs , Fc_yofs , rr_edges_to_create , & clipped , L_rr_node_indices , const_cast < const RRGraph & > ( rr_graph ) , directs , num_directs , clb_to_clb_directs , num_seg_types ) ; if ( clipped ) { * Fc_clipped = true ; } } uniquify_edges ( rr_edges_to_create ) ; alloc_and_load_edges ( rr_graph , rr_edges_to_create ) ; rr_edges_to_create . clear ( ) ; } } } VTR_ASSERT ( Fs % 3 == 0 ) ; for ( size_t i = 0 ; i < grid . width ( ) - 1 ; ++ i ) { for ( size_t j = 0 ; j < grid . height ( ) - 1 ; ++ j ) { if ( i > 0 ) { int tracks_per_chan = ( ( is_global_graph ) ? 1 : chan_width . x_list [ j ] ) ; build_rr_chan ( i , j , CHANX , track_to_pin_lookup , sb_conn_map , switch_block_conn , CHANX_COST_INDEX_START , max_chan_width , grid , tracks_per_chan , sblock_pattern , Fs / 3 , chan_details_x , chan_details_y , L_rr_node_indices , rr_edges_to_create , rr_graph , wire_to_ipin_switch , directionality ) ; uniquify_edges ( rr_edges_to_create ) ; alloc_and_load_edges ( rr_graph , rr_edges_to_create ) ; rr_edges_to_create . clear ( ) ; } if ( j > 0 ) { int tracks_per_chan = ( ( is_global_graph ) ? 1 : chan_width . y_list [ i ] ) ; build_rr_chan ( i , j , CHANY , track_to_pin_lookup , sb_conn_map , switch_block_conn , CHANX_COST_INDEX_START + num_seg_types , max_chan_width , grid , tracks_per_chan , sblock_pattern , Fs / 3 , chan_details_x , chan_details_y , L_rr_node_indices , rr_edges_to_create , rr_graph , wire_to_ipin_switch , directionality ) ; uniquify_edges ( rr_edges_to_create ) ; alloc_and_load_edges ( rr_graph , rr_edges_to_create ) ; rr_edges_to_create . clear ( ) ; } } } }
Does the actual work of allocating the rr_graph and filling all the
 appropriate values.
Does the actual work of allocating the rr_graph and filling all the appropriate values .
//We take special care when creating RR graph edges (there are typically many more //edges than nodes in an RR graph). // //In particular, all the following build_*() functions do not create the edges, but //instead record the edges they wish to create in rr_edges_to_create. // //We uniquify the edges to be created (avoiding any duplicates), and create //the edges in alloc_and_load_edges(). // //By doing things in this manner we ensure we know exactly how many edges leave each RR //node, which avoids resizing the RR edge arrays (which can cause significant memory //fragmentation, and significantly increasing peak memory usage). This is important since //RR graph creation is the high-watermark of VPR's memory use. /* If Fc gets clipped, this will be flagged to true */ /* Connection SINKS and SOURCES to their pins. */ //Create the actual SOURCE->OPIN, IPIN->SINK edges /* Build opins */ //Create the actual OPIN->CHANX/CHANY edges /* Build channels */ //Create the actual CHAN->CHAN edges //Create the actual CHAN->CHAN edges