PAPI  5.0.1.0
ppc64_events.c File Reference
Include dependency graph for ppc64_events.c:

Go to the source code of this file.

Functions

void perfctr_initialize_native_table ()
void perfctr_ppc64_setup_gps (int total, ntv_event_group_info_t *group_info)
int perfctr_ppc64_setup_native_table ()
int check_native_name ()
static FILE * open_file (const char *fname)
static ntv_event_t * copy_buffer (ntv_event_t events[], int maxevents)
static ntv_event_info_t * parse_eventfile (FILE *evfile)
static int any_counter_invalid (int event_id[], int size)
static ntv_event_group_info_t * parse_groupfile (FILE *grp_file)
ntv_event_info_t * perfctr_get_native_evt_info (void)
ntv_event_group_info_t * perfctr_get_native_group_info (void)

Variables

hwd_groups_t group_map [MAX_GROUPS]
native_event_entry_t native_table [PAPI_MAX_NATIVE_EVENTS]

Function Documentation

static int any_counter_invalid ( int  event_id[],
int  size 
) [static]

Definition at line 395 of file ppc64_events.c.

{
    int j;
    for ( j = 0; j < size; j++ ) {
        if ( event_id[j] >= PAPI_MAX_NATIVE_EVENTS )
            return 1;
    }
    return 0;
}

Here is the caller graph for this function:

Definition at line 168 of file ppc64_events.c.

