|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* File: papi_preset.c
|
|
Packit Service |
a1973e |
* Author: Haihang You
|
|
Packit Service |
a1973e |
* you@cs.utk.edu
|
|
Packit Service |
a1973e |
* Mods: Brian Sheely
|
|
Packit Service |
a1973e |
* bsheely@eecs.utk.edu
|
|
Packit Service |
a1973e |
* Author: Vince Weaver
|
|
Packit Service |
a1973e |
* vweaver1 @ eecs.utk.edu
|
|
Packit Service |
a1973e |
* Merge of the libpfm3/libpfm4/pmapi-ppc64_events preset code
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include <string.h>
|
|
Packit Service |
a1973e |
#include <ctype.h>
|
|
Packit Service |
a1973e |
#include <errno.h>
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "papi.h"
|
|
Packit Service |
a1973e |
#include "papi_internal.h"
|
|
Packit Service |
a1973e |
#include "papi_vector.h"
|
|
Packit Service |
a1973e |
#include "papi_memory.h"
|
|
Packit Service |
a1973e |
#include "papi_preset.h"
|
|
Packit Service |
a1973e |
#include "extras.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// A place to put user defined events
|
|
Packit Service |
a1973e |
extern hwi_presets_t user_defined_events[];
|
|
Packit Service |
a1973e |
extern int user_defined_events_count;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int papi_load_derived_events (char *pmu_str, int pmu_type, int cidx, int preset_flag);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This routine copies values from a dense 'findem' array of events
|
|
Packit Service |
a1973e |
into the sparse global _papi_hwi_presets array, which is assumed
|
|
Packit Service |
a1973e |
to be empty at initialization.
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
Multiple dense arrays can be copied into the sparse array, allowing
|
|
Packit Service |
a1973e |
event overloading at run-time, or allowing a baseline table to be
|
|
Packit Service |
a1973e |
augmented by a model specific table at init time.
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
This method supports adding new events; overriding existing events, or
|
|
Packit Service |
a1973e |
deleting deprecated events.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_setup_all_presets( hwi_search_t * findem, int cidx )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int i, pnum, did_something = 0;
|
|
Packit Service |
a1973e |
unsigned int preset_index, j, k;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* dense array of events is terminated with a 0 preset.
|
|
Packit Service |
a1973e |
don't do anything if NULL pointer. This allows just notes to be loaded.
|
|
Packit Service |
a1973e |
It's also good defensive programming.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
if ( findem != NULL ) {
|
|
Packit Service |
a1973e |
for ( pnum = 0; ( pnum < PAPI_MAX_PRESET_EVENTS ) &&
|
|
Packit Service |
a1973e |
( findem[pnum].event_code != 0 ); pnum++ ) {
|
|
Packit Service |
a1973e |
/* find the index for the event to be initialized */
|
|
Packit Service |
a1973e |
preset_index = ( findem[pnum].event_code & PAPI_PRESET_AND_MASK );
|
|
Packit Service |
a1973e |
/* count and set the number of native terms in this event,
|
|
Packit Service |
a1973e |
these items are contiguous.
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
PAPI_EVENTS_IN_DERIVED_EVENT is arbitrarily defined in the high
|
|
Packit Service |
a1973e |
level to be a reasonable number of terms to use in a derived
|
|
Packit Service |
a1973e |
event linear expression, currently 8.
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
This wastes space for components with less than 8 counters,
|
|
Packit Service |
a1973e |
but keeps the framework independent of the components.
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
The 'native' field below is an arbitrary opaque identifier
|
|
Packit Service |
a1973e |
that points to information on an actual native event.
|
|
Packit Service |
a1973e |
It is not an event code itself (whatever that might mean).
|
|
Packit Service |
a1973e |
By definition, this value can never == PAPI_NULL.
|
|
Packit Service |
a1973e |
- dkt */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG( "Counting number of terms for preset index %d, "
|
|
Packit Service |
a1973e |
"search map index %d.\n", preset_index, pnum );
|
|
Packit Service |
a1973e |
i = 0;
|
|
Packit Service |
a1973e |
j = 0;
|
|
Packit Service |
a1973e |
while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
|
|
Packit Service |
a1973e |
if ( findem[pnum].native[i] != PAPI_NULL ) {
|
|
Packit Service |
a1973e |
j++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
else if ( j ) {
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
i++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG( "This preset has %d terms.\n", j );
|
|
Packit Service |
a1973e |
_papi_hwi_presets[preset_index].count = j;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwi_presets[preset_index].derived_int = findem[pnum].derived;
|
|
Packit Service |
a1973e |
for(k=0;k
|
|
Packit Service |
a1973e |
_papi_hwi_presets[preset_index].code[k] =
|
|
Packit Service |
a1973e |
findem[pnum].native[k];
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* preset code list must be PAPI_NULL terminated */
|
|
Packit Service |
a1973e |
if (k
|
|
Packit Service |
a1973e |
_papi_hwi_presets[preset_index].code[k] = PAPI_NULL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwi_presets[preset_index].postfix=
|
|
Packit Service |
a1973e |
papi_strdup(findem[pnum].operation);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
did_something++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwd[cidx]->cmp_info.num_preset_events += did_something;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( did_something ? PAPI_OK : PAPI_ENOEVNT );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_cleanup_all_presets( void )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int preset_index,cidx;
|
|
Packit Service |
a1973e |
unsigned int j;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( preset_index = 0; preset_index < PAPI_MAX_PRESET_EVENTS;
|
|
Packit Service |
a1973e |
preset_index++ ) {
|
|
Packit Service |
a1973e |
if ( _papi_hwi_presets[preset_index].postfix != NULL ) {
|
|
Packit Service |
a1973e |
papi_free( _papi_hwi_presets[preset_index].postfix );
|
|
Packit Service |
a1973e |
_papi_hwi_presets[preset_index].postfix = NULL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( _papi_hwi_presets[preset_index].note != NULL ) {
|
|
Packit Service |
a1973e |
papi_free( _papi_hwi_presets[preset_index].note );
|
|
Packit Service |
a1973e |
_papi_hwi_presets[preset_index].note = NULL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
for(j=0; j<_papi_hwi_presets[preset_index].count;j++) {
|
|
Packit Service |
a1973e |
papi_free(_papi_hwi_presets[preset_index].name[j]);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for(cidx=0;cidx
|
|
Packit Service |
a1973e |
_papi_hwd[cidx]->cmp_info.num_preset_events = 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if defined(ITANIUM2) || defined(ITANIUM3)
|
|
Packit Service |
a1973e |
/* NOTE: This memory may need to be freed for BG/P builds as well */
|
|
Packit Service |
a1973e |
if ( preset_search_map != NULL ) {
|
|
Packit Service |
a1973e |
papi_free( preset_search_map );
|
|
Packit Service |
a1973e |
preset_search_map = NULL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#define PAPI_EVENT_FILE "papi_events.csv"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Trims blank space from both ends of a string (in place).
|
|
Packit Service |
a1973e |
Returns pointer to new start address */
|
|
Packit Service |
a1973e |
static inline char *
|
|
Packit Service |
a1973e |
trim_string( char *in )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int len, i = 0;
|
|
Packit Service |
a1973e |
char *start = in;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( in == NULL )
|
|
Packit Service |
a1973e |
return ( in );
|
|
Packit Service |
a1973e |
len = ( int ) strlen( in );
|
|
Packit Service |
a1973e |
if ( len == 0 )
|
|
Packit Service |
a1973e |
return ( in );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Trim left */
|
|
Packit Service |
a1973e |
while ( i < len ) {
|
|
Packit Service |
a1973e |
if ( isblank( in[i] ) ) {
|
|
Packit Service |
a1973e |
in[i] = '\0';
|
|
Packit Service |
a1973e |
start++;
|
|
Packit Service |
a1973e |
} else
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
i++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Trim right */
|
|
Packit Service |
a1973e |
i = ( int ) strlen( start ) - 1;
|
|
Packit Service |
a1973e |
while ( i >= 0 ) {
|
|
Packit Service |
a1973e |
if ( isblank( start[i] ) )
|
|
Packit Service |
a1973e |
start[i] = '\0';
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
i--;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( start );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Calls trim_string to remove blank space;
|
|
Packit Service |
a1973e |
Removes paired punctuation delimiters from
|
|
Packit Service |
a1973e |
beginning and end of string. If the same punctuation
|
|
Packit Service |
a1973e |
appears first and last (quotes, slashes) they are trimmed;
|
|
Packit Service |
a1973e |
Also checks for the following pairs: () <> {} [] */
|
|
Packit Service |
a1973e |
static inline char *
|
|
Packit Service |
a1973e |
trim_note( char *in )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int len;
|
|
Packit Service |
a1973e |
char *note, start, end;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
note = trim_string( in );
|
|
Packit Service |
a1973e |
if ( note != NULL ) {
|
|
Packit Service |
a1973e |
len = ( int ) strlen( note );
|
|
Packit Service |
a1973e |
if ( len > 0 ) {
|
|
Packit Service |
a1973e |
if ( ispunct( *note ) ) {
|
|
Packit Service |
a1973e |
start = *note;
|
|
Packit Service |
a1973e |
end = note[len - 1];
|
|
Packit Service |
a1973e |
if ( ( start == end )
|
|
Packit Service |
a1973e |
|| ( ( start == '(' ) && ( end == ')' ) )
|
|
Packit Service |
a1973e |
|| ( ( start == '<' ) && ( end == '>' ) )
|
|
Packit Service |
a1973e |
|| ( ( start == '{' ) && ( end == '}' ) )
|
|
Packit Service |
a1973e |
|| ( ( start == '[' ) && ( end == ']' ) ) ) {
|
|
Packit Service |
a1973e |
note[len - 1] = '\0';
|
|
Packit Service |
a1973e |
*note = '\0';
|
|
Packit Service |
a1973e |
note++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return note;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
find_event_index(hwi_presets_t *array, int size, char *tmp) {
|
|
Packit Service |
a1973e |
SUBDBG("ENTER: array: %p, size: %d, tmp: %s\n", array, size, tmp);
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
for (i = 0; i < size; i++) {
|
|
Packit Service |
a1973e |
if (array[i].symbol == NULL) {
|
|
Packit Service |
a1973e |
array[i].symbol = papi_strdup(tmp);
|
|
Packit Service |
a1973e |
SUBDBG("EXIT: i: %d\n", i);
|
|
Packit Service |
a1973e |
return i;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (strcasecmp(tmp, array[i].symbol) == 0) {
|
|
Packit Service |
a1973e |
SUBDBG("EXIT: i: %d\n", i);
|
|
Packit Service |
a1973e |
return i;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG("EXIT: PAPI_EINVAL\n");
|
|
Packit Service |
a1973e |
return PAPI_EINVAL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Look for an event file 'name' in a couple common locations.
|
|
Packit Service |
a1973e |
Return a valid file handle if found */
|
|
Packit Service |
a1973e |
static FILE *
|
|
Packit Service |
a1973e |
open_event_table( char *name )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
FILE *table;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "Opening %s\n", name );
|
|
Packit Service |
a1973e |
table = fopen( name, "r" );
|
|
Packit Service |
a1973e |
if ( table == NULL ) {
|
|
Packit Service |
a1973e |
SUBDBG( "Open %s failed, trying ./%s.\n",
|
|
Packit Service |
a1973e |
name, PAPI_EVENT_FILE );
|
|
Packit Service |
a1973e |
sprintf( name, "%s", PAPI_EVENT_FILE );
|
|
Packit Service |
a1973e |
table = fopen( name, "r" );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( table == NULL ) {
|
|
Packit Service |
a1973e |
SUBDBG( "Open ./%s failed, trying ../%s.\n",
|
|
Packit Service |
a1973e |
name, PAPI_EVENT_FILE );
|
|
Packit Service |
a1973e |
sprintf( name, "../%s", PAPI_EVENT_FILE );
|
|
Packit Service |
a1973e |
table = fopen( name, "r" );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( table ) {
|
|
Packit Service |
a1973e |
SUBDBG( "Open %s succeeded.\n", name );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return table;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* parse a single line from either a file or character table
|
|
Packit Service |
a1973e |
Strip trailing <cr>; return 0 if empty */
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
get_event_line( char *line, FILE * table, char **tmp_perfmon_events_table )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( table ) {
|
|
Packit Service |
a1973e |
if ( fgets( line, LINE_MAX, table ) == NULL)
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
i = ( int ) strlen( line );
|
|
Packit Service |
a1973e |
if (i == 0)
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
if ( line[i-1] == '\n' )
|
|
Packit Service |
a1973e |
line[i-1] = '\0';
|
|
Packit Service |
a1973e |
return 1;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
for ( i = 0;
|
|
Packit Service |
a1973e |
**tmp_perfmon_events_table && **tmp_perfmon_events_table != '\n';
|
|
Packit Service |
a1973e |
i++, ( *tmp_perfmon_events_table )++ )
|
|
Packit Service |
a1973e |
line[i] = **tmp_perfmon_events_table;
|
|
Packit Service |
a1973e |
if (i == 0)
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
if ( **tmp_perfmon_events_table && **tmp_perfmon_events_table == '\n' ) {
|
|
Packit Service |
a1973e |
( *tmp_perfmon_events_table )++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
line[i] = '\0';
|
|
Packit Service |
a1973e |
return 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// update tokens in formula referring to index "old_index" with tokens referring to index "new_index".
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
update_ops_string(char **formula, int old_index, int new_index) {
|
|
Packit Service |
a1973e |
INTDBG("ENTER: *formula: %s, old_index: %d, new_index: %d\n", *formula?*formula:"NULL", old_index, new_index);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int cur_index;
|
|
Packit Service |
a1973e |
char *newFormula;
|
|
Packit Service |
a1973e |
char *subtoken;
|
|
Packit Service |
a1973e |
char *tok_save_ptr=NULL;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if formula is null just return
|
|
Packit Service |
a1973e |
if (*formula == NULL) {
|
|
Packit Service |
a1973e |
INTDBG("EXIT: Null pointer to formula passed in\n");
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// get some space for the new formula we are going to create
|
|
Packit Service |
a1973e |
newFormula = papi_calloc(strlen(*formula) + 20, 1);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// replace the specified "replace" tokens in the new original formula with the new insertion formula
|
|
Packit Service |
a1973e |
newFormula[0] = '\0';
|
|
Packit Service |
a1973e |
subtoken = strtok_r(*formula, "|", &tok_save_ptr);
|
|
Packit Service |
a1973e |
while ( subtoken != NULL) {
|
|
Packit Service |
a1973e |
// INTDBG("subtoken: %s, newFormula: %s\n", subtoken, newFormula);
|
|
Packit Service |
a1973e |
char work[10];
|
|
Packit Service |
a1973e |
// if this is the token we want to replace with the new token index, do it now
|
|
Packit Service |
a1973e |
if ((subtoken[0] == 'N') && (isdigit(subtoken[1]))) {
|
|
Packit Service |
a1973e |
cur_index = atoi(&subtoken[1]);
|
|
Packit Service |
a1973e |
// if matches old index, use the new one
|
|
Packit Service |
a1973e |
if (cur_index == old_index) {
|
|
Packit Service |
a1973e |
sprintf (work, "N%d", new_index);
|
|
Packit Service |
a1973e |
strcat (newFormula, work);
|
|
Packit Service |
a1973e |
} else if (cur_index > old_index) {
|
|
Packit Service |
a1973e |
// current token greater than old index, make it one less than what it was
|
|
Packit Service |
a1973e |
sprintf (work, "N%d", cur_index-1);
|
|
Packit Service |
a1973e |
strcat (newFormula, work);
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
// current token less than old index, copy this part of the original formula into the new formula
|
|
Packit Service |
a1973e |
strcat(newFormula, subtoken);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
// copy this part of the original formula into the new formula
|
|
Packit Service |
a1973e |
strcat(newFormula, subtoken);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
strcat (newFormula, "|");
|
|
Packit Service |
a1973e |
subtoken = strtok_r(NULL, "|", &tok_save_ptr);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
papi_free (*formula);
|
|
Packit Service |
a1973e |
*formula = newFormula;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG("EXIT: newFormula: %s\n", newFormula);
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
//
|
|
Packit Service |
a1973e |
// Handle creating a new derived event of type DERIVED_ADD. This may create a new formula
|
|
Packit Service |
a1973e |
// which can be used to compute the results of the new event from the events it depends on.
|
|
Packit Service |
a1973e |
// This code is also responsible for making sure that all the needed native events are in the
|
|
Packit Service |
a1973e |
// new events native event list and that the formula's referenced to this array are correct.
|
|
Packit Service |
a1973e |
//
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
ops_string_append(hwi_presets_t *results, hwi_presets_t *depends_on, int addition) {
|
|
Packit Service |
a1973e |
INTDBG("ENTER: results: %p, depends_on: %p, addition %d\n", results, depends_on, addition);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
int second_event = 0;
|
|
Packit Service |
a1973e |
char newFormula[PAPI_MIN_STR_LEN] = "";
|
|
Packit Service |
a1973e |
char work[20];
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if our results already have a formula, start with what was collected so far
|
|
Packit Service |
a1973e |
// this should only happens when processing the second event of a new derived add
|
|
Packit Service |
a1973e |
if (results->postfix != NULL) {
|
|
Packit Service |
a1973e |
INTDBG("Event %s has existing formula %s\n", results->symbol, results->postfix);
|
|
Packit Service |
a1973e |
// get the existing formula
|
|
Packit Service |
a1973e |
strncat(newFormula, results->postfix, sizeof(newFormula)-1);
|
|
Packit Service |
a1973e |
newFormula[sizeof(newFormula)-1] = '\0';
|
|
Packit Service |
a1973e |
second_event = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// process based on what kind of event the one we depend on is
|
|
Packit Service |
a1973e |
switch (depends_on->derived_int) {
|
|
Packit Service |
a1973e |
case DERIVED_POSTFIX: {
|
|
Packit Service |
a1973e |
// the event we depend on has a formula, append it our new events formula
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if event we depend on does not have a formula, report error
|
|
Packit Service |
a1973e |
if (depends_on->postfix == NULL) {
|
|
Packit Service |
a1973e |
INTDBG("Event %s is of type DERIVED_POSTFIX but is missing operation string\n", depends_on->symbol);
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// may need to renumber the native event index values in the depends on event formula before putting it into new derived event
|
|
Packit Service |
a1973e |
char *temp = papi_strdup(depends_on->postfix);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// If this is not the first event of the new derived add, need to adjust native event index values in formula.
|
|
Packit Service |
a1973e |
// At this time we assume that all the native events in the second events formula are unique for the new event
|
|
Packit Service |
a1973e |
// and just bump the indexes by the number of events already known to the new event. Later when we add the events
|
|
Packit Service |
a1973e |
// to the native event list for this new derived event, we will check to see if the native events are already known
|
|
Packit Service |
a1973e |
// to the new derived event and if so adjust the indexes again.
|
|
Packit Service |
a1973e |
if (second_event) {
|
|
Packit Service |
a1973e |
for ( i=depends_on->count-1 ; i>=0 ; i--) {
|
|
Packit Service |
a1973e |
update_ops_string(&temp, i, results->count + i);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// append the existing formula from the event we depend on (but get rid of last '|' character)
|
|
Packit Service |
a1973e |
strncat(newFormula, temp, sizeof(newFormula)-1);
|
|
Packit Service |
a1973e |
newFormula[sizeof(newFormula)-1] = '\0';
|
|
Packit Service |
a1973e |
papi_free (temp);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
case DERIVED_ADD: {
|
|
Packit Service |
a1973e |
// the event we depend on has no formula, create a formula for our new event to add together the depends_on native event values
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// build a formula for this add event
|
|
Packit Service |
a1973e |
sprintf(work, "N%d|N%d|+|", results->count, results->count + 1);
|
|
Packit Service |
a1973e |
strcat(newFormula, work);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
case DERIVED_SUB: {
|
|
Packit Service |
a1973e |
// the event we depend on has no formula, create a formula for our new event to subtract the depends_on native event values
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// build a formula for this subtract event
|
|
Packit Service |
a1973e |
sprintf(work, "N%d|N%d|-|", results->count, results->count + 1);
|
|
Packit Service |
a1973e |
strcat(newFormula, work);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
case NOT_DERIVED: {
|
|
Packit Service |
a1973e |
// the event we depend on has no formula and is itself only based on one native event, create a formula for our new event to include this native event
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// build a formula for this subtract event
|
|
Packit Service |
a1973e |
sprintf(work, "N%d|", results->count);
|
|
Packit Service |
a1973e |
strcat(newFormula, work);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
default: {
|
|
Packit Service |
a1973e |
// the event we depend on has unsupported derived type, put out some debug and give up
|
|
Packit Service |
a1973e |
INTDBG("Event %s depends on event %s which has an unsupported derived type of %d\n", results->symbol, depends_on->symbol, depends_on->derived_int);
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if this was the second event, append to the formula an operation to add or subtract the results of the two events
|
|
Packit Service |
a1973e |
if (second_event) {
|
|
Packit Service |
a1973e |
if (addition != 0) {
|
|
Packit Service |
a1973e |
strcat(newFormula, "+|");
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
strcat(newFormula, "-|");
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
// also change the new derived events type to show it has a formula now
|
|
Packit Service |
a1973e |
results->derived_int = DERIVED_POSTFIX;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// we need to free the existing space (created by malloc and we need to create a new one)
|
|
Packit Service |
a1973e |
papi_free (results->postfix);
|
|
Packit Service |
a1973e |
results->postfix = papi_strdup(newFormula);
|
|
Packit Service |
a1973e |
INTDBG("EXIT: newFormula: %s\n", newFormula);
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// merge the 'insertion' formula into the 'original' formula replacing the
|
|
Packit Service |
a1973e |
// 'replaces' token in the 'original' formula.
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
ops_string_merge(char **original, char *insertion, int replaces, int start_index) {
|
|
Packit Service |
a1973e |
INTDBG("ENTER: original: %p, *original: %s, insertion: %s, replaces: %d, start_index: %d\n", original, *original, insertion, replaces, start_index);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int orig_len=0;
|
|
Packit Service |
a1973e |
int ins_len=0;
|
|
Packit Service |
a1973e |
char *subtoken;
|
|
Packit Service |
a1973e |
char *workBuf;
|
|
Packit Service |
a1973e |
char *workPtr;
|
|
Packit Service |
a1973e |
char *tok_save_ptr=NULL;
|
|
Packit Service |
a1973e |
char *newOriginal;
|
|
Packit Service |
a1973e |
char *newInsertion;
|
|
Packit Service |
a1973e |
char *newFormula;
|
|
Packit Service |
a1973e |
int insert_events;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (*original != NULL) {
|
|
Packit Service |
a1973e |
orig_len = strlen(*original);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (insertion != NULL) {
|
|
Packit Service |
a1973e |
ins_len = strlen(insertion);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
newFormula = papi_calloc (orig_len + ins_len + 40, 1);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if insertion formula is not provided, then the original formula remains basically unchanged.
|
|
Packit Service |
a1973e |
if (insertion == NULL) {
|
|
Packit Service |
a1973e |
// if the original formula has a leading '|' then get rid of it
|
|
Packit Service |
a1973e |
workPtr = *original;
|
|
Packit Service |
a1973e |
if (workPtr[0] == '|') {
|
|
Packit Service |
a1973e |
strcpy(newFormula, &workPtr[1]);
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
strcpy(newFormula, workPtr);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
// formula fields are always malloced space so free the previous one
|
|
Packit Service |
a1973e |
papi_free (*original);
|
|
Packit Service |
a1973e |
*original = newFormula;
|
|
Packit Service |
a1973e |
INTDBG("EXIT: newFormula: %s\n", *original);
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// renumber the token numbers in the insertion formula
|
|
Packit Service |
a1973e |
// also count how many native events are used in this formula
|
|
Packit Service |
a1973e |
insert_events = 0;
|
|
Packit Service |
a1973e |
newInsertion = papi_calloc(ins_len+20, 1);
|
|
Packit Service |
a1973e |
workBuf = papi_calloc(ins_len+10, 1);
|
|
Packit Service |
a1973e |
workPtr = papi_strdup(insertion);
|
|
Packit Service |
a1973e |
subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
|
|
Packit Service |
a1973e |
while ( subtoken != NULL) {
|
|
Packit Service |
a1973e |
// INTDBG("subtoken: %s, newInsertion: %s\n", subtoken, newInsertion);
|
|
Packit Service |
a1973e |
if ((subtoken[0] == 'N') && (isdigit(subtoken[1]))) {
|
|
Packit Service |
a1973e |
insert_events++;
|
|
Packit Service |
a1973e |
int val = atoi(&subtoken[1]);
|
|
Packit Service |
a1973e |
val += start_index;
|
|
Packit Service |
a1973e |
subtoken[1] = '\0';
|
|
Packit Service |
a1973e |
sprintf (workBuf, "N%d", val);
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
strcpy(workBuf, subtoken);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
strcat (newInsertion, workBuf);
|
|
Packit Service |
a1973e |
strcat (newInsertion, "|");
|
|
Packit Service |
a1973e |
subtoken = strtok_r(NULL, "|", &tok_save_ptr);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
papi_free (workBuf);
|
|
Packit Service |
a1973e |
papi_free (workPtr);
|
|
Packit Service |
a1973e |
INTDBG("newInsertion: %s\n", newInsertion);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if original formula is not provided, then the updated insertion formula becomes the new formula
|
|
Packit Service |
a1973e |
// but we still had to renumber the native event tokens in case another native event was put into the list first
|
|
Packit Service |
a1973e |
if (*original == NULL) {
|
|
Packit Service |
a1973e |
*original = papi_strdup(newInsertion);
|
|
Packit Service |
a1973e |
INTDBG("EXIT: newFormula: %s\n", newInsertion);
|
|
Packit Service |
a1973e |
papi_free (newInsertion);
|
|
Packit Service |
a1973e |
papi_free (newFormula);
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if token to replace not valid, return null (do we also need to check an upper bound ???)
|
|
Packit Service |
a1973e |
if ((replaces < 0)) {
|
|
Packit Service |
a1973e |
papi_free (newInsertion);
|
|
Packit Service |
a1973e |
papi_free (newFormula);
|
|
Packit Service |
a1973e |
INTDBG("EXIT: Invalid value for token in original formula to be replaced\n");
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// renumber the token numbers in the original formula
|
|
Packit Service |
a1973e |
// tokens with an index greater than the replaces token need to be incremented by number of events in insertion formula-1
|
|
Packit Service |
a1973e |
newOriginal = papi_calloc (orig_len+20, 1);
|
|
Packit Service |
a1973e |
workBuf = papi_calloc(orig_len+10, 1);
|
|
Packit Service |
a1973e |
workPtr = papi_strdup(*original);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
|
|
Packit Service |
a1973e |
while ( subtoken != NULL) {
|
|
Packit Service |
a1973e |
// INTDBG("subtoken: %s, newOriginal: %s\n", subtoken, newOriginal);
|
|
Packit Service |
a1973e |
// prime the work area with the next token, then see if we need to change it
|
|
Packit Service |
a1973e |
strcpy(workBuf, subtoken);
|
|
Packit Service |
a1973e |
if ((subtoken[0] == 'N') && (isdigit(subtoken[1]))) {
|
|
Packit Service |
a1973e |
int val = atoi(&subtoken[1]);
|
|
Packit Service |
a1973e |
if (val > replaces) {
|
|
Packit Service |
a1973e |
val += insert_events-1;
|
|
Packit Service |
a1973e |
subtoken[1] = '\0';
|
|
Packit Service |
a1973e |
sprintf (workBuf, "N%d", val);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
// put the work buffer into the new original formula
|
|
Packit Service |
a1973e |
strcat (newOriginal, workBuf);
|
|
Packit Service |
a1973e |
strcat (newOriginal, "|");
|
|
Packit Service |
a1973e |
subtoken = strtok_r(NULL, "|", &tok_save_ptr);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
papi_free (workBuf);
|
|
Packit Service |
a1973e |
papi_free (workPtr);
|
|
Packit Service |
a1973e |
INTDBG("newOriginal: %s\n", newOriginal);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// replace the specified "replace" tokens in the new original formula with the new insertion formula
|
|
Packit Service |
a1973e |
newFormula[0] = '\0';
|
|
Packit Service |
a1973e |
workPtr = newOriginal;
|
|
Packit Service |
a1973e |
subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
|
|
Packit Service |
a1973e |
while ( subtoken != NULL) {
|
|
Packit Service |
a1973e |
// INTDBG("subtoken: %s, newFormula: %s\n", subtoken, newFormula);
|
|
Packit Service |
a1973e |
// if this is the token we want to replace with the insertion string, do it now
|
|
Packit Service |
a1973e |
if ((subtoken[0] == 'N') && (isdigit(subtoken[1])) && (replaces == atoi(&subtoken[1]))) {
|
|
Packit Service |
a1973e |
// copy updated insertion string into the original string (replacing this token)
|
|
Packit Service |
a1973e |
strcat(newFormula, newInsertion);
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
// copy this part of the original formula into the new formula
|
|
Packit Service |
a1973e |
strcat(newFormula, subtoken);
|
|
Packit Service |
a1973e |
strcat(newFormula, "|");
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
subtoken = strtok_r(NULL, "|", &tok_save_ptr);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
papi_free (newInsertion);
|
|
Packit Service |
a1973e |
papi_free (workPtr);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// formula fields are always malloced space so free the previous one
|
|
Packit Service |
a1973e |
papi_free (*original);
|
|
Packit Service |
a1973e |
*original = newFormula;
|
|
Packit Service |
a1973e |
INTDBG("EXIT: newFormula: %s\n", newFormula);
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
//
|
|
Packit Service |
a1973e |
// Check to see if an event the new derived event being created depends on is known. We check both preset and user defined derived events here.
|
|
Packit Service |
a1973e |
// If it is a known derived event then we set the new event being defined to include the necessary native events and formula to compute its
|
|
Packit Service |
a1973e |
// derived value and use it in the correct context of the new derived event being created. Depending on the inputs, the operations strings (formulas)
|
|
Packit Service |
a1973e |
// to be used by the new derived event may need to be created and/or adjusted to reference the correct native event indexes for the new derived event.
|
|
Packit Service |
a1973e |
// The formulas processed by this code must be reverse polish notation (RPN) or postfix format and they must contain place holders (like N0, N1) which
|
|
Packit Service |
a1973e |
// identify indexes into the native event array used to compute the new derived events final value.
|
|
Packit Service |
a1973e |
//
|
|
Packit Service |
a1973e |
// Arguments:
|
|
Packit Service |
a1973e |
// target: event we are looking for
|
|
Packit Service |
a1973e |
// derived_type: type of derived event being created (add, subtract, postfix)
|
|
Packit Service |
a1973e |
// results: where to build the new preset event being defined.
|
|
Packit Service |
a1973e |
// search: table of known existing preset or user events the new derived event is allowed to use (points to a table of either preset or user events).
|
|
Packit Service |
a1973e |
// search_size: number of entries in the search table.
|
|
Packit Service |
a1973e |
//
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
check_derived_events(char *target, int derived_type, hwi_presets_t* results, hwi_presets_t * search, int search_size, int token_index)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
INTDBG("ENTER: target: %p (%s), results: %p, search: %p, search_size: %d, token_index: %d\n", target, target, results, search, search_size, token_index);
|
|
Packit Service |
a1973e |
unsigned int i;
|
|
Packit Service |
a1973e |
int j;
|
|
Packit Service |
a1973e |
int k;
|
|
Packit Service |
a1973e |
int found = 0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for (j=0; j < search_size; j++) {
|
|
Packit Service |
a1973e |
// INTDBG("search[%d].symbol: %s, looking for: %s\n", j, search[j].symbol, target);
|
|
Packit Service |
a1973e |
if (search[j].symbol == NULL) {
|
|
Packit Service |
a1973e |
INTDBG("EXIT: returned: 0\n");
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if not the event we depend on, just look at next
|
|
Packit Service |
a1973e |
if ( strcasecmp( target, search[j].symbol) != 0 ) {
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG("Found a match\n");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// derived formulas need to be adjusted based on what kind of derived event we are processing
|
|
Packit Service |
a1973e |
// the derived type passed to this function is the type of the new event being defined (not the events it is based on)
|
|
Packit Service |
a1973e |
// when we get here the formula must be in reverse polish notation (RPN) format
|
|
Packit Service |
a1973e |
switch (derived_type) {
|
|
Packit Service |
a1973e |
case DERIVED_POSTFIX: {
|
|
Packit Service |
a1973e |
// go create a formula to merge the second formula into a spot identified by one of the tokens in
|
|
Packit Service |
a1973e |
// the first formula.
|
|
Packit Service |
a1973e |
ops_string_merge(&(results->postfix), search[j].postfix, token_index, results->count);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
case DERIVED_ADD: {
|
|
Packit Service |
a1973e |
// the new derived event adds two things together, go handle this target events role in the add
|
|
Packit Service |
a1973e |
ops_string_append(results, &search[j], 1);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
case DERIVED_SUB: {
|
|
Packit Service |
a1973e |
// go create a formula to subtract the value generated by the second formula from the value generated by the first formula.
|
|
Packit Service |
a1973e |
ops_string_append(results, &search[j], 0);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
default: {
|
|
Packit Service |
a1973e |
INTDBG("Derived type: %d, not currently handled\n", derived_type);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// copy event name and code used by the derived event into the results table (place where new derived event is getting created)
|
|
Packit Service |
a1973e |
for ( k = 0; k < (int)search[j].count; k++ ) {
|
|
Packit Service |
a1973e |
// INTDBG("search[%d]: %p, name[%d]: %s, code[%d]: %#x\n", j, &search[j], k, search[j].name[k], k, search[j].code[k]);
|
|
Packit Service |
a1973e |
// if this event is already in the list, just update the formula so that references to this event point to the existing one
|
|
Packit Service |
a1973e |
for (i=0 ; i < results->count ; i++) {
|
|
Packit Service |
a1973e |
if (results->code[i] == search[j].code[k]) {
|
|
Packit Service |
a1973e |
INTDBG("event: %s, code: %#x, already in results at index: %d\n", search[j].name[k], search[j].code[k], i);
|
|
Packit Service |
a1973e |
// replace all tokens in the formula that refer to index "results->count + found" with a token that refers to index "i".
|
|
Packit Service |
a1973e |
// the index "results->count + found" identifies the index used in the formula for the event we just determined is a duplicate
|
|
Packit Service |
a1973e |
update_ops_string(&(results->postfix), results->count + found, i);
|
|
Packit Service |
a1973e |
found++;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if we did not find a match, copy native event info into results array
|
|
Packit Service |
a1973e |
if (found == 0) {
|
|
Packit Service |
a1973e |
// not a duplicate, go ahead and copy into results and bump number of native events in results
|
|
Packit Service |
a1973e |
if (search[j].name[k]) {
|
|
Packit Service |
a1973e |
results->name[results->count] = papi_strdup(search[j].name[k]);
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
results->name[results->count] = papi_strdup(target);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
results->code[results->count] = search[j].code[k];
|
|
Packit Service |
a1973e |
INTDBG("results: %p, name[%d]: %s, code[%d]: %#x\n", results, results->count, results->name[results->count], results->count, results->code[results->count]);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
results->count++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG("EXIT: returned: 1\n");
|
|
Packit Service |
a1973e |
return 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG("EXIT: returned: 0\n");
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
check_native_events(char *target, hwi_presets_t* results)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
INTDBG("ENTER: target: %p (%s), results: %p\n", target, target, results);
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// find this native events code
|
|
Packit Service |
a1973e |
if ( ( ret = _papi_hwi_native_name_to_code( target, (int *)(&results->code[results->count])) ) != PAPI_OK ) {
|
|
Packit Service |
a1973e |
INTDBG("EXIT: returned: 0, call to convert name to event code failed with ret: %d\n", ret);
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if the code returned was 0, return to show it is not a valid native event
|
|
Packit Service |
a1973e |
if ( results->code[results->count] == 0 ) {
|
|
Packit Service |
a1973e |
INTDBG( "EXIT: returned: 0, event code not found\n");
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if this native event is not for component 0, return to show it can not be used in derived events
|
|
Packit Service |
a1973e |
// it should be possible to create derived events for other components as long as all events in the derived event are associated with the same component
|
|
Packit Service |
a1973e |
if ( _papi_hwi_component_index(results->code[results->count]) != 0 ) {
|
|
Packit Service |
a1973e |
INTDBG( "EXIT: returned: 0, new event not associated with component 0 (current limitation with derived events)\n");
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// found = 1;
|
|
Packit Service |
a1973e |
INTDBG("\tFound a native event %s\n", target);
|
|
Packit Service |
a1973e |
results->name[results->count++] = papi_strdup(target);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG( "EXIT: returned: 1\n");
|
|
Packit Service |
a1973e |
return 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// see if the event_name string passed in matches a known event name
|
|
Packit Service |
a1973e |
// if it does these calls also updates information in event definition tables to remember the event
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
is_event(char *event_name, int derived_type, hwi_presets_t* results, int token_index) {
|
|
Packit Service |
a1973e |
INTDBG("ENTER: event_name: %p (%s), derived_type: %d, results: %p, token_index: %d\n", event_name, event_name, derived_type, results, token_index);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* check if its a preset event */
|
|
Packit Service |
a1973e |
if ( check_derived_events(event_name, derived_type, results, &_papi_hwi_presets[0], PAPI_MAX_PRESET_EVENTS, token_index) ) {
|
|
Packit Service |
a1973e |
INTDBG("EXIT: found preset event\n");
|
|
Packit Service |
a1973e |
return 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* check if its a user defined event */
|
|
Packit Service |
a1973e |
if ( check_derived_events(event_name, derived_type, results, user_defined_events, user_defined_events_count, token_index) ) {
|
|
Packit Service |
a1973e |
INTDBG("EXIT: found user event\n");
|
|
Packit Service |
a1973e |
return 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* check if its a native event */
|
|
Packit Service |
a1973e |
if ( check_native_events(event_name, results) ) {
|
|
Packit Service |
a1973e |
INTDBG("EXIT: found native event\n");
|
|
Packit Service |
a1973e |
return 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG("EXIT: event not found\n");
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Static version of the events file. */
|
|
Packit Service |
a1973e |
#if defined(STATIC_PAPI_EVENTS_TABLE)
|
|
Packit Service |
a1973e |
#include "papi_events_table.h"
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
static char *papi_events_table = NULL;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int _papi_load_preset_table(char *pmu_str, int pmu_type, int cidx) {
|
|
Packit Service |
a1973e |
SUBDBG("ENTER: pmu_str: %s, pmu_type: %d, cidx: %d\n", pmu_str, pmu_type, cidx);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int retval;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// go load papi preset events (last argument tells function if we are loading presets or user events)
|
|
Packit Service |
a1973e |
retval = papi_load_derived_events(pmu_str, pmu_type, cidx, 1);
|
|
Packit Service |
a1973e |
if (retval != PAPI_OK) {
|
|
Packit Service |
a1973e |
SUBDBG("EXIT: retval: %d\n", retval);
|
|
Packit Service |
a1973e |
return retval;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// go load the user defined event definitions if any are defined
|
|
Packit Service |
a1973e |
retval = papi_load_derived_events(pmu_str, pmu_type, cidx, 0);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG("EXIT: retval: %d\n", retval);
|
|
Packit Service |
a1973e |
return retval;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// global variables
|
|
Packit Service |
a1973e |
static char stack[2*PAPI_HUGE_STR_LEN]; // stack
|
|
Packit Service |
a1973e |
static int stacktop = -1; // stack length
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// priority: This function returns the priority of the operator
|
|
Packit Service |
a1973e |
static
|
|
Packit Service |
a1973e |
int priority( char symbol ) {
|
|
Packit Service |
a1973e |
switch( symbol ) {
|
|
Packit Service |
a1973e |
case '@':
|
|
Packit Service |
a1973e |
return -1;
|
|
Packit Service |
a1973e |
case '(':
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
case '+':
|
|
Packit Service |
a1973e |
case '-':
|
|
Packit Service |
a1973e |
return 1;
|
|
Packit Service |
a1973e |
case '*':
|
|
Packit Service |
a1973e |
case '/':
|
|
Packit Service |
a1973e |
case '%':
|
|
Packit Service |
a1973e |
return 2;
|
|
Packit Service |
a1973e |
default :
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
} // end switch symbol
|
|
Packit Service |
a1973e |
} // end priority
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static
|
|
Packit Service |
a1973e |
int push( char symbol ) {
|
|
Packit Service |
a1973e |
if (stacktop >= 2*PAPI_HUGE_STR_LEN - 1) {
|
|
Packit Service |
a1973e |
INTDBG("stack overflow converting algebraic expression (%d,%c)\n", stacktop,symbol );
|
|
Packit Service |
a1973e |
return -1; //***TODO: Figure out how to exit gracefully
|
|
Packit Service |
a1973e |
} // end if stacktop>MAX
|
|
Packit Service |
a1973e |
stack[++stacktop] = symbol;
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
} // end push
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// pop from stack
|
|
Packit Service |
a1973e |
static
|
|
Packit Service |
a1973e |
char pop() {
|
|
Packit Service |
a1973e |
if( stacktop < 0 ) {
|
|
Packit Service |
a1973e |
INTDBG("stack underflow converting algebraic expression\n" );
|
|
Packit Service |
a1973e |
return '\0'; //***TODO: Figure out how to exit gracefully
|
|
Packit Service |
a1973e |
} // end if empty
|
|
Packit Service |
a1973e |
return( stack[stacktop--] );
|
|
Packit Service |
a1973e |
} // end pop
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* infix_to_postfix:
|
|
Packit Service |
a1973e |
routine that will be called with parameter:
|
|
Packit Service |
a1973e |
char *in characters of infix notation (algebraic formula)
|
|
Packit Service |
a1973e |
returns: char * pointer to string of returned postfix */
|
|
Packit Service |
a1973e |
static char *
|
|
Packit Service |
a1973e |
infix_to_postfix( char *infix ) {
|
|
Packit Service |
a1973e |
INTDBG("ENTER: in: %s, size: %zu\n", infix, strlen(infix));
|
|
Packit Service |
a1973e |
static char postfix[2*PAPI_HUGE_STR_LEN]; // output
|
|
Packit Service |
a1973e |
unsigned int index;
|
|
Packit Service |
a1973e |
int postfixlen;
|
|
Packit Service |
a1973e |
char token;
|
|
Packit Service |
a1973e |
if ( strlen(infix) > PAPI_HUGE_STR_LEN )
|
|
Packit Service |
a1973e |
PAPIERROR("A infix string (probably in user-defined presets) is too big (max allowed %d): %s", PAPI_HUGE_STR_LEN, infix );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// initialize stack
|
|
Packit Service |
a1973e |
memset(stack, 0, 2*PAPI_HUGE_STR_LEN);
|
|
Packit Service |
a1973e |
stacktop = -1;
|
|
Packit Service |
a1973e |
push('#');
|
|
Packit Service |
a1973e |
stacktop = 0; // after initialization of stack to #
|
|
Packit Service |
a1973e |
/* initialize output string */
|
|
Packit Service |
a1973e |
memset(postfix,0,2*PAPI_HUGE_STR_LEN);
|
|
Packit Service |
a1973e |
postfixlen = 0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for( index=0; index
|
|
Packit Service |
a1973e |
token = infix[index];
|
|
Packit Service |
a1973e |
INTDBG("INTDBG: in: %s, length: %zu, index: %d token %c\n", infix, strlen( infix ), index, token);
|
|
Packit Service |
a1973e |
switch( token ) {
|
|
Packit Service |
a1973e |
case '(':
|
|
Packit Service |
a1973e |
push( token );
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
case ')':
|
|
Packit Service |
a1973e |
if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
|
|
Packit Service |
a1973e |
while ( stack[stacktop] != '(' ) {
|
|
Packit Service |
a1973e |
postfix[postfixlen++] = pop();
|
|
Packit Service |
a1973e |
postfix[postfixlen++] = '|';
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
token = pop(); /* pop the '(' character */
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
case '+':
|
|
Packit Service |
a1973e |
case '-':
|
|
Packit Service |
a1973e |
case '*':
|
|
Packit Service |
a1973e |
case '/':
|
|
Packit Service |
a1973e |
case '%':
|
|
Packit Service |
a1973e |
case '^': /* if an operator */
|
|
Packit Service |
a1973e |
if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
|
|
Packit Service |
a1973e |
while ( priority(stack[stacktop]) > priority(token) ) {
|
|
Packit Service |
a1973e |
postfix[postfixlen++] = pop();
|
|
Packit Service |
a1973e |
postfix[postfixlen++] = '|';
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
push( token ); /* save current operator */
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
default: // if alphanumeric character which is not parenthesis or an operator
|
|
Packit Service |
a1973e |
postfix[postfixlen++] = token;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
} // end switch symbol
|
|
Packit Service |
a1973e |
} // end while
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Write any remaining operators */
|
|
Packit Service |
a1973e |
if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
|
|
Packit Service |
a1973e |
while ( stacktop>0 ) {
|
|
Packit Service |
a1973e |
postfix[postfixlen++] = pop();
|
|
Packit Service |
a1973e |
postfix[postfixlen++] = '|';
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
postfix[postfixlen++] = '\0';
|
|
Packit Service |
a1973e |
stacktop = -1;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG("EXIT: postfix: %s, size: %zu\n", postfix, strlen(postfix));
|
|
Packit Service |
a1973e |
return (postfix);
|
|
Packit Service |
a1973e |
} // end infix_to_postfix
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* This function will load event definitions from either a file or an in memory table. It is used to load both preset events
|
|
Packit Service |
a1973e |
* which are defined by the PAPI development team and delivered with the product and user defined events which can be defined
|
|
Packit Service |
a1973e |
* by papi users and provided to papi to be processed at library initialization. Both the preset events and user defined events
|
|
Packit Service |
a1973e |
* support the same event definition syntax.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* Event definition file syntax:
|
|
Packit Service |
a1973e |
* see PAPI_derived_event_files(1) man page.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* Blank lines are ignored
|
|
Packit Service |
a1973e |
* Lines that begin with '#' are comments.
|
|
Packit Service |
a1973e |
* Lines that begin with 'CPU' identify a pmu name and have the following effect.
|
|
Packit Service |
a1973e |
* If this pmu name does not match the pmu_str passed in, it is ignored and we get the next input line.
|
|
Packit Service |
a1973e |
* If this pmu name matches the pmu_str passed in, we set a 'process events' flag.
|
|
Packit Service |
a1973e |
* Multiple consecutive 'CPU' lines may be provided and if any of them match the pmu_str passed in, we set a 'process events' flag.
|
|
Packit Service |
a1973e |
* When a 'CPU' line is found following event definition lines, it turns off the 'process events' flag and then does the above checks.
|
|
Packit Service |
a1973e |
* Lines that begin with 'PRESET' or 'EVENT' specify an event definition and are processed as follows.
|
|
Packit Service |
a1973e |
* If the 'process events' flag is not set, the line is ignored and we get the next input line.
|
|
Packit Service |
a1973e |
* If the 'process events' flag is set, the event is processed and the event information is put into the next slot in the results array.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* There are three possible sources of input for preset event definitions. The code will first look for the environment variable
|
|
Packit Service |
a1973e |
* "PAPI_CSV_EVENT_FILE". If found its value will be used as the pathname of where to get the preset information. If not found,
|
|
Packit Service |
a1973e |
* the code will look for a built in table containing preset events. If the built in table was not created during the build of
|
|
Packit Service |
a1973e |
* PAPI then the code will build a pathname of the form "PAPI_DATADIR/PAPI_EVENT_FILE". Each of these are build variables, the
|
|
Packit Service |
a1973e |
* PAPI_DATADIR variable can be given a value during the configure of PAPI at build time, and the PAPI_EVENT_FILE variable has a
|
|
Packit Service |
a1973e |
* hard coded value of "papi_events.csv".
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* There is only one way to define user events. The code will look for an environment variable "PAPI_USER_EVENTS_FILE". If found
|
|
Packit Service |
a1973e |
* its value will be used as the pathname of a file which contains user event definitions. The events defined in this file will be
|
|
Packit Service |
a1973e |
* added to the ones known by PAPI when the call to PAPI_library_init is done.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* TODO:
|
|
Packit Service |
a1973e |
* Look into restoring the ability to specify a user defined event file with a call to PAPI_set_opt(PAPI_USER_EVENTS_FILE).
|
|
Packit Service |
a1973e |
* This needs to figure out how to pass a pmu name (could use default pmu from component 0) to this function.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* Currently code elsewhere in PAPI limits the events which preset and user events can depend on to those events which are known to component 0. This possibly could
|
|
Packit Service |
a1973e |
* be relaxed to allow events from different components. But since all the events used by any derived event must be added to the same eventset, it will always be a
|
|
Packit Service |
a1973e |
* requirement that all events used by a given derived event must be from the same component.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
papi_load_derived_events (char *pmu_str, int pmu_type, int cidx, int preset_flag) {
|
|
Packit Service |
a1973e |
SUBDBG( "ENTER: pmu_str: %s, pmu_type: %d, cidx: %d, preset_flag: %d\n", pmu_str, pmu_type, cidx, preset_flag);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
char pmu_name[PAPI_MIN_STR_LEN];
|
|
Packit Service |
a1973e |
char line[LINE_MAX];
|
|
Packit Service |
a1973e |
char name[PATH_MAX] = "builtin papi_events_table";
|
|
Packit Service |
a1973e |
char *event_file_path=NULL;
|
|
Packit Service |
a1973e |
char *event_table_ptr=NULL;
|
|
Packit Service |
a1973e |
int event_type_bits = 0;
|
|
Packit Service |
a1973e |
char *tmpn;
|
|
Packit Service |
a1973e |
char *tok_save_ptr=NULL;
|
|
Packit Service |
a1973e |
FILE *event_file = NULL;
|
|
Packit Service |
a1973e |
hwi_presets_t *results=NULL;
|
|
Packit Service |
a1973e |
int result_size = 0;
|
|
Packit Service |
a1973e |
int *event_count = NULL;
|
|
Packit Service |
a1973e |
int invalid_event;
|
|
Packit Service |
a1973e |
int line_no = 0; /* count of lines read from event definition input */
|
|
Packit Service |
a1973e |
int derived = 0;
|
|
Packit Service |
a1973e |
int res_idx = 0; /* index into results array for where to store next event */
|
|
Packit Service |
a1973e |
int preset = 0;
|
|
Packit Service |
a1973e |
int get_events = 0; /* only process derived events after CPU type they apply to is identified */
|
|
Packit Service |
a1973e |
int found_events = 0; /* flag to track if event definitions (PRESETS) are found since last CPU declaration */
|
|
Packit Service |
a1973e |
#ifdef PAPI_DATADIR
|
|
Packit Service |
a1973e |
char path[PATH_MAX];
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (preset_flag) {
|
|
Packit Service |
a1973e |
/* try the environment variable first */
|
|
Packit Service |
a1973e |
if ((tmpn = getenv("PAPI_CSV_EVENT_FILE")) && (strlen(tmpn) > 0)) {
|
|
Packit Service |
a1973e |
event_file_path = tmpn;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* if no valid environment variable, look for built-in table */
|
|
Packit Service |
a1973e |
else if (papi_events_table) {
|
|
Packit Service |
a1973e |
event_table_ptr = papi_events_table;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* if no env var and no built-in, search for default file */
|
|
Packit Service |
a1973e |
else {
|
|
Packit Service |
a1973e |
#ifdef PAPI_DATADIR
|
|
Packit Service |
a1973e |
sprintf( path, "%s/%s", PAPI_DATADIR, PAPI_EVENT_FILE );
|
|
Packit Service |
a1973e |
event_file_path = path;
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
event_file_path = PAPI_EVENT_FILE;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
event_type_bits = PAPI_PRESET_MASK;
|
|
Packit Service |
a1973e |
results = &_papi_hwi_presets[0];
|
|
Packit Service |
a1973e |
result_size = PAPI_MAX_PRESET_EVENTS;
|
|
Packit Service |
a1973e |
event_count = &_papi_hwd[cidx]->cmp_info.num_preset_events;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
if ((event_file_path = getenv( "PAPI_USER_EVENTS_FILE" )) == NULL ) {
|
|
Packit Service |
a1973e |
SUBDBG("EXIT: User event definition file not provided.\n");
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
event_type_bits = PAPI_UE_MASK;
|
|
Packit Service |
a1973e |
results = &user_defined_events[0];
|
|
Packit Service |
a1973e |
result_size = PAPI_MAX_USER_EVENTS;
|
|
Packit Service |
a1973e |
event_count = &user_defined_events_count;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if we have an event file pathname, open it and read event definitions from the file
|
|
Packit Service |
a1973e |
if (event_file_path != NULL) {
|
|
Packit Service |
a1973e |
if ((event_file = open_event_table(event_file_path)) == NULL) {
|
|
Packit Service |
a1973e |
// if file open fails, return an error
|
|
Packit Service |
a1973e |
SUBDBG("EXIT: Event file open failed.\n");
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
strncpy(name, event_file_path, sizeof(name)-1);
|
|
Packit Service |
a1973e |
name[sizeof(name)-1] = '\0';
|
|
Packit Service |
a1973e |
} else if (event_table_ptr == NULL) {
|
|
Packit Service |
a1973e |
// if we do not have a path name or table pointer, return an error
|
|
Packit Service |
a1973e |
SUBDBG("EXIT: Both event_file_path and event_table_ptr are NULL.\n");
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* copy the pmu identifier, stripping commas if found */
|
|
Packit Service |
a1973e |
tmpn = pmu_name;
|
|
Packit Service |
a1973e |
while (*pmu_str) {
|
|
Packit Service |
a1973e |
if (*pmu_str != ',')
|
|
Packit Service |
a1973e |
*tmpn++ = *pmu_str;
|
|
Packit Service |
a1973e |
pmu_str++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
*tmpn = '\0';
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* at this point we have either a valid file pointer or built-in table pointer */
|
|
Packit Service |
a1973e |
while (get_event_line(line, event_file, &event_table_ptr)) {
|
|
Packit Service |
a1973e |
char *t;
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// increment number of lines we have read
|
|
Packit Service |
a1973e |
line_no++;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
t = trim_string(strtok_r(line, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Skip blank lines */
|
|
Packit Service |
a1973e |
if ((t == NULL) || (strlen(t) == 0))
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Skip comments */
|
|
Packit Service |
a1973e |
if (t[0] == '#') {
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (strcasecmp(t, "CPU") == 0) {
|
|
Packit Service |
a1973e |
if (get_events != 0 && found_events != 0) {
|
|
Packit Service |
a1973e |
SUBDBG( "Ending event scanning at line %d of %s.\n", line_no, name);
|
|
Packit Service |
a1973e |
get_events = 0;
|
|
Packit Service |
a1973e |
found_events = 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
if ((t == NULL) || (strlen(t) == 0)) {
|
|
Packit Service |
a1973e |
PAPIERROR("Expected name after CPU token at line %d of %s -- ignoring", line_no, name);
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (strcasecmp(t, pmu_name) == 0) {
|
|
Packit Service |
a1973e |
int type;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "Process events for PMU %s found at line %d of %s.\n", t, line_no, name);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
if ((t == NULL) || (strlen(t) == 0)) {
|
|
Packit Service |
a1973e |
SUBDBG("No additional qualifier found, matching on string.\n");
|
|
Packit Service |
a1973e |
get_events = 1;
|
|
Packit Service |
a1973e |
} else if ((sscanf(t, "%d", &type) == 1) && (type == pmu_type)) {
|
|
Packit Service |
a1973e |
SUBDBG( "Found CPU %s type %d at line %d of %s.\n", pmu_name, type, line_no, name);
|
|
Packit Service |
a1973e |
get_events = 1;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
SUBDBG( "Additional qualifier match failed %d vs %d.\n", pmu_type, type);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ((strcasecmp(t, "PRESET") == 0) || (strcasecmp(t, "EVENT") == 0)) {
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (get_events == 0)
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
found_events = 1;
|
|
Packit Service |
a1973e |
t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ((t == NULL) || (strlen(t) == 0)) {
|
|
Packit Service |
a1973e |
PAPIERROR("Expected name after PRESET token at line %d of %s -- ignoring", line_no, name);
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "Examining event %s\n", t);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// see if this event already exists in the results array, if not already known it sets up event in unused entry
|
|
Packit Service |
a1973e |
if ((res_idx = find_event_index (results, result_size, t)) < 0) {
|
|
Packit Service |
a1973e |
PAPIERROR("No room left for event %s -- ignoring", t);
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// add the proper event bits (preset or user defined bits)
|
|
Packit Service |
a1973e |
preset = res_idx | event_type_bits;
|
|
Packit Service |
a1973e |
(void) preset;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "Use event code: %#x for %s\n", preset, t);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
if ((t == NULL) || (strlen(t) == 0)) {
|
|
Packit Service |
a1973e |
// got an error, make this entry unused
|
|
Packit Service |
a1973e |
papi_free (results[res_idx].symbol);
|
|
Packit Service |
a1973e |
results[res_idx].symbol = NULL;
|
|
Packit Service |
a1973e |
PAPIERROR("Expected derived type after PRESET token at line %d of %s -- ignoring", line_no, name);
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (_papi_hwi_derived_type(t, &derived) != PAPI_OK) {
|
|
Packit Service |
a1973e |
// got an error, make this entry unused
|
|
Packit Service |
a1973e |
papi_free (results[res_idx].symbol);
|
|
Packit Service |
a1973e |
results[res_idx].symbol = NULL;
|
|
Packit Service |
a1973e |
PAPIERROR("Invalid derived name %s after PRESET token at line %d of %s -- ignoring", t, line_no, name);
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/****************************************/
|
|
Packit Service |
a1973e |
/* Have an event, let's start assigning */
|
|
Packit Service |
a1973e |
/****************************************/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "Adding event: %s, code: %#x, derived: %d results[%d]: %p.\n", t, preset, derived, res_idx, &results[res_idx]);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* results[res_idx].event_code = preset; */
|
|
Packit Service |
a1973e |
results[res_idx].derived_int = derived;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Derived support starts here */
|
|
Packit Service |
a1973e |
/* Special handling for postfix and infix */
|
|
Packit Service |
a1973e |
if ((derived == DERIVED_POSTFIX) || (derived == DERIVED_INFIX)) {
|
|
Packit Service |
a1973e |
t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
if ((t == NULL) || (strlen(t) == 0)) {
|
|
Packit Service |
a1973e |
// got an error, make this entry unused
|
|
Packit Service |
a1973e |
papi_free (results[res_idx].symbol);
|
|
Packit Service |
a1973e |
results[res_idx].symbol = NULL;
|
|
Packit Service |
a1973e |
PAPIERROR("Expected Operation string after derived type DERIVED_POSTFIX or DERIVED_INFIX at line %d of %s -- ignoring", line_no, name);
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if it is an algebraic formula, we need to convert it to postfix
|
|
Packit Service |
a1973e |
if (derived == DERIVED_INFIX) {
|
|
Packit Service |
a1973e |
SUBDBG( "Converting InFix operations %s\n", t);
|
|
Packit Service |
a1973e |
t = infix_to_postfix( t );
|
|
Packit Service |
a1973e |
results[res_idx].derived_int = DERIVED_POSTFIX;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "Saving PostFix operations %s\n", t);
|
|
Packit Service |
a1973e |
results[res_idx].postfix = papi_strdup(t);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* All derived terms collected here */
|
|
Packit Service |
a1973e |
i = 0;
|
|
Packit Service |
a1973e |
invalid_event = 0;
|
|
Packit Service |
a1973e |
results[res_idx].count = 0;
|
|
Packit Service |
a1973e |
do {
|
|
Packit Service |
a1973e |
t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
if ((t == NULL) || (strlen(t) == 0))
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
if (strcasecmp(t, "NOTE") == 0)
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
if (strcasecmp(t, "LDESC") == 0)
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
if (strcasecmp(t, "SDESC") == 0)
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "Adding term (%d) %s to derived event %#x, current native event count: %d.\n", i, t, preset, results[res_idx].count);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// show that we do not have an event code yet (the component may create one and update this info)
|
|
Packit Service |
a1973e |
// this also clears any values left over from a previous call
|
|
Packit Service |
a1973e |
_papi_hwi_set_papi_event_code(-1, -1);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// make sure that this term in the derived event is a valid event name
|
|
Packit Service |
a1973e |
// this call replaces preset and user event names with the equivalent native events in our results table
|
|
Packit Service |
a1973e |
// it also updates formulas for derived events so that they refer to the correct native event index
|
|
Packit Service |
a1973e |
if (is_event(t, results[res_idx].derived_int, &results[res_idx], i) == 0) {
|
|
Packit Service |
a1973e |
invalid_event = 1;
|
|
Packit Service |
a1973e |
PAPIERROR("Missing event %s, used in derived event %s", t, results[res_idx].symbol);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
i++;
|
|
Packit Service |
a1973e |
} while (results[res_idx].count < PAPI_EVENTS_IN_DERIVED_EVENT);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* preset code list must be PAPI_NULL terminated */
|
|
Packit Service |
a1973e |
if (i < PAPI_EVENTS_IN_DERIVED_EVENT) {
|
|
Packit Service |
a1973e |
results[res_idx].code[results[res_idx].count] = PAPI_NULL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (invalid_event) {
|
|
Packit Service |
a1973e |
// got an error, make this entry unused
|
|
Packit Service |
a1973e |
// preset table is statically allocated, user defined is dynamic
|
|
Packit Service |
a1973e |
if (!preset_flag) papi_free (results[res_idx].symbol);
|
|
Packit Service |
a1973e |
results[res_idx].symbol = NULL;
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* End of derived support */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if we did not find any terms to base this derived event on, report error
|
|
Packit Service |
a1973e |
if (i == 0) {
|
|
Packit Service |
a1973e |
// got an error, make this entry unused
|
|
Packit Service |
a1973e |
if (!preset_flag) papi_free (results[res_idx].symbol);
|
|
Packit Service |
a1973e |
results[res_idx].symbol = NULL;
|
|
Packit Service |
a1973e |
PAPIERROR("Expected PFM event after DERIVED token at line %d of %s -- ignoring", line_no, name);
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (i == PAPI_EVENTS_IN_DERIVED_EVENT) {
|
|
Packit Service |
a1973e |
t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// if something was provided following the list of events to be used by the operation, process it
|
|
Packit Service |
a1973e |
if ( t!= NULL && strlen(t) > 0 ) {
|
|
Packit Service |
a1973e |
do {
|
|
Packit Service |
a1973e |
// save the field name
|
|
Packit Service |
a1973e |
char *fptr = papi_strdup(t);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// get the value to be used with this field
|
|
Packit Service |
a1973e |
t = trim_note(strtok_r(NULL, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
if ( t== NULL || strlen(t) == 0 ) {
|
|
Packit Service |
a1973e |
papi_free(fptr);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// Handle optional short descriptions, long descriptions and notes
|
|
Packit Service |
a1973e |
if (strcasecmp(fptr, "SDESC") == 0) {
|
|
Packit Service |
a1973e |
results[res_idx].short_descr = papi_strdup(t);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (strcasecmp(fptr, "LDESC") == 0) {
|
|
Packit Service |
a1973e |
results[res_idx].long_descr = papi_strdup(t);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (strcasecmp(fptr, "NOTE") == 0) {
|
|
Packit Service |
a1973e |
results[res_idx].note = papi_strdup(t);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "Found %s (%s) on line %d\n", fptr, t, line_no);
|
|
Packit Service |
a1973e |
papi_free (fptr);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// look for another field name
|
|
Packit Service |
a1973e |
t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
|
|
Packit Service |
a1973e |
if ( t== NULL || strlen(t) == 0 ) {
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} while (t != NULL);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
(*event_count)++;
|
|
Packit Service |
a1973e |
continue;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
PAPIERROR("Unrecognized token %s at line %d of %s -- ignoring", t, line_no, name);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (event_file) {
|
|
Packit Service |
a1973e |
fclose(event_file);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG("EXIT: Done processing derived event file.\n");
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* The following code is proof of principle for reading preset events from an
|
|
Packit Service |
a1973e |
xml file. It has been tested and works for pentium3. It relys on the expat
|
|
Packit Service |
a1973e |
library and is invoked by adding
|
|
Packit Service |
a1973e |
XMLFLAG = -DXML
|
|
Packit Service |
a1973e |
to the Makefile. It is presently hardcoded to look for "./papi_events.xml"
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
#ifdef XML
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#define BUFFSIZE 8192
|
|
Packit Service |
a1973e |
#define SPARSE_BEGIN 0
|
|
Packit Service |
a1973e |
#define SPARSE_EVENT_SEARCH 1
|
|
Packit Service |
a1973e |
#define SPARSE_EVENT 2
|
|
Packit Service |
a1973e |
#define SPARSE_DESC 3
|
|
Packit Service |
a1973e |
#define ARCH_SEARCH 4
|
|
Packit Service |
a1973e |
#define DENSE_EVENT_SEARCH 5
|
|
Packit Service |
a1973e |
#define DENSE_NATIVE_SEARCH 6
|
|
Packit Service |
a1973e |
#define DENSE_NATIVE_DESC 7
|
|
Packit Service |
a1973e |
#define FINISHED 8
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
char buffer[BUFFSIZE], *xml_arch;
|
|
Packit Service |
a1973e |
int location = SPARSE_BEGIN, sparse_index = 0, native_index, error = 0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* The function below, _xml_start(), is a hook into expat's XML
|
|
Packit Service |
a1973e |
* parser. _xml_start() defines how the parser handles the
|
|
Packit Service |
a1973e |
* opening tags in PAPI's XML file. This function can be understood
|
|
Packit Service |
a1973e |
* more easily if you follow along with its logic while looking at
|
|
Packit Service |
a1973e |
* papi_events.xml. The location variable is a global telling us
|
|
Packit Service |
a1973e |
* where we are in the XML file. Have we found our architecture's
|
|
Packit Service |
a1973e |
* events yet? Are we looking at an event definition?...etc.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
_xml_start( void *data, const char *el, const char **attr )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int native_encoding;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( location == SPARSE_BEGIN && !strcmp( "papistdevents", el ) ) {
|
|
Packit Service |
a1973e |
location = SPARSE_EVENT_SEARCH;
|
|
Packit Service |
a1973e |
} else if ( location == SPARSE_EVENT_SEARCH && !strcmp( "papievent", el ) ) {
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].info.symbol = papi_strdup( attr[1] );
|
|
Packit Service |
a1973e |
// strcpy(_papi_hwi_presets.info[sparse_index].symbol, attr[1]);
|
|
Packit Service |
a1973e |
location = SPARSE_EVENT;
|
|
Packit Service |
a1973e |
} else if ( location == SPARSE_EVENT && !strcmp( "desc", el ) ) {
|
|
Packit Service |
a1973e |
location = SPARSE_DESC;
|
|
Packit Service |
a1973e |
} else if ( location == ARCH_SEARCH && !strcmp( "availevents", el ) &&
|
|
Packit Service |
a1973e |
!strcmp( xml_arch, attr[1] ) ) {
|
|
Packit Service |
a1973e |
location = DENSE_EVENT_SEARCH;
|
|
Packit Service |
a1973e |
} else if ( location == DENSE_EVENT_SEARCH && !strcmp( "papievent", el ) ) {
|
|
Packit Service |
a1973e |
if ( !strcmp( "PAPI_NULL", attr[1] ) ) {
|
|
Packit Service |
a1973e |
location = FINISHED;
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
} else if ( PAPI_event_name_to_code( ( char * ) attr[1], &sparse_index )
|
|
Packit Service |
a1973e |
!= PAPI_OK ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "Improper Preset name given in XML file for %s.",
|
|
Packit Service |
a1973e |
attr[1] );
|
|
Packit Service |
a1973e |
error = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
sparse_index &= PAPI_PRESET_AND_MASK;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* allocate and initialize data space for this event */
|
|
Packit Service |
a1973e |
papi_valid_free( _papi_hwi_presets[sparse_index].data );
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].data =
|
|
Packit Service |
a1973e |
papi_malloc( sizeof ( hwi_preset_data_t ) );
|
|
Packit Service |
a1973e |
native_index = 0;
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].data->native[native_index] = PAPI_NULL;
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].data->operation[0] = '\0';
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( attr[2] ) { /* derived event */
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].data->derived =
|
|
Packit Service |
a1973e |
_papi_hwi_derived_type( ( char * ) attr[3] );
|
|
Packit Service |
a1973e |
/* where does DERIVED POSTSCRIPT get encoded?? */
|
|
Packit Service |
a1973e |
if ( _papi_hwi_presets[sparse_index].data->derived == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "No derived type match for %s in Preset XML file.",
|
|
Packit Service |
a1973e |
attr[3] );
|
|
Packit Service |
a1973e |
error = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( attr[5] ) {
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].count = atoi( attr[5] );
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
PAPIERROR( "No count given for %s in Preset XML file.",
|
|
Packit Service |
a1973e |
attr[1] );
|
|
Packit Service |
a1973e |
error = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].data->derived = NOT_DERIVED;
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].count = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
location = DENSE_NATIVE_SEARCH;
|
|
Packit Service |
a1973e |
} else if ( location == DENSE_NATIVE_SEARCH && !strcmp( "native", el ) ) {
|
|
Packit Service |
a1973e |
location = DENSE_NATIVE_DESC;
|
|
Packit Service |
a1973e |
} else if ( location == DENSE_NATIVE_DESC && !strcmp( "event", el ) ) {
|
|
Packit Service |
a1973e |
if ( _papi_hwi_native_name_to_code( attr[1], &native_encoding ) !=
|
|
Packit Service |
a1973e |
PAPI_OK ) {
|
|
Packit Service |
a1973e |
printf( "Improper Native name given in XML file for %s\n",
|
|
Packit Service |
a1973e |
attr[1] );
|
|
Packit Service |
a1973e |
PAPIERROR( "Improper Native name given in XML file for %s",
|
|
Packit Service |
a1973e |
attr[1] );
|
|
Packit Service |
a1973e |
error = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].data->native[native_index] =
|
|
Packit Service |
a1973e |
native_encoding;
|
|
Packit Service |
a1973e |
native_index++;
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].data->native[native_index] = PAPI_NULL;
|
|
Packit Service |
a1973e |
} else if ( location && location != ARCH_SEARCH && location != FINISHED ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "Poorly-formed Preset XML document." );
|
|
Packit Service |
a1973e |
error = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* The function below, _xml_end(), is a hook into expat's XML
|
|
Packit Service |
a1973e |
* parser. _xml_end() defines how the parser handles the
|
|
Packit Service |
a1973e |
* end tags in PAPI's XML file.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
_xml_end( void *data, const char *el )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( location == SPARSE_EVENT_SEARCH && !strcmp( "papistdevents", el ) ) {
|
|
Packit Service |
a1973e |
for ( i = sparse_index; i < PAPI_MAX_PRESET_EVENTS; i++ ) {
|
|
Packit Service |
a1973e |
_papi_hwi_presets[i].info.symbol = NULL;
|
|
Packit Service |
a1973e |
_papi_hwi_presets[i].info.long_descr = NULL;
|
|
Packit Service |
a1973e |
_papi_hwi_presets[i].info.short_descr = NULL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
location = ARCH_SEARCH;
|
|
Packit Service |
a1973e |
} else if ( location == DENSE_NATIVE_DESC && !strcmp( "native", el ) ) {
|
|
Packit Service |
a1973e |
location = DENSE_EVENT_SEARCH;
|
|
Packit Service |
a1973e |
} else if ( location == DENSE_EVENT_SEARCH && !strcmp( "availevents", el ) ) {
|
|
Packit Service |
a1973e |
location = FINISHED;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* The function below, _xml_content(), is a hook into expat's XML
|
|
Packit Service |
a1973e |
* parser. _xml_content() defines how the parser handles the
|
|
Packit Service |
a1973e |
* text between tags in PAPI's XML file. The information between
|
|
Packit Service |
a1973e |
* tags is usally text for event descriptions.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
_xml_content( void *data, const char *el, const int len )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
if ( location == SPARSE_DESC ) {
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].info.long_descr =
|
|
Packit Service |
a1973e |
papi_malloc( len + 1 );
|
|
Packit Service |
a1973e |
for ( i = 0; i < len; i++ )
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].info.long_descr[i] = el[i];
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].info.long_descr[len] = '\0';
|
|
Packit Service |
a1973e |
/* the XML data currently doesn't contain a short description */
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].info.short_descr = NULL;
|
|
Packit Service |
a1973e |
sparse_index++;
|
|
Packit Service |
a1973e |
_papi_hwi_presets[sparse_index].data = NULL;
|
|
Packit Service |
a1973e |
location = SPARSE_EVENT_SEARCH;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_xml_papi_hwi_setup_all_presets( char *arch, hwi_dev_notes_t * notes )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int done = 0;
|
|
Packit Service |
a1973e |
FILE *fp = fopen( "./papi_events.xml", "r" );
|
|
Packit Service |
a1973e |
XML_Parser p = XML_ParserCreate( NULL );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( !p ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "Couldn't allocate memory for XML parser." );
|
|
Packit Service |
a1973e |
fclose(fp);
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
XML_SetElementHandler( p, _xml_start, _xml_end );
|
|
Packit Service |
a1973e |
XML_SetCharacterDataHandler( p, _xml_content );
|
|
Packit Service |
a1973e |
if ( fp == NULL ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "Error opening Preset XML file." );
|
|
Packit Service |
a1973e |
fclose(fp);
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
xml_arch = arch;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
do {
|
|
Packit Service |
a1973e |
int len;
|
|
Packit Service |
a1973e |
void *buffer = XML_GetBuffer( p, BUFFSIZE );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( buffer == NULL ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "Couldn't allocate memory for XML buffer." );
|
|
Packit Service |
a1973e |
fclose(fp);
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
len = fread( buffer, 1, BUFFSIZE, fp );
|
|
Packit Service |
a1973e |
if ( ferror( fp ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "XML read error." );
|
|
Packit Service |
a1973e |
fclose(fp);
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
done = feof( fp );
|
|
Packit Service |
a1973e |
if ( !XML_ParseBuffer( p, len, len == 0 ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "Parse error at line %d:\n%s",
|
|
Packit Service |
a1973e |
XML_GetCurrentLineNumber( p ),
|
|
Packit Service |
a1973e |
XML_ErrorString( XML_GetErrorCode( p ) ) );
|
|
Packit Service |
a1973e |
fclose(fp);
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( error ) {
|
|
Packit Service |
a1973e |
fclose(fp);
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} while ( !done );
|
|
Packit Service |
a1973e |
XML_ParserFree( p );
|
|
Packit Service |
a1973e |
fclose( fp );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|