papi_preset.c File Reference

Include dependency graph for papi_preset.c:

Go to the source code of this file.

Defines

#define PAPI_EVENT_FILE   "papi_events.csv"

Functions

static int papi_load_derived_events (char *pmu_str, int pmu_type, int cidx, int preset_flag)
int _papi_hwi_setup_all_presets (hwi_search_t *findem, int cidx)
int _papi_hwi_cleanup_all_presets (void)
static char * trim_string (char *in)
static char * trim_note (char *in)
static int find_event_index (hwi_presets_t *array, int size, char *tmp)
static FILE * open_event_table (char *name)
static int get_event_line (char *line, FILE *table, char **tmp_perfmon_events_table)
static void update_ops_string (char **formula, int old_index, int new_index)
static void ops_string_append (hwi_presets_t *results, hwi_presets_t *depends_on, int addition)
static void ops_string_merge (char **original, char *insertion, int replaces, int start_index)
static int check_derived_events (char *target, int derived_type, hwi_presets_t *results, hwi_presets_t *search, int search_size, int token_index)
static int check_native_events (char *target, hwi_presets_t *results)
static int is_event (char *event_name, int derived_type, hwi_presets_t *results, int token_index)
int _papi_load_preset_table (char *pmu_str, int pmu_type, int cidx)
static int priority (char symbol)
static int push (char symbol)
static char pop ()
static char * infix_to_postfix (char *infix)

Variables

hwi_presets_t user_defined_events []
int user_defined_events_count
static char * papi_events_table = NULL
static char stack [2 *PAPI_HUGE_STR_LEN]
static int stacktop = -1

Define Documentation

#define PAPI_EVENT_FILE   "papi_events.csv"

Definition at line 151 of file papi_preset.c.


Function Documentation

int _papi_hwi_cleanup_all_presets ( void   ) 

Definition at line 114 of file papi_preset.c.

00115 {
00116         int preset_index,cidx;
00117     unsigned int j;
00118 
00119     for ( preset_index = 0; preset_index < PAPI_MAX_PRESET_EVENTS;
00120           preset_index++ ) {
00121         if ( _papi_hwi_presets[preset_index].postfix != NULL ) {
00122            papi_free( _papi_hwi_presets[preset_index].postfix );
00123            _papi_hwi_presets[preset_index].postfix = NULL;
00124         }
00125         if ( _papi_hwi_presets[preset_index].note != NULL ) {
00126            papi_free( _papi_hwi_presets[preset_index].note );
00127            _papi_hwi_presets[preset_index].note = NULL;
00128         }
00129         for(j=0; j<_papi_hwi_presets[preset_index].count;j++) {
00130            papi_free(_papi_hwi_presets[preset_index].name[j]);
00131         }
00132     }
00133 
00134     for(cidx=0;cidx<papi_num_components;cidx++) {
00135        _papi_hwd[cidx]->cmp_info.num_preset_events = 0;
00136     }
00137 
00138 #if defined(ITANIUM2) || defined(ITANIUM3)
00139     /* NOTE: This memory may need to be freed for BG/P builds as well */
00140     if ( preset_search_map != NULL ) {
00141         papi_free( preset_search_map );
00142         preset_search_map = NULL;
00143     }
00144 #endif
00145 
00146     return PAPI_OK;
00147 }

Here is the caller graph for this function:

int _papi_hwi_setup_all_presets ( hwi_search_t findem,
int  cidx 
)

Definition at line 44 of file papi_preset.c.

00045 {
00046     int i, pnum, did_something = 0;
00047     unsigned int preset_index, j, k;
00048 
00049     /* dense array of events is terminated with a 0 preset.
00050        don't do anything if NULL pointer. This allows just notes to be loaded.
00051        It's also good defensive programming.
00052      */
00053     if ( findem != NULL ) {
00054        for ( pnum = 0; ( pnum < PAPI_MAX_PRESET_EVENTS ) &&
00055               ( findem[pnum].event_code != 0 ); pnum++ ) {
00056        /* find the index for the event to be initialized */
00057        preset_index = ( findem[pnum].event_code & PAPI_PRESET_AND_MASK );
00058        /* count and set the number of native terms in this event, 
00059               these items are contiguous.
00060 
00061           PAPI_EVENTS_IN_DERIVED_EVENT is arbitrarily defined in the high 
00062               level to be a reasonable number of terms to use in a derived 
00063               event linear expression, currently 8.
00064 
00065           This wastes space for components with less than 8 counters, 
00066               but keeps the framework independent of the components.
00067 
00068           The 'native' field below is an arbitrary opaque identifier 
00069               that points to information on an actual native event. 
00070               It is not an event code itself (whatever that might mean).
00071           By definition, this value can never == PAPI_NULL.
00072           - dkt */
00073 
00074        INTDBG( "Counting number of terms for preset index %d, "
00075                    "search map index %d.\n", preset_index, pnum );
00076        i = 0;
00077        j = 0;
00078        while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
00079           if ( findem[pnum].native[i] != PAPI_NULL ) {
00080          j++;
00081           }
00082           else if ( j ) {
00083          break;
00084           }
00085           i++;
00086        }
00087 
00088        INTDBG( "This preset has %d terms.\n", j );
00089        _papi_hwi_presets[preset_index].count = j;
00090  
00091            _papi_hwi_presets[preset_index].derived_int = findem[pnum].derived;
00092        for(k=0;k<j;k++) {
00093               _papi_hwi_presets[preset_index].code[k] =
00094                      findem[pnum].native[k];
00095        }
00096        /* preset code list must be PAPI_NULL terminated */
00097        if (k<PAPI_EVENTS_IN_DERIVED_EVENT) {
00098               _papi_hwi_presets[preset_index].code[k] = PAPI_NULL;
00099        }
00100 
00101        _papi_hwi_presets[preset_index].postfix=
00102                                        papi_strdup(findem[pnum].operation);
00103 
00104        did_something++;
00105        }
00106     }
00107 
00108     _papi_hwd[cidx]->cmp_info.num_preset_events += did_something;
00109 
00110     return ( did_something ? PAPI_OK : PAPI_ENOEVNT );
00111 }