{
    enum native_name foo;
    int itemCount = 0;
    int i;

    /* This should ensure that the cardinality of native_name is the same
       as that of native_name_map which may be true iff native_name 
       expresses the same data as native_name_map and there is a 1:1 
       mapping from one onto the other, though there is no guarantee of 
       order. */
    if ( ( NATNAME_GUARD - PAPI_NATIVE_MASK ) != MAX_NATNAME_MAP_INDEX ) {
        SUBDBG( "%i is the number of elements apparently in native_name, "
                "but really should be %i, according to native_name_map.\n",
                ( NATNAME_GUARD - PAPI_NATIVE_MASK ), MAX_NATNAME_MAP_INDEX );
        PAPIERROR
            ( "Inconsistent cardinality between native_name and native_name_map "
              "detected in preliminary check\n" );
        return PAPI_EBUG;
    }

    /* The following is sanity checking only.  It attempts to verify some level
       of consistency between native_name and native_name_map and native_table.
       This should imply that native_name is a subset of native_name_map. */
    for ( foo = PAPI_NATIVE_MASK; foo < NATNAME_GUARD; foo++ ) {
        for ( i = 0; i < MAX_NATNAME_MAP_INDEX; i++ ) {
            /* Now, if the event we are on is the native event we seek... */
            if ( ( native_name_map[i].index | PAPI_NATIVE_MASK ) == foo ) {
                itemCount++;
                break;
            }
        }
    }
    if ( itemCount != MAX_NATNAME_MAP_INDEX ) {
        SUBDBG( "Inconsistency between native_name_map and native_name.  "
                "%i events matched, but really should be %i\n", itemCount,
                MAX_NATNAME_MAP_INDEX );
        PAPIERROR
            ( "Inconsistent cardinality between native_name and native_name_map\n" );
        return PAPI_EBUG;
    }

    return PAPI_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static ntv_event_t* copy_buffer ( ntv_event_t  events[],
int  maxevents 
) [static]

Definition at line 279 of file ppc64_events.c.

{
    ntv_event_t *cur_wev, *start_wev;
    start_wev = ( ntv_event_t * ) malloc( sizeof ( ntv_event_t ) * maxevents );
    cur_wev = start_wev;

    int cnt;
    for ( cnt = 0; cnt < maxevents; cnt++, cur_wev++ ) {
        cur_wev->event_num = events[cnt].event_num;
        strcpy( cur_wev->symbol, events[cnt].symbol );
        cur_wev->short_description =
            ( char * ) malloc( strlen( events[cnt].short_description ) );
        strcpy( cur_wev->short_description, events[cnt].short_description );
        cur_wev->description =
            ( char * ) malloc( strlen( events[cnt].description ) );
        strcpy( cur_wev->description, events[cnt].description );
    }
    return start_wev;
}

Here is the caller graph for this function:

static FILE* open_file ( const char *  fname) [static]

Definition at line 214 of file ppc64_events.c.

{
    char *cpu;
    char *dot = ".";
    char *dot_dot = "..";
#ifdef _POWER5p
    cpu = "power5+";
#elif defined(_POWER5)
    cpu = "power5";
#elif defined(_PPC970)
    cpu = "ppc970";
#else
    cpu = "";
#endif
    char *dir = ( char * ) getenv( "PAPI_EVENTFILE_PATH" );
#ifdef PAPI_DATADIR
    if ( dir == NULL ) {
        dir = PAPI_DATADIR;
    }
#endif
    /* If dir is still NULL, assume current dir holds event_data dir */
    if ( dir == NULL )
        dir = dot;

    char *relative_pathname = ( char * ) malloc( strlen( "/" ) +
                                                 strlen( "event_data" ) +
                                                 strlen( "/" ) + strlen( cpu ) +
                                                 strlen( "/" ) +
                                                 strlen( fname ) + 1 );
    strcpy( relative_pathname, "/" );
    strcat( relative_pathname, "event_data" );
    strcat( relative_pathname, "/" );
    strcat( relative_pathname, cpu );
    strcat( relative_pathname, "/" );
    strcat( relative_pathname, fname );
    /* Add a little extra space to the malloc for the case where dir = "." since
     * we may be trying dir = ".." later on. */
    char *pathname =
        ( char * ) malloc( strlen( dir ) + strlen( relative_pathname ) + 4 );
    int keep_trying;
    if ( strcmp( dir, dot ) == 0 )
        keep_trying = 2;
    else
        keep_trying = 3;
    FILE *file = NULL;
    while ( file == NULL && keep_trying-- ) {
        strcpy( pathname, dir );
        strcat( pathname, relative_pathname );
        file = fopen( pathname, "r" );
        if ( strcmp( dir, dot ) == 0 ) {
            dir = dot_dot;
        } else {
            dir = dot;
        }
        SUBDBG( "Attempt to open event data file %s %s successful.\n", pathname,
                ( file == NULL ) ? "was not" : "was" );
        memset( pathname, '\0', sizeof ( pathname ) );
    }

    free( pathname );
    free( relative_pathname );
    return ( file );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static ntv_event_info_t* parse_eventfile ( FILE *  evfile) [static]

Definition at line 300 of file ppc64_events.c.

{
    int counter = 0, num_events = 0;
    int i, len, cc;
    int event;
    int line_counter_flag = 0;
    char line_data[1024];
    ntv_event_t events[PAPI_MAX_NATIVE_EVENTS];
    ntv_event_info_t *ntv_evt_info =
        ( ntv_event_info_t * ) malloc( sizeof ( ntv_event_info_t ) );
    ntv_evt_info->maxpmcs = 0;
    char data[1024];
    while ( fgets( data, 1022, evfile ) ) {
        if ( feof( evfile ) )
            continue;
        if ( strlen( data ) < 2 )
            continue;

        if ( strncmp( data, "$$$$", 4 ) == 0 ) {
            line_counter_flag = 0;
            ntv_evt_info->maxevents[counter - 1] = num_events;
            ntv_evt_info->wev[counter - 1] = copy_buffer( events, num_events );
            ntv_event_t *temp = ntv_evt_info->wev[counter - 1];
            temp++;
        }
        switch ( line_counter_flag ) {
        case 0:
            if ( sscanf( data, "{ counter %u", &counter ) == 1 ) {
                line_counter_flag = 1;
                num_events = 0;
                ntv_evt_info->maxpmcs++;
            }
            break;
        case 1:
            if ( sscanf( data, "#%u", &event ) != 1 ) {
                fprintf( stderr, "EVS file format error 1 (%s)\n", data );
                return NULL;
            }
            if ( event >= PAPI_MAX_NATIVE_EVENTS ) {
                fprintf( stderr, "EVS file format error 1 (%s)\n", data );
                return NULL;
            }
            events[num_events].event_num = event;
            len = strlen( data );
            int symb_found = 0;
            for ( i = cc = 0; i < len; i++ ) {
                if ( data[i] == ',' )
                    cc++;
                if ( cc == 5 && !symb_found ) {
                    strcpy( line_data, &data[i + 1] );
                    int j = 0;
                    while ( line_data[j] != ',' )
                        j++;
                    strncpy( events[num_events].symbol, line_data, j );
                    events[num_events].symbol[j] = 0;
                    symb_found = 1;
                    i += j;
                } else if ( cc == 6 ) {
                    len = strlen( &data[i + 1] );
                    events[num_events].short_description =
                        ( char * ) malloc( len );
                    strcpy( events[num_events].short_description,
                            &data[i + 1] );
                    events[num_events].short_description[len - 1] = 0;
                    break;
                }
            }
            line_counter_flag = 2;
            break;
        case 2:
            line_counter_flag = 3;
            break;
        case 3:
            len = strlen( data );
            events[num_events].description = ( char * ) malloc( len );
            strcpy( events[num_events].description, data );
            events[num_events].description[len - 1] = 0;
            line_counter_flag = 1;
            num_events++;
            break;
        }
    }
    if ( counter == 0 ) {
        free( ntv_evt_info );
        ntv_evt_info = NULL;
    }
    if ( counter == MAX_COUNTERS ) {
        ntv_evt_info->maxevents[counter - 1] = num_events;
        ntv_evt_info->wev[counter - 1] = copy_buffer( events, num_events );
    }
    fclose( evfile );
    return ntv_evt_info;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static ntv_event_group_info_t* parse_groupfile ( FILE *  grp_file) [static]

Definition at line 406 of file ppc64_events.c.

{
    char data[1024];
    unsigned int mmcr0, mmcr1H, mmcr1L, mmcra;
    int g, state = 0;
    ntv_event_group_info_t *group_info =
        ( ntv_event_group_info_t * )
        malloc( sizeof ( ntv_event_group_info_t ) );
    group_info->maxgroups = 0;
    int event_num[MAX_COUNTERS];
    while ( fgets( data, 1022, grp_file ) ) {
        if ( feof( grp_file ) || ( strlen( data ) < 2 ) )
            continue;

        switch ( state ) {
        case 0:
#if defined(_POWER5) || defined(_POWER5p)
            if ( sscanf
                 ( data, "#%u,%u,%u,%u,%u,%u,%u", &g, &event_num[0],
                   &event_num[1], &event_num[2], &event_num[3], &event_num[4],
                   &event_num[5] ) == 7 ) {
                state = 1;
                if ( any_counter_invalid( event_num, 6 ) ) {
                    fprintf( stderr, "ERROR: Maximum events exceeded\n" );
                    return NULL;
                }
            }
#else
            if ( sscanf
                 ( data, "#%u,%u,%u,%u,%u,%u,%u,%u,%u", &g, &event_num[0],
                   &event_num[1], &event_num[2], &event_num[3], &event_num[4],
                   &event_num[5], &event_num[6], &event_num[7] ) == 9 ) {
                state = 1;
                if ( any_counter_invalid( event_num, 8 ) ) {
                    fprintf( stderr, "ERROR: Maximum events exceeded\n" );
                    return NULL;
                }
            }
#endif
            if ( state == 1 ) {
                group_info->event_groups[group_info->maxgroups] =
                    ( event_group_t * ) malloc( sizeof ( event_group_t ) );
                group_info->event_groups[group_info->maxgroups]->group_id = g;
                int j = 0;
                for ( ; j < MAX_COUNTERS; j++ )
                    group_info->event_groups[group_info->maxgroups]->events[j] =
                        event_num[j];
            }
            break;
        case 1:
            // unused hex event codes
            state = 2;
            break;
        case 2:
            /* get mmcr values */
            if ( sscanf( data, "%x,%x,%x,%x", &mmcr0, &mmcr1H, &mmcr1L, &mmcra )
                 != 4 ) {
                fprintf( stderr, "GPS file format error 1 (%s)\n", data );
                return NULL;
            }
            state = 3;
            group_info->event_groups[group_info->maxgroups]->mmcr0 = mmcr0;
            group_info->event_groups[group_info->maxgroups]->mmcr1L = mmcr1L;
            group_info->event_groups[group_info->maxgroups]->mmcr1U = mmcr1H;
            group_info->event_groups[group_info->maxgroups]->mmcra = mmcra;
            group_info->maxgroups++;
            break;
        case 3:
            // unused group name
            state = 0;
        }
    }
    fclose( grp_file );
    return group_info;
}

Here is the call graph for this function:

Here is the caller graph for this function:

ntv_event_info_t* perfctr_get_native_evt_info ( void  )

Definition at line 483 of file ppc64_events.c.

{
    ntv_event_info_t *evt_info = NULL;
    FILE *evt_file = open_file( "events" );
    if ( evt_file != NULL ) {
        evt_info = parse_eventfile( evt_file );
    }
    return evt_info;

}

Here is the call graph for this function:

Here is the caller graph for this function:

ntv_event_group_info_t* perfctr_get_native_group_info ( void  )

Definition at line 495 of file ppc64_events.c.

{
    ntv_event_group_info_t *groups = NULL;
    FILE *grp_file = NULL;
    if ( ( grp_file = open_file( "groups" ) ) != NULL ) {
        groups = parse_groupfile( grp_file );
    }
    return groups;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 27 of file ppc64_events.c.

{
    int i, j;
    memset( native_table, 0,
            PAPI_MAX_NATIVE_EVENTS * sizeof ( native_event_entry_t ) );
    for ( i = 0; i < PAPI_MAX_NATIVE_EVENTS; i++ ) {
        for ( j = 0; j < MAX_COUNTERS; j++ )
            native_table[i].resources.counter_cmd[j] = -1;
    }
}

Here is the caller graph for this function:

void perfctr_ppc64_setup_gps ( int  total,
ntv_event_group_info_t *  group_info 
)

Definition at line 41 of file ppc64_events.c.

{
    int i, j, gnum;

    for ( i = 0; i < total; i++ ) {
        for ( j = 0; j < MAX_COUNTERS; j++ ) {
            if ( native_table[i].resources.selector & ( 1 << j ) ) {
                for ( gnum = 0; gnum < group_info->maxgroups; gnum++ ) {
                    if ( native_table[i].resources.counter_cmd[j] ==
                         group_info->event_groups[gnum]->events[j] ) {
                        native_table[i].resources.group[gnum / 32] |=
                            1 << ( gnum % 32 );
                    }
                }
            }
        }
    }

    for ( gnum = 0; gnum < group_info->maxgroups; gnum++ ) {
        group_map[gnum].mmcr0 = group_info->event_groups[gnum]->mmcr0;
        group_map[gnum].mmcr1L = group_info->event_groups[gnum]->mmcr1L;
        group_map[gnum].mmcr1U = group_info->event_groups[gnum]->mmcr1U;
        group_map[gnum].mmcra = group_info->event_groups[gnum]->mmcra;
        for ( i = 0; i < MAX_COUNTERS; i++ )
            group_map[gnum].counter_cmd[i] =
                group_info->event_groups[gnum]->events[i];
    }
}

Here is the caller graph for this function:

Definition at line 73 of file ppc64_events.c.

{
    int pmc, ev, i, j, index;
    /* This is for initialisation-testing of consistency between
       native_name_map and our events file */
    int itemCount = 0;
    index = 0;
    perfctr_initialize_native_table(  );
    ntv_event_info_t *info = perfctr_get_native_evt_info(  );
    if ( info == NULL ) {
        PAPIERROR( EVENT_INFO_FILE_ERROR );
        return PAPI_ECMP;
    }
    ntv_event_t *wevp;
    for ( pmc = 0; pmc < info->maxpmcs; pmc++ ) {
        wevp = info->wev[pmc];
        for ( ev = 0; ev < info->maxevents[pmc]; ev++, wevp++ ) {
            for ( i = 0; i < index; i++ ) {
                if ( strcmp( wevp->symbol, native_table[i].name ) == 0 ) {
                    native_table[i].resources.selector |= 1 << pmc;
                    native_table[i].resources.counter_cmd[pmc] =
                        wevp->event_num;
                    break;
                }
            }
            if ( i == index ) {
                //native_table[i].index=i; 
                native_table[i].resources.selector |= 1 << pmc;
                native_table[i].resources.counter_cmd[pmc] = wevp->event_num;
                native_table[i].name =
                    ( char * ) malloc( strlen( wevp->symbol ) + 1 );
                strcpy( native_table[i].name, wevp->symbol );
                native_table[i].description = wevp->description;
                index++;
                for ( j = 0; j < MAX_NATNAME_MAP_INDEX; j++ ) {
                    /* It appears that here, if I'm right, that the events
                       file entry matches the event from native_name_map, */
                    /* This here check is to ensure that native_name_map in fact
                       has MAX_NATNAME_MAP_INDEX elements, or rather that it never
                       tries to access one that has not been initialised. */
                    if ( native_name_map[j].name == NULL ) {
                        SUBDBG( "native_name_map has a NULL at position %i\n",
                                j );
                        PAPIERROR
                            ( "Inconsistency between events_map file and events header." );
                        return PAPI_EBUG;
                    }
                    if ( strcmp( native_table[i].name, native_name_map[j].name )
                         == 0 ) {
                        native_name_map[j].index = i;
                        itemCount++;
                        break;
                    }
                }
                /* If we never set native_name_map[j], then there is an
                   inconsistency between native_name_map and native_table */
                if ( ( !( j < MAX_NATNAME_MAP_INDEX ) ) ||
                     native_name_map[j].index != i ) {
                    SUBDBG
                        ( "No match found between native_name_map and native_table.  "
                          "Values was %s at position %i in native_table.\n",
                          native_table[i].name, i );
                    PAPIERROR
                        ( "Inconsistency between native_name_map and events file." );
                    return PAPI_EBUG;
                }
            }
        }
    }
    /* given the previous evidence that native_name_map is a superset of
       native_table, ensuring this match in their cardinality shows them to
       be equivalent. */
    if ( itemCount != MAX_NATNAME_MAP_INDEX ) {
        SUBDBG( "%i events found in native_table, but really should be %i\n",
                itemCount, MAX_NATNAME_MAP_INDEX );
        PAPIERROR
            ( "Inconsistent cardinality between native_name_map and events file",
              itemCount, MAX_NATNAME_MAP_INDEX );
        return PAPI_EBUG;
    }

    ntv_event_group_info_t *gp_info = perfctr_get_native_group_info(  );
    if ( gp_info == NULL ) {
        perfctr_initialize_native_table(  );
        PAPIERROR( EVENT_INFO_FILE_ERROR );
        return PAPI_ECMP;
    }

    perfctr_ppc64_setup_gps( index, gp_info );
    _papi_hwi_system_info.sub_info.num_native_events = index;

    return check_native_name(  );
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Initial value:
 { {0}
, {0}
, {0}
, {0}
, {0}
}

Definition at line 17 of file ppc64_events.c.

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines