vpr/src/route/rr_graph.cpp
/**
 * Parse out which CLB pins should connect directly to which other CLB pins then store that in a clb_to_clb_directs data structure
 * This data structure supplements the the info in the "directs" data structure
 * TODO: The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety, should replace with this one
 */
Parse out which CLB pins should connect directly to which other CLB pins then store that in a clb_to_clb_directs data structure
This data structure supplements the the info in the "directs" data structure
TODO: The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety, should replace with this one
Parse out which CLB pins should connect directly to which other CLB pins then store that in a clb_to_clb_directs data structure This data structure supplements the the info in the " directs " data structure TODO : The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety should replace with this one
t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch) {
    int i;
    t_clb_to_clb_directs* clb_to_clb_directs;
    char *tile_name, *port_name;
    int start_pin_index, end_pin_index;
    t_physical_tile_type_ptr physical_tile = nullptr;
    t_physical_tile_port tile_port;
    auto& device_ctx = g_vpr_ctx.device();
    clb_to_clb_directs = (t_clb_to_clb_directs*)vtr::calloc(num_directs, sizeof(t_clb_to_clb_directs));
    tile_name = nullptr;
    port_name = nullptr;
    for (i = 0; i < num_directs; i++) {
        tile_name = (char*)vtr::malloc((strlen(directs[i].from_pin) + strlen(directs[i].to_pin)) * sizeof(char));
        port_name = (char*)vtr::malloc((strlen(directs[i].from_pin) + strlen(directs[i].to_pin)) * sizeof(char));
        parse_direct_pin_name(directs[i].from_pin, directs[i].line, &start_pin_index, &end_pin_index, tile_name, port_name);
        for (const auto& type : device_ctx.physical_tile_types) {
            if (strcmp(type.name, tile_name) == 0) {
                physical_tile = &type;
                break;
            }
        }
        if (physical_tile == nullptr) {
            VPR_THROW(VPR_ERROR_ARCH, "Unable to find block %s.\n", tile_name);
        }
        clb_to_clb_directs[i].from_clb_type = physical_tile;
        bool port_found = false;
        for (const auto& port : physical_tile->ports) {
            if (0 == strcmp(port.name, port_name)) {
                tile_port = port;
                port_found = true;
                break;
            }
        }
        if (!port_found) {
            VPR_THROW(VPR_ERROR_ARCH, "Unable to find port %s (on block %s).\n", port_name, tile_name);
        }
        if (start_pin_index == OPEN) {
            VTR_ASSERT(start_pin_index == end_pin_index);
            start_pin_index = 0;
            end_pin_index = tile_port.num_pins - 1;
        }
        clb_to_clb_directs[i].from_clb_pin_start_index = tile_port.absolute_first_pin_index + start_pin_index;
        clb_to_clb_directs[i].from_clb_pin_end_index = tile_port.absolute_first_pin_index + end_pin_index;
        parse_direct_pin_name(directs[i].to_pin, directs[i].line, &start_pin_index, &end_pin_index, tile_name, port_name);
        for (const auto& type : device_ctx.physical_tile_types) {
            if (strcmp(type.name, tile_name) == 0) {
                physical_tile = &type;
                break;
            }
        }
        if (physical_tile == nullptr) {
            VPR_THROW(VPR_ERROR_ARCH, "Unable to find block %s.\n", tile_name);
        }
        clb_to_clb_directs[i].to_clb_type = physical_tile;
        port_found = false;
        for (const auto& port : physical_tile->ports) {
            if (0 == strcmp(port.name, port_name)) {
                tile_port = port;
                port_found = true;
                break;
            }
        }
        if (!port_found) {
            VPR_THROW(VPR_ERROR_ARCH, "Unable to find port %s (on block %s).\n", port_name, tile_name);
        }
        if (start_pin_index == OPEN) {
            VTR_ASSERT(start_pin_index == end_pin_index);
            start_pin_index = 0;
            end_pin_index = tile_port.num_pins - 1;
        }
        clb_to_clb_directs[i].to_clb_pin_start_index = tile_port.absolute_first_pin_index + start_pin_index;
        clb_to_clb_directs[i].to_clb_pin_end_index = tile_port.absolute_first_pin_index + end_pin_index;
        if (abs(clb_to_clb_directs[i].from_clb_pin_start_index - clb_to_clb_directs[i].from_clb_pin_end_index) != abs(clb_to_clb_directs[i].to_clb_pin_start_index - clb_to_clb_directs[i].to_clb_pin_end_index)) {
            vpr_throw(VPR_ERROR_ARCH, get_arch_file_name(), directs[i].line,
                      "Range mismatch from %s to %s.\n", directs[i].from_pin, directs[i].to_pin);
        }
        if (directs[i].switch_type > 0) {
            clb_to_clb_directs[i].switch_index = directs[i].switch_type;
        } else {
            clb_to_clb_directs[i].switch_index = delayless_switch;
        }
        free(tile_name);
        free(port_name);
        free_blk_pin_from_port_pin();
    }
    return clb_to_clb_directs;
}
t_clb_to_clb_directs * alloc_and_load_clb_to_clb_directs ( const t_direct_inf * directs , const int num_directs , int delayless_switch ) { int i ; t_clb_to_clb_directs * clb_to_clb_directs ; char * tile_name , * port_name ; int start_pin_index , end_pin_index ; t_physical_tile_type_ptr physical_tile = nullptr ; t_physical_tile_port tile_port ; auto & device_ctx = g_vpr_ctx . device ( ) ; clb_to_clb_directs = ( t_clb_to_clb_directs * ) vtr :: calloc ( num_directs , sizeof ( t_clb_to_clb_directs ) ) ; tile_name = nullptr ; port_name = nullptr ; for ( i = 0 ; i < num_directs ; i ++ ) { tile_name = ( char * ) vtr :: malloc ( ( strlen ( directs [ i ] . from_pin ) + strlen ( directs [ i ] . to_pin ) ) * sizeof ( char ) ) ; port_name = ( char * ) vtr :: malloc ( ( strlen ( directs [ i ] . from_pin ) + strlen ( directs [ i ] . to_pin ) ) * sizeof ( char ) ) ; parse_direct_pin_name ( directs [ i ] . from_pin , directs [ i ] . line , & start_pin_index , & end_pin_index , tile_name , port_name ) ; for ( const auto & type : device_ctx . physical_tile_types ) { if ( strcmp ( type . name , tile_name ) == 0 ) { physical_tile = & type ; break ; } } if ( physical_tile == nullptr ) { VPR_THROW ( VPR_ERROR_ARCH , " \n " , tile_name ) ; } clb_to_clb_directs [ i ] . from_clb_type = physical_tile ; bool port_found = false ; for ( const auto & port : physical_tile -> ports ) { if ( 0 == strcmp ( port . name , port_name ) ) { tile_port = port ; port_found = true ; break ; } } if ( ! port_found ) { VPR_THROW ( VPR_ERROR_ARCH , " \n " , port_name , tile_name ) ; } if ( start_pin_index == OPEN ) { VTR_ASSERT ( start_pin_index == end_pin_index ) ; start_pin_index = 0 ; end_pin_index = tile_port . num_pins - 1 ; } clb_to_clb_directs [ i ] . from_clb_pin_start_index = tile_port . absolute_first_pin_index + start_pin_index ; clb_to_clb_directs [ i ] . from_clb_pin_end_index = tile_port . absolute_first_pin_index + end_pin_index ; parse_direct_pin_name ( directs [ i ] . to_pin , directs [ i ] . line , & start_pin_index , & end_pin_index , tile_name , port_name ) ; for ( const auto & type : device_ctx . physical_tile_types ) { if ( strcmp ( type . name , tile_name ) == 0 ) { physical_tile = & type ; break ; } } if ( physical_tile == nullptr ) { VPR_THROW ( VPR_ERROR_ARCH , " \n " , tile_name ) ; } clb_to_clb_directs [ i ] . to_clb_type = physical_tile ; port_found = false ; for ( const auto & port : physical_tile -> ports ) { if ( 0 == strcmp ( port . name , port_name ) ) { tile_port = port ; port_found = true ; break ; } } if ( ! port_found ) { VPR_THROW ( VPR_ERROR_ARCH , " \n " , port_name , tile_name ) ; } if ( start_pin_index == OPEN ) { VTR_ASSERT ( start_pin_index == end_pin_index ) ; start_pin_index = 0 ; end_pin_index = tile_port . num_pins - 1 ; } clb_to_clb_directs [ i ] . to_clb_pin_start_index = tile_port . absolute_first_pin_index + start_pin_index ; clb_to_clb_directs [ i ] . to_clb_pin_end_index = tile_port . absolute_first_pin_index + end_pin_index ; if ( abs ( clb_to_clb_directs [ i ] . from_clb_pin_start_index - clb_to_clb_directs [ i ] . from_clb_pin_end_index ) != abs ( clb_to_clb_directs [ i ] . to_clb_pin_start_index - clb_to_clb_directs [ i ] . to_clb_pin_end_index ) ) { vpr_throw ( VPR_ERROR_ARCH , get_arch_file_name ( ) , directs [ i ] . line , " \n " , directs [ i ] . from_pin , directs [ i ] . to_pin ) ; } if ( directs [ i ] . switch_type > 0 ) { clb_to_clb_directs [ i ] . switch_index = directs [ i ] . switch_type ; } else { clb_to_clb_directs [ i ] . switch_index = delayless_switch ; } free ( tile_name ) ; free ( port_name ) ; free_blk_pin_from_port_pin ( ) ; } return clb_to_clb_directs ; }
Parse out which CLB pins should connect directly to which other CLB pins then store that in a clb_to_clb_directs data structure
 This data structure supplements the the info in the "directs" data structure
 TODO: The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety, should replace with this one
Parse out which CLB pins should connect directly to which other CLB pins then store that in a clb_to_clb_directs data structure This data structure supplements the the info in the " directs " data structure TODO : The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety should replace with this one
// Load from pins // Parse out the pb_type name, port name, and pin range // Figure out which type, port, and pin is used // Add clb directs start/end pin indices based on the absolute pin position // of the port defined in the direct connection. The CLB is the source one. // Load to pins // Parse out the pb_type name, port name, and pin range // Figure out which type, port, and pin is used // Add clb directs start/end pin indices based on the absolute pin position // of the port defined in the direct connection. The CLB is the destination one. //Set the switch index //Use the specified switch //Use the delayless switch by default //We must be careful to clean-up anything that we may have incidentally allocated. //Specifically, we can be called while generating the dummy architecture //for placer delay estimation.  Since the delay estimation occurs on a //'different' architecture it is almost certain that the f_blk_pin_from_port_pin allocated //by calling get_blk_pin_from_port_pin() will later be invalid. //We therefore must free it now.