Here is the caller graph for this function:

int _papi_load_preset_table ( char *  pmu_str,
int  pmu_type,
int  cidx 
)

Definition at line 771 of file papi_preset.c.

00771                                                                    {
00772     SUBDBG("ENTER: pmu_str: %s, pmu_type: %d, cidx: %d\n", pmu_str, pmu_type, cidx);
00773 
00774     int retval;
00775 
00776     // go load papi preset events (last argument tells function if we are loading presets or user events)
00777     retval = papi_load_derived_events(pmu_str, pmu_type, cidx, 1);
00778     if (retval != PAPI_OK) {
00779         SUBDBG("EXIT: retval: %d\n", retval);
00780         return retval;
00781     }
00782 
00783     // go load the user defined event definitions if any are defined
00784     retval = papi_load_derived_events(pmu_str, pmu_type, cidx, 0);
00785 
00786     SUBDBG("EXIT: retval: %d\n", retval);
00787     return retval;
00788 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int check_derived_events ( char *  target,
int  derived_type,
hwi_presets_t results,
hwi_presets_t search,
int  search_size,
int  token_index 
) [static]

Definition at line 617 of file papi_preset.c.

00618 {
00619     INTDBG("ENTER: target: %p (%s), results: %p, search: %p, search_size: %d, token_index: %d\n", target, target, results, search, search_size, token_index);
00620     unsigned int i;
00621     int j;
00622     int k;
00623     int found = 0;
00624 
00625     for (j=0; j < search_size; j++) {
00626         //  INTDBG("search[%d].symbol: %s, looking for: %s\n", j, search[j].symbol, target);
00627         if (search[j].symbol == NULL) {
00628             INTDBG("EXIT: returned: 0\n");
00629             return 0;
00630         }
00631 
00632         // if not the event we depend on, just look at next
00633         if ( strcasecmp( target, search[j].symbol) != 0 ) {
00634             continue;
00635         }
00636 
00637         INTDBG("Found a match\n");
00638 
00639         // derived formulas need to be adjusted based on what kind of derived event we are processing
00640         // the derived type passed to this function is the type of the new event being defined (not the events it is based on)
00641         // when we get here the formula must be in reverse polish notation (RPN) format
00642         switch (derived_type) {
00643             case DERIVED_POSTFIX: {
00644                 // go create a formula to merge the second formula into a spot identified by one of the tokens in
00645                 // the first formula.
00646                 ops_string_merge(&(results->postfix), search[j].postfix, token_index, results->count);
00647                 break;
00648             }
00649             case DERIVED_ADD: {
00650                 // the new derived event adds two things together, go handle this target events role in the add
00651                 ops_string_append(results, &search[j], 1);
00652                 break;
00653             }
00654             case DERIVED_SUB: {
00655                 // go create a formula to subtract the value generated by the second formula from the value generated by the first formula.
00656                 ops_string_append(results, &search[j], 0);
00657                 break;
00658             }
00659                 default: {
00660                 INTDBG("Derived type: %d, not currently handled\n", derived_type);
00661                 break;
00662             }
00663         }
00664 
00665         // copy event name and code used by the derived event into the results table (place where new derived event is getting created)
00666         for ( k = 0; k < (int)search[j].count; k++ ) {
00667 //          INTDBG("search[%d]: %p, name[%d]: %s, code[%d]: %#x\n", j, &search[j], k, search[j].name[k], k, search[j].code[k]);
00668             // if this event is already in the list, just update the formula so that references to this event point to the existing one
00669             for (i=0 ; i < results->count ; i++) {
00670                 if (results->code[i] == search[j].code[k]) {
00671                     INTDBG("event: %s, code: %#x, already in results at index: %d\n", search[j].name[k], search[j].code[k], i);
00672                     // replace all tokens in the formula that refer to index "results->count + found" with a token that refers to index "i".
00673                     // the index "results->count + found" identifies the index used in the formula for the event we just determined is a duplicate
00674                     update_ops_string(&(results->postfix), results->count + found, i);
00675                     found++;
00676                     break;
00677                 }
00678             }
00679 
00680             // if we did not find a match, copy native event info into results array
00681             if (found == 0) {
00682                 // not a duplicate, go ahead and copy into results and bump number of native events in results
00683                 if (search[j].name[k]) {
00684                     results->name[results->count] = papi_strdup(search[j].name[k]);
00685                 } else {
00686                     results->name[results->count] = papi_strdup(target);
00687                 }
00688                 results->code[results->count] = search[j].code[k];
00689                 INTDBG("results: %p, name[%d]: %s, code[%d]: %#x\n", results, results->count, results->name[results->count], results->count, results->code[results->count]);
00690 
00691                 results->count++;
00692             }
00693         }
00694 
00695         INTDBG("EXIT: returned: 1\n");
00696         return 1;
00697     }
00698 
00699     INTDBG("EXIT: returned: 0\n");
00700     return 0;
00701 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int check_native_events ( char *  target,
hwi_presets_t results 
) [static]

Definition at line 704 of file papi_preset.c.

00705 {
00706     INTDBG("ENTER: target: %p (%s), results: %p\n", target, target, results);
00707     int ret;
00708 
00709     // find this native events code
00710     if ( ( ret = _papi_hwi_native_name_to_code( target, (int *)(&results->code[results->count])) ) != PAPI_OK ) {
00711         INTDBG("EXIT: returned: 0, call to convert name to event code failed with ret: %d\n", ret);
00712         return 0;
00713     }
00714 
00715     // if the code returned was 0, return to show it is not a valid native event
00716     if ( results->code[results->count] == 0 ) {
00717         INTDBG( "EXIT: returned: 0, event code not found\n");
00718         return 0;
00719     }
00720 
00721     // if this native event is not for component 0, return to show it can not be used in derived events
00722     // 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
00723     if ( _papi_hwi_component_index(results->code[results->count]) != 0 ) {
00724         INTDBG( "EXIT: returned: 0, new event not associated with component 0 (current limitation with derived events)\n");
00725         return 0;
00726     }
00727 
00728     //    found = 1;
00729     INTDBG("\tFound a native event %s\n", target);
00730     results->name[results->count++] = papi_strdup(target);
00731 
00732     INTDBG( "EXIT: returned: 1\n");
00733     return 1;
00734 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int find_event_index ( hwi_presets_t array,
int  size,
char *  tmp 
) [inline, static]

Definition at line 225 of file papi_preset.c.

00225                                                             {
00226     SUBDBG("ENTER: array: %p, size: %d, tmp: %s\n", array, size, tmp);
00227     int i;
00228     for (i = 0; i < size; i++) {
00229         if (array[i].symbol == NULL) {
00230             array[i].symbol = papi_strdup(tmp);
00231             SUBDBG("EXIT: i: %d\n", i);
00232             return i;
00233         }
00234         if (strcasecmp(tmp, array[i].symbol) == 0) {
00235             SUBDBG("EXIT: i: %d\n", i);
00236             return i;
00237         }
00238     }
00239     SUBDBG("EXIT: PAPI_EINVAL\n");
00240     return PAPI_EINVAL;
00241 }

Here is the caller graph for this function:

static int get_event_line ( char *  line,
FILE *  table,
char **  tmp_perfmon_events_table 
) [static]

Definition at line 273 of file papi_preset.c.

00274 {
00275     int i;
00276 
00277     if ( table ) {
00278         if ( fgets( line, LINE_MAX, table ) == NULL)
00279         return 0;
00280 
00281         i = ( int ) strlen( line );
00282         if (i == 0)
00283         return 0;
00284         if ( line[i-1] == '\n' )
00285         line[i-1] = '\0';
00286         return 1;
00287     } else {
00288         for ( i = 0;
00289               **tmp_perfmon_events_table && **tmp_perfmon_events_table != '\n';
00290               i++, ( *tmp_perfmon_events_table )++ )
00291             line[i] = **tmp_perfmon_events_table;
00292         if (i == 0)
00293             return 0;
00294         if ( **tmp_perfmon_events_table && **tmp_perfmon_events_table == '\n' ) {
00295             ( *tmp_perfmon_events_table )++;
00296         }
00297         line[i] = '\0';
00298         return 1;
00299     }
00300 }

Here is the caller graph for this function:

static char* infix_to_postfix ( char *  infix  )  [static]

Definition at line 839 of file papi_preset.c.

00839                                 {
00840     INTDBG("ENTER: in: %s, size: %zu\n", infix, strlen(infix));
00841     static char postfix[2*PAPI_HUGE_STR_LEN];   // output
00842         unsigned int index;
00843         int postfixlen;
00844         char token;
00845         if ( strlen(infix) > PAPI_HUGE_STR_LEN ) 
00846             PAPIERROR("A infix string (probably in user-defined presets) is too big (max allowed %d): %s", PAPI_HUGE_STR_LEN, infix );
00847 
00848         // initialize stack
00849     memset(stack, 0, 2*PAPI_HUGE_STR_LEN);
00850     stacktop = -1; 
00851     push('#'); 
00852         stacktop = 0; // after initialization of stack to #
00853         /* initialize output string */
00854     memset(postfix,0,2*PAPI_HUGE_STR_LEN);
00855         postfixlen = 0;
00856 
00857     for( index=0; index<strlen(infix); index++ ) {
00858                 token = infix[index];
00859                 INTDBG("INTDBG: in: %s, length: %zu, index: %d token %c\n", infix, strlen( infix ), index, token);
00860         switch( token ) {
00861         case '(':
00862             push( token );
00863             break;
00864         case ')':
00865                         if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
00866                         while ( stack[stacktop] != '(' ) {
00867                                 postfix[postfixlen++] = pop();
00868                                 postfix[postfixlen++] = '|';
00869                         }
00870                         token = pop();  /* pop the '(' character */
00871             break;
00872         case '+':
00873         case '-':
00874         case '*':
00875         case '/':
00876         case '%':
00877         case '^':       /* if an operator */
00878                         if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
00879                         while ( priority(stack[stacktop]) > priority(token) ) {
00880                                 postfix[postfixlen++] = pop();
00881                                 postfix[postfixlen++] = '|';
00882                         }
00883                         push( token ); /* save current operator */
00884                         break;
00885         default: // if alphanumeric character which is not parenthesis or an operator
00886                         postfix[postfixlen++] = token;
00887             break;
00888         } // end switch symbol
00889     } // end while
00890 
00891         /* Write any remaining operators */
00892         if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
00893         while ( stacktop>0 ) {
00894                 postfix[postfixlen++] = pop();
00895                 postfix[postfixlen++] = '|';
00896         }
00897         postfix[postfixlen++] = '\0';
00898     stacktop = -1; 
00899 
00900     INTDBG("EXIT: postfix: %s, size: %zu\n", postfix, strlen(postfix));
00901     return (postfix);
00902 } // end infix_to_postfix

Here is the call graph for this function:

Here is the caller graph for this function:

static int is_event ( char *  event_name,
int  derived_type,
hwi_presets_t results,
int  token_index 
) [static]

Definition at line 739 of file papi_preset.c.

00739                                                                                       {
00740     INTDBG("ENTER: event_name: %p (%s), derived_type: %d, results: %p, token_index: %d\n", event_name, event_name, derived_type, results, token_index);
00741 
00742     /* check if its a preset event */
00743     if ( check_derived_events(event_name, derived_type, results, &_papi_hwi_presets[0], PAPI_MAX_PRESET_EVENTS, token_index) ) {
00744         INTDBG("EXIT: found preset event\n");
00745         return 1;
00746     }
00747 
00748     /* check if its a user defined event */
00749     if ( check_derived_events(event_name, derived_type, results, user_defined_events, user_defined_events_count, token_index) ) {
00750         INTDBG("EXIT: found user event\n");
00751         return 1;
00752     }
00753 
00754     /* check if its a native event */
00755     if ( check_native_events(event_name, results) ) {
00756         INTDBG("EXIT: found native event\n");
00757         return 1;
00758     }
00759 
00760     INTDBG("EXIT: event not found\n");
00761     return 0;
00762 }

Here is the call graph for this function:

Here is the caller graph for this function:

static FILE* open_event_table ( char *  name  )  [static]

Definition at line 246 of file papi_preset.c.

00247 {
00248     FILE *table;
00249 
00250     SUBDBG( "Opening %s\n", name );
00251     table = fopen( name, "r" );
00252     if ( table == NULL ) {
00253         SUBDBG( "Open %s failed, trying ./%s.\n", 
00254             name, PAPI_EVENT_FILE );
00255         sprintf( name, "%s", PAPI_EVENT_FILE );
00256         table = fopen( name, "r" );
00257     }
00258     if ( table == NULL ) {
00259         SUBDBG( "Open ./%s failed, trying ../%s.\n", 
00260             name, PAPI_EVENT_FILE );
00261         sprintf( name, "../%s", PAPI_EVENT_FILE );
00262         table = fopen( name, "r" );
00263     }
00264     if ( table ) {
00265         SUBDBG( "Open %s succeeded.\n", name );
00266     }
00267     return table;
00268 }

Here is the caller graph for this function:

static void ops_string_append ( hwi_presets_t results,
hwi_presets_t depends_on,
int  addition 
) [static]

Definition at line 363 of file papi_preset.c.

00363                                                                                    {
00364     INTDBG("ENTER: results: %p, depends_on: %p, addition %d\n", results, depends_on, addition);
00365 
00366     int i;
00367     int second_event = 0;
00368     char newFormula[PAPI_MIN_STR_LEN] = "";
00369     char work[20];
00370 
00371     // if our results already have a formula, start with what was collected so far
00372     // this should only happens when processing the second event of a new derived add
00373     if (results->postfix != NULL) {
00374         INTDBG("Event %s has existing formula %s\n", results->symbol, results->postfix);
00375         // get the existing formula
00376         strncat(newFormula, results->postfix, sizeof(newFormula)-1);
00377         newFormula[sizeof(newFormula)-1] = '\0';
00378         second_event = 1;
00379     }
00380 
00381     // process based on what kind of event the one we depend on is
00382     switch (depends_on->derived_int) {
00383         case DERIVED_POSTFIX: {
00384             // the event we depend on has a formula, append it our new events formula
00385 
00386             // if event we depend on does not have a formula, report error
00387             if (depends_on->postfix == NULL) {
00388                 INTDBG("Event %s is of type DERIVED_POSTFIX but is missing operation string\n", depends_on->symbol);
00389                 return;
00390             }
00391 
00392             // may need to renumber the native event index values in the depends on event formula before putting it into new derived event
00393             char *temp = papi_strdup(depends_on->postfix);
00394 
00395             // If this is not the first event of the new derived add, need to adjust native event index values in formula.
00396             // At this time we assume that all the native events in the second events formula are unique for the new event
00397             // and just bump the indexes by the number of events already known to the new event.  Later when we add the events
00398             // to the native event list for this new derived event, we will check to see if the native events are already known
00399             // to the new derived event and if so adjust the indexes again.
00400             if (second_event) {
00401                 for ( i=depends_on->count-1 ; i>=0 ; i--) {
00402                     update_ops_string(&temp, i, results->count + i);
00403                 }
00404             }
00405 
00406             // append the existing formula from the event we depend on (but get rid of last '|' character)
00407             strncat(newFormula, temp, sizeof(newFormula)-1);
00408             newFormula[sizeof(newFormula)-1] = '\0';
00409             papi_free (temp);
00410             break;
00411         }
00412         case DERIVED_ADD: {
00413             // the event we depend on has no formula, create a formula for our new event to add together the depends_on native event values
00414 
00415             // build a formula for this add event
00416             sprintf(work, "N%d|N%d|+|", results->count, results->count + 1);
00417             strcat(newFormula, work);
00418             break;
00419         }
00420         case DERIVED_SUB: {
00421             // the event we depend on has no formula, create a formula for our new event to subtract the depends_on native event values
00422 
00423             // build a formula for this subtract event
00424             sprintf(work, "N%d|N%d|-|", results->count, results->count + 1);
00425             strcat(newFormula, work);
00426             break;
00427         }
00428         case NOT_DERIVED: {
00429             // 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
00430 
00431             // build a formula for this subtract event
00432             sprintf(work, "N%d|", results->count);
00433             strcat(newFormula, work);
00434             break;
00435         }
00436         default: {
00437             // the event we depend on has unsupported derived type, put out some debug and give up
00438             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);
00439             return;
00440         }
00441     }
00442 
00443     // if this was the second event, append to the formula an operation to add or subtract the results of the two events
00444     if (second_event) {
00445         if (addition != 0) {
00446             strcat(newFormula, "+|");
00447         } else {
00448             strcat(newFormula, "-|");
00449         }
00450         // also change the new derived events type to show it has a formula now
00451         results->derived_int = DERIVED_POSTFIX;
00452     }
00453 
00454     // we need to free the existing space (created by malloc and we need to create a new one)
00455     papi_free (results->postfix);
00456     results->postfix = papi_strdup(newFormula);
00457     INTDBG("EXIT: newFormula: %s\n", newFormula);
00458     return;
00459 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void ops_string_merge ( char **  original,
char *  insertion,
int  replaces,
int  start_index 
) [static]

Definition at line 464 of file papi_preset.c.

00464                                                                                   {
00465     INTDBG("ENTER: original: %p, *original: %s, insertion: %s, replaces: %d, start_index: %d\n", original, *original, insertion, replaces, start_index);
00466 
00467     int orig_len=0;
00468     int ins_len=0;
00469     char *subtoken;
00470     char *workBuf;
00471     char *workPtr;
00472     char *tok_save_ptr;
00473     char *newOriginal;
00474     char *newInsertion;
00475     char *newFormula;
00476     int insert_events;
00477 
00478     if (*original != NULL) {
00479         orig_len = strlen(*original);
00480     }
00481     if (insertion != NULL) {
00482         ins_len = strlen(insertion);
00483     }
00484     newFormula = papi_calloc (orig_len + ins_len + 40, 1);
00485 
00486     // if insertion formula is not provided, then the original formula remains basically unchanged.
00487     if (insertion == NULL) {
00488         // if the original formula has a leading '|' then get rid of it
00489         workPtr = *original;
00490         if (workPtr[0] == '|') {
00491             strcpy(newFormula, &workPtr[1]);
00492         } else {
00493             strcpy(newFormula, workPtr);
00494         }
00495         // formula fields are always malloced space so free the previous one
00496         papi_free (*original);
00497         *original = newFormula;
00498         INTDBG("EXIT: newFormula: %s\n", *original);
00499         return;
00500     }
00501 
00502     // renumber the token numbers in the insertion formula
00503     // also count how many native events are used in this formula
00504     insert_events = 0;
00505     newInsertion = papi_calloc(ins_len+20, 1);
00506     workBuf = papi_calloc(ins_len+10, 1);
00507     workPtr = papi_strdup(insertion);
00508     subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
00509     while ( subtoken != NULL) {
00510 //      INTDBG("subtoken: %s, newInsertion: %s\n", subtoken, newInsertion);
00511         if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))) {
00512             insert_events++;
00513             int val = atoi(&subtoken[1]);
00514             val += start_index;
00515             subtoken[1] = '\0';
00516             sprintf (workBuf, "N%d", val);
00517         } else {
00518             strcpy(workBuf, subtoken);
00519         }
00520         strcat (newInsertion, workBuf);
00521         strcat (newInsertion, "|");
00522         subtoken = strtok_r(NULL, "|", &tok_save_ptr);
00523     }
00524     papi_free (workBuf);
00525     papi_free (workPtr);
00526     INTDBG("newInsertion: %s\n", newInsertion);
00527 
00528     // if original formula is not provided, then the updated insertion formula becomes the new formula
00529     // but we still had to renumber the native event tokens in case another native event was put into the list first
00530     if (*original == NULL) {
00531         *original = papi_strdup(newInsertion);
00532         INTDBG("EXIT: newFormula: %s\n", newInsertion);
00533         papi_free (newInsertion);
00534         papi_free (newFormula);
00535         return;
00536     }
00537 
00538     // if token to replace not valid, return null  (do we also need to check an upper bound ???)
00539     if ((replaces < 0)) {
00540         papi_free (newInsertion);
00541         papi_free (newFormula);
00542         INTDBG("EXIT: Invalid value for token in original formula to be replaced\n");
00543         return;
00544     }
00545 
00546     // renumber the token numbers in the original formula
00547     // tokens with an index greater than the replaces token need to be incremented by number of events in insertion formula-1
00548     newOriginal = papi_calloc (orig_len+20, 1);
00549     workBuf = papi_calloc(orig_len+10, 1);
00550     workPtr = papi_strdup(*original);
00551 
00552     subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
00553     while ( subtoken != NULL) {
00554 //      INTDBG("subtoken: %s, newOriginal: %s\n", subtoken, newOriginal);
00555         // prime the work area with the next token, then see if we need to change it
00556         strcpy(workBuf, subtoken);
00557         if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))) {
00558             int val = atoi(&subtoken[1]);
00559             if (val > replaces) {
00560                 val += insert_events-1;
00561                 subtoken[1] = '\0';
00562                 sprintf (workBuf, "N%d", val);
00563             }
00564         }
00565         // put the work buffer into the new original formula
00566         strcat (newOriginal, workBuf);
00567         strcat (newOriginal, "|");
00568         subtoken = strtok_r(NULL, "|", &tok_save_ptr);
00569     }
00570     papi_free (workBuf);
00571     papi_free (workPtr);
00572     INTDBG("newOriginal: %s\n", newOriginal);
00573 
00574     // replace the specified "replace" tokens in the new original formula with the new insertion formula
00575     newFormula[0] = '\0';
00576     workPtr = newOriginal;
00577     subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
00578     while ( subtoken != NULL) {
00579 //      INTDBG("subtoken: %s, newFormula: %s\n", subtoken, newFormula);
00580         // if this is the token we want to replace with the insertion string, do it now
00581         if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))  &&  (replaces == atoi(&subtoken[1]))) {
00582             // copy updated insertion string into the original string (replacing this token)
00583             strcat(newFormula, newInsertion);
00584         } else {
00585             // copy this part of the original formula into the new formula
00586             strcat(newFormula, subtoken);
00587             strcat(newFormula, "|");
00588         }
00589         subtoken = strtok_r(NULL, "|", &tok_save_ptr);
00590     }
00591     papi_free (newInsertion);
00592     papi_free (workPtr);
00593 
00594     // formula fields are always malloced space so free the previous one
00595     papi_free (*original);
00596     *original = newFormula;
00597     INTDBG("EXIT: newFormula: %s\n", newFormula);
00598     return;
00599 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int papi_load_derived_events ( char *  pmu_str,
int  pmu_type,
int  cidx,
int  preset_flag 
) [static]

Definition at line 947 of file papi_preset.c.

00947                                                                                   {
00948     SUBDBG( "ENTER: pmu_str: %s, pmu_type: %d, cidx: %d, preset_flag: %d\n", pmu_str, pmu_type, cidx, preset_flag);
00949 
00950     char pmu_name[PAPI_MIN_STR_LEN];
00951     char line[LINE_MAX];
00952     char name[PATH_MAX] = "builtin papi_events_table";
00953     char *event_file_path=NULL;
00954     char *event_table_ptr=NULL;
00955     int event_type_bits = 0;
00956     char *tmpn;
00957     char *tok_save_ptr=NULL;
00958     FILE *event_file = NULL;
00959     hwi_presets_t *results=NULL;
00960     int result_size = 0;
00961     int *event_count = NULL;
00962     int invalid_event;
00963     int line_no = 0;  /* count of lines read from event definition input */
00964     int derived = 0;
00965     int res_idx = 0;  /* index into results array for where to store next event */
00966     int preset = 0;
00967     int get_events = 0; /* only process derived events after CPU type they apply to is identified      */
00968     int found_events = 0; /* flag to track if event definitions (PRESETS) are found since last CPU declaration */
00969 #ifdef PAPI_DATADIR
00970         char path[PATH_MAX];
00971 #endif
00972 
00973 
00974     if (preset_flag) {
00975         /* try the environment variable first */
00976         if ((tmpn = getenv("PAPI_CSV_EVENT_FILE")) && (strlen(tmpn) > 0)) {
00977             event_file_path = tmpn;
00978         }
00979         /* if no valid environment variable, look for built-in table */
00980         else if (papi_events_table) {
00981             event_table_ptr = papi_events_table;
00982         }
00983         /* if no env var and no built-in, search for default file */
00984         else {
00985 #ifdef PAPI_DATADIR
00986             sprintf( path, "%s/%s", PAPI_DATADIR, PAPI_EVENT_FILE );
00987             event_file_path = path;
00988 #else
00989             event_file_path = PAPI_EVENT_FILE;
00990 #endif
00991         }
00992         event_type_bits = PAPI_PRESET_MASK;
00993         results = &_papi_hwi_presets[0];
00994         result_size = PAPI_MAX_PRESET_EVENTS;
00995         event_count = &_papi_hwd[cidx]->cmp_info.num_preset_events;
00996     } else {
00997         if ((event_file_path = getenv( "PAPI_USER_EVENTS_FILE" )) == NULL ) {
00998             SUBDBG("EXIT: User event definition file not provided.\n");
00999             return PAPI_OK;
01000         }
01001 
01002         event_type_bits = PAPI_UE_MASK;
01003         results = &user_defined_events[0];
01004         result_size = PAPI_MAX_USER_EVENTS;
01005         event_count = &user_defined_events_count;
01006     }
01007 
01008     // if we have an event file pathname, open it and read event definitions from the file
01009     if (event_file_path != NULL) {
01010         if ((event_file = open_event_table(event_file_path)) == NULL) {
01011             // if file open fails, return an error
01012             SUBDBG("EXIT: Event file open failed.\n");
01013             return PAPI_ESYS;
01014         }
01015         strncpy(name, event_file_path, sizeof(name)-1);
01016         name[sizeof(name)-1] = '\0';
01017     } else if (event_table_ptr == NULL) {
01018         // if we do not have a path name or table pointer, return an error
01019         SUBDBG("EXIT: Both event_file_path and event_table_ptr are NULL.\n");
01020         return PAPI_ESYS;
01021     }
01022 
01023     /* copy the pmu identifier, stripping commas if found */
01024     tmpn = pmu_name;
01025     while (*pmu_str) {
01026         if (*pmu_str != ',')
01027             *tmpn++ = *pmu_str;
01028         pmu_str++;
01029     }
01030     *tmpn = '\0';
01031 
01032     /* at this point we have either a valid file pointer or built-in table pointer */
01033     while (get_event_line(line, event_file, &event_table_ptr)) {
01034         char *t;
01035         int i;
01036 
01037         // increment number of lines we have read
01038         line_no++;
01039 
01040         t = trim_string(strtok_r(line, ",", &tok_save_ptr));
01041 
01042         /* Skip blank lines */
01043         if ((t == NULL) || (strlen(t) == 0))
01044             continue;
01045 
01046         /* Skip comments */
01047         if (t[0] == '#') {
01048             continue;
01049         }
01050 
01051         if (strcasecmp(t, "CPU") == 0) {
01052             if (get_events != 0 && found_events != 0) {
01053                 SUBDBG( "Ending event scanning at line %d of %s.\n", line_no, name);
01054                 get_events = 0;
01055                 found_events = 0;
01056             }
01057 
01058             t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01059             if ((t == NULL) || (strlen(t) == 0)) {
01060                 PAPIERROR("Expected name after CPU token at line %d of %s -- ignoring", line_no, name);
01061                 continue;
01062             }
01063 
01064             if (strcasecmp(t, pmu_name) == 0) {
01065                 int type;
01066 
01067                 SUBDBG( "Process events for PMU %s found at line %d of %s.\n", t, line_no, name);
01068 
01069                 t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01070                 if ((t == NULL) || (strlen(t) == 0)) {
01071                     SUBDBG("No additional qualifier found, matching on string.\n");
01072                     get_events = 1;
01073                 } else if ((sscanf(t, "%d", &type) == 1) && (type == pmu_type)) {
01074                     SUBDBG( "Found CPU %s type %d at line %d of %s.\n", pmu_name, type, line_no, name);
01075                     get_events = 1;
01076                 } else {
01077                     SUBDBG( "Additional qualifier match failed %d vs %d.\n", pmu_type, type);
01078                 }
01079             }
01080             continue;
01081         }
01082 
01083         if ((strcasecmp(t, "PRESET") == 0)  || (strcasecmp(t, "EVENT") == 0)) {
01084 
01085             if (get_events == 0)
01086                 continue;
01087 
01088             found_events = 1;
01089             t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01090 
01091             if ((t == NULL) || (strlen(t) == 0)) {
01092                 PAPIERROR("Expected name after PRESET token at line %d of %s -- ignoring", line_no, name);
01093                 continue;
01094             }
01095 
01096             SUBDBG( "Examining event %s\n", t);
01097 
01098             // see if this event already exists in the results array, if not already known it sets up event in unused entry
01099             if ((res_idx = find_event_index (results, result_size, t)) < 0) {
01100                 PAPIERROR("No room left for event %s -- ignoring", t);
01101                 continue;
01102             }
01103 
01104             // add the proper event bits (preset or user defined bits)
01105             preset = res_idx | event_type_bits;
01106             (void) preset;
01107 
01108             SUBDBG( "Use event code: %#x for %s\n", preset, t);
01109 
01110             t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01111             if ((t == NULL) || (strlen(t) == 0)) {
01112                 // got an error, make this entry unused
01113                 papi_free (results[res_idx].symbol);
01114                 results[res_idx].symbol = NULL;
01115                 PAPIERROR("Expected derived type after PRESET token at line %d of %s -- ignoring", line_no, name);
01116                 continue;
01117             }
01118 
01119             if (_papi_hwi_derived_type(t, &derived) != PAPI_OK) {
01120                 // got an error, make this entry unused
01121                 papi_free (results[res_idx].symbol);
01122                 results[res_idx].symbol = NULL;
01123                 PAPIERROR("Invalid derived name %s after PRESET token at line %d of %s -- ignoring", t, line_no, name);
01124                 continue;
01125             }
01126 
01127             /****************************************/
01128             /* Have an event, let's start assigning */
01129             /****************************************/
01130 
01131             SUBDBG( "Adding event: %s, code: %#x, derived: %d results[%d]: %p.\n", t, preset, derived, res_idx, &results[res_idx]);
01132 
01133             /* results[res_idx].event_code = preset; */
01134             results[res_idx].derived_int = derived;
01135 
01136             /* Derived support starts here */
01137             /* Special handling for postfix and infix */
01138             if ((derived == DERIVED_POSTFIX)  || (derived == DERIVED_INFIX)) {
01139                 t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01140                 if ((t == NULL) || (strlen(t) == 0)) {
01141                     // got an error, make this entry unused
01142                     papi_free (results[res_idx].symbol);
01143                     results[res_idx].symbol = NULL;
01144                     PAPIERROR("Expected Operation string after derived type DERIVED_POSTFIX or DERIVED_INFIX at line %d of %s -- ignoring", line_no, name);
01145                     continue;
01146                 }
01147 
01148                 // if it is an algebraic formula, we need to convert it to postfix
01149                 if (derived == DERIVED_INFIX) {
01150                     SUBDBG( "Converting InFix operations %s\n", t);
01151                     t = infix_to_postfix( t );
01152                     results[res_idx].derived_int = DERIVED_POSTFIX;
01153                 }
01154 
01155                 SUBDBG( "Saving PostFix operations %s\n", t);
01156                 results[res_idx].postfix = papi_strdup(t);
01157             }
01158 
01159             /* All derived terms collected here */
01160             i = 0;
01161             invalid_event = 0;
01162             results[res_idx].count = 0;
01163             do {
01164                 t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01165                 if ((t == NULL) || (strlen(t) == 0))
01166                     break;
01167                 if (strcasecmp(t, "NOTE") == 0)
01168                     break;
01169                 if (strcasecmp(t, "LDESC") == 0)
01170                     break;
01171                 if (strcasecmp(t, "SDESC") == 0)
01172                     break;
01173 
01174                 SUBDBG( "Adding term (%d) %s to derived event %#x, current native event count: %d.\n", i, t, preset, results[res_idx].count);
01175 
01176                 // show that we do not have an event code yet (the component may create one and update this info)
01177                 // this also clears any values left over from a previous call
01178                 _papi_hwi_set_papi_event_code(-1, -1);
01179 
01180                 // make sure that this term in the derived event is a valid event name
01181                 // this call replaces preset and user event names with the equivalent native events in our results table
01182                 // it also updates formulas for derived events so that they refer to the correct native event index
01183                 if (is_event(t, results[res_idx].derived_int, &results[res_idx], i) == 0) {
01184                     invalid_event = 1;
01185                     PAPIERROR("Error finding event %s, it is used in derived event %s", t, results[res_idx].symbol);
01186                     break;
01187                 }
01188 
01189                 i++;
01190             } while (results[res_idx].count < PAPI_EVENTS_IN_DERIVED_EVENT);
01191 
01192             /* preset code list must be PAPI_NULL terminated */
01193             if (i < PAPI_EVENTS_IN_DERIVED_EVENT) {
01194                 results[res_idx].code[results[res_idx].count] = PAPI_NULL;
01195             }
01196 
01197             if (invalid_event) {
01198                 // got an error, make this entry unused
01199                     // preset table is statically allocated, user defined is dynamic
01200                     if (!preset_flag) papi_free (results[res_idx].symbol);
01201                 results[res_idx].symbol = NULL;
01202                 continue;
01203             }
01204 
01205             /* End of derived support */
01206 
01207             // if we did not find any terms to base this derived event on, report error
01208             if (i == 0) {
01209                 // got an error, make this entry unused
01210               if (!preset_flag) papi_free (results[res_idx].symbol);
01211                 results[res_idx].symbol = NULL;
01212                 PAPIERROR("Expected PFM event after DERIVED token at line %d of %s -- ignoring", line_no, name);
01213                 continue;
01214             }
01215 
01216             if (i == PAPI_EVENTS_IN_DERIVED_EVENT) {
01217                 t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01218             }
01219 
01220             // if something was provided following the list of events to be used by the operation, process it
01221             if ( t!= NULL  && strlen(t) > 0 ) {
01222                 do {
01223                     // save the field name
01224                     char *fptr = papi_strdup(t);
01225 
01226                     // get the value to be used with this field
01227                     t = trim_note(strtok_r(NULL, ",", &tok_save_ptr));
01228                     if ( t== NULL  || strlen(t) == 0 ) {
01229                         papi_free(fptr);
01230                         break;
01231                     }
01232 
01233                     // Handle optional short descriptions, long descriptions and notes
01234                     if (strcasecmp(fptr, "SDESC") == 0) {
01235                         results[res_idx].short_descr = papi_strdup(t);
01236                     }
01237                     if (strcasecmp(fptr, "LDESC") == 0) {
01238                         results[res_idx].long_descr = papi_strdup(t);
01239                     }
01240                     if (strcasecmp(fptr, "NOTE") == 0) {
01241                         results[res_idx].note = papi_strdup(t);
01242                     }
01243 
01244                     SUBDBG( "Found %s (%s) on line %d\n", fptr, t, line_no);
01245                     papi_free (fptr);
01246 
01247                     // look for another field name
01248                     t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01249                     if ( t== NULL  || strlen(t) == 0 ) {
01250                         break;
01251                     }
01252                 } while (t != NULL);
01253             }
01254             (*event_count)++;
01255             continue;
01256         }
01257 
01258         PAPIERROR("Unrecognized token %s at line %d of %s -- ignoring", t, line_no, name);
01259     }
01260 
01261     if (event_file) {
01262         fclose(event_file);
01263     }
01264 
01265     SUBDBG("EXIT: Done processing derived event file.\n");
01266     return PAPI_OK;
01267 }

Here is the call graph for this function:

Here is the caller graph for this function:

static char pop (  )  [static]

Definition at line 826 of file papi_preset.c.

00826            {
00827   if( stacktop < 0 ) {
00828     INTDBG("stack underflow converting algebraic expression\n" );
00829     return '\0';  //***TODO: Figure out how to exit gracefully
00830   } // end if empty
00831   return( stack[stacktop--] );
00832 } // end pop

Here is the caller graph for this function:

static int priority ( char  symbol  )  [static]

Definition at line 796 of file papi_preset.c.

00796                             {
00797         switch( symbol ) {
00798         case '@':
00799                 return -1;
00800         case '(':
00801                 return 0;
00802     case '+':
00803     case '-':
00804                 return 1;
00805     case '*':
00806     case '/':
00807     case '%':
00808         return 2;
00809     default :
00810         return 0;
00811     } // end switch symbol
00812 } // end priority

Here is the caller graph for this function:

static int push ( char  symbol  )  [static]

Definition at line 815 of file papi_preset.c.

00815                         {
00816   if (stacktop >= 2*PAPI_HUGE_STR_LEN - 1) {
00817     INTDBG("stack overflow converting algebraic expression (%d,%c)\n", stacktop,symbol );
00818     return -1;  //***TODO: Figure out how to exit gracefully
00819   } // end if stacktop>MAX
00820   stack[++stacktop] = symbol;
00821   return 0;
00822 } // end push

Here is the caller graph for this function:

static char* trim_note ( char *  in  )  [inline, static]

Definition at line 197 of file papi_preset.c.

00198 {
00199     int len;
00200     char *note, start, end;
00201 
00202     note = trim_string( in );
00203     if ( note != NULL ) {
00204                 len = ( int ) strlen( note );
00205         if ( len > 0 ) {
00206             if ( ispunct( *note ) ) {
00207                 start = *note;
00208                 end = note[len - 1];
00209                 if ( ( start == end )
00210                      || ( ( start == '(' ) && ( end == ')' ) )
00211                      || ( ( start == '<' ) && ( end == '>' ) )
00212                      || ( ( start == '{' ) && ( end == '}' ) )
00213                      || ( ( start == '[' ) && ( end == ']' ) ) ) {
00214                     note[len - 1] = '\0';
00215                     *note = '\0';
00216                     note++;
00217                 }
00218             }
00219         }
00220     }
00221     return note;
00222 }

Here is the call graph for this function:

Here is the caller graph for this function:

static char* trim_string ( char *  in  )  [inline, static]

Definition at line 157 of file papi_preset.c.

00158 {
00159     int len, i = 0;
00160     char *start = in;
00161 
00162     if ( in == NULL )
00163         return ( in );
00164     len = ( int ) strlen( in );
00165     if ( len == 0 )
00166         return ( in );
00167 
00168     /* Trim left */
00169     while ( i < len ) {
00170         if ( isblank( in[i] ) ) {
00171             in[i] = '\0';
00172             start++;
00173         } else
00174             break;
00175         i++;
00176     }
00177 
00178     /* Trim right */
00179     i = ( int ) strlen( start ) - 1;
00180     while ( i >= 0 ) {
00181         if ( isblank( start[i] ) )
00182             start[i] = '\0';
00183         else
00184             break;
00185         i--;
00186     }
00187     return ( start );
00188 }

Here is the caller graph for this function:

static void update_ops_string ( char **  formula,
int  old_index,
int  new_index 
) [static]

Definition at line 304 of file papi_preset.c.

00304                                                                 {
00305     INTDBG("ENTER:   *formula: %s, old_index: %d, new_index: %d\n", *formula?*formula:"NULL", old_index, new_index);
00306 
00307     int cur_index;
00308     char *newFormula;
00309     char *subtoken;
00310     char *tok_save_ptr=NULL;
00311 
00312     // if formula is null just return
00313     if (*formula == NULL) {
00314         INTDBG("EXIT: Null pointer to formula passed in\n");
00315         return;
00316     }
00317 
00318     // get some space for the new formula we are going to create
00319     newFormula = papi_calloc(strlen(*formula) + 20, 1);
00320 
00321     // replace the specified "replace" tokens in the new original formula with the new insertion formula
00322     newFormula[0] = '\0';
00323     subtoken = strtok_r(*formula, "|", &tok_save_ptr);
00324     while ( subtoken != NULL) {
00325 //      INTDBG("subtoken: %s, newFormula: %s\n", subtoken, newFormula);
00326         char work[10];
00327         // if this is the token we want to replace with the new token index, do it now
00328         if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))) {
00329             cur_index = atoi(&subtoken[1]);
00330             // if matches old index, use the new one
00331             if (cur_index == old_index) {
00332                 sprintf (work, "N%d", new_index);
00333                 strcat (newFormula, work);
00334             } else if (cur_index > old_index) {
00335                 // current token greater than old index, make it one less than what it was
00336                 sprintf (work, "N%d", cur_index-1);
00337                 strcat (newFormula, work);
00338             } else {
00339                 // current token less than old index, copy this part of the original formula into the new formula
00340                 strcat(newFormula, subtoken);
00341             }
00342         } else {
00343             // copy this part of the original formula into the new formula
00344             strcat(newFormula, subtoken);
00345         }
00346         strcat (newFormula, "|");
00347         subtoken = strtok_r(NULL, "|", &tok_save_ptr);
00348     }
00349     papi_free (*formula);
00350     *formula = newFormula;
00351 
00352     INTDBG("EXIT: newFormula: %s\n", newFormula);
00353     return;
00354 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char* papi_events_table = NULL [static]

Definition at line 768 of file papi_preset.c.

char stack[2 *PAPI_HUGE_STR_LEN] [static]

Definition at line 791 of file papi_preset.c.

int stacktop = -1 [static]

Definition at line 792 of file papi_preset.c.

Definition at line 59 of file papi_internal.c.

Definition at line 60 of file papi_internal.c.


Generated on 17 Nov 2016 for PAPI by  doxygen 1.6.1