// Define the papi_avail man page contents. /** * file papi_avail.c * @brief papi_avail utility. * @page papi_avail * @section Name * papi_avail - provides availability and detailed information for PAPI preset and user defined events. * * @section Synopsis * papi_avail [-adht] [-e event] * * @section Description * papi_avail is a PAPI utility program that reports information about the * current PAPI installation and supported preset and user defined events. * * @section Options * * * Event filtering options * * @section Bugs * There are no known bugs in this utility. * If you find a bug, it should be reported to the PAPI Mailing List at . *
* @see PAPI_derived_event_files * */ // Define the PAPI_derived_event_files man page contents. /** * @page PAPI_derived_event_files * @brief Describes derived event definition file syntax. * * @section main Derived Events * PAPI provides the ability to define events whose value will be derived from multiple native events. The list of native * events to be used in a derived event and a formula which describes how to use them is provided in an event definition file. * The PAPI team provides an event definition file which describes all of the supported PAPI preset events. PAPI also allows * a user to provide an event definition file that describes a set of user defined events which can extend the events PAPI * normally supports. * * This page documents the syntax of the commands which can appear in an event definition file. * *
* @subsection rules General Rules: * * *
* @subsection commands Commands: * @par CPU,\ * Specifies a PMU name which controls if the PRESET and EVENT commands that follow this line should * be processed. Multiple CPU commands can be entered without PRESET or EVENT commands between them to provide * a list of PMU names to which the derived events that follow will apply. When a PMU name provided in the list * matches a PMU name known to the running system, the events which follow will be created. If none of the PMU * names provided in the list match a PMU name on the running system, the events which follow will be ignored. * When a new CPU command follows either a PRESET or EVENT command, the PMU list is rebuilt.

* * @par PRESET,\,\,\,LDESC,\"\\",SDESC,\"\\",NOTE,\"\\" * Declare a PAPI preset derived event.

* * @par EVENT,\,\,\,LDESC,\"\\",SDESC,\"\\",NOTE,\"\\" * Declare a user defined derived event.

* * @par Where: * @par pmuName: * The PMU which the following events should apply to. A list of PMU names supported by your * system can be obtained by running papi_component_avail on your system.
* @par eventName: * Specifies the name used to identify this derived event. This name should be unique within the events on your system.
* @par derivedType: * Specifies the kind of derived event being defined (see 'Derived Types' below).
* @par eventAttr: * Specifies a formula and a list of base events that are used to compute the derived events value. The syntax * of this field depends on the 'derivedType' specified above (see 'Derived Types' below).
* @par longDesc: * Provides the long description of the event.
* @par shortDesc: * Provides the short description of the event.
* @par note: * Provides an event note.
* @par baseEvent (used below): * Identifies an event on which this derived event is based. This may be a native event (possibly with event masks), * an already known preset event, or an already known user event.
* *
* @subsection notes Notes: * The PRESET command has traditionally been used in the PAPI provided preset definition file. * The EVENT command is intended to be used in user defined event definition files. The code treats them * the same so they are interchangeable and they can both be used in either event definition file.
* *
* @subsection types Derived Types: * This describes values allowed in the 'derivedType' field of the PRESET and EVENT commands. It also * shows the syntax of the 'eventAttr' field for each derived type supported by these commands. * All of the derived events provide a list of one or more events which the derived event is based * on (baseEvent). Some derived events provide a formula that specifies how to compute the derived * events value using the baseEvents in the list. The following derived types are supported, the syntax * of the 'eventAttr' parameter for each derived event type is shown in parentheses.

* * @par NOT_DERIVED (\): * This derived type defines an alias for the existing event 'baseEvent'.
* @par DERIVED_ADD (\,\): * This derived type defines a new event that will be the sum of two other * events. It has a value of 'baseEvent1' plus 'baseEvent2'.
* @par DERIVED_PS (PAPI_TOT_CYC,\): * This derived type defines a new event that will report the number of 'baseEvent1' events which occurred * per second. It has a value of ((('baseEvent1' * cpu_max_mhz) * 1000000 ) / PAPI_TOT_CYC). The user must * provide PAPI_TOT_CYC as the first event of two events in the event list for this to work correctly.
* @par DERIVED_ADD_PS (PAPI_TOT_CYC,\,\): * This derived type defines a new event that will add together two event counters and then report the number * which occurred per second. It has a value of (((('baseEvent1' + baseEvent2) * cpu_max_mhz) * 1000000 ) / PAPI_TOT_CYC). * The user must provide PAPI_TOT_CYC as the first event of three events in the event list for this to work correctly.
* @par DERIVED_CMPD (\,\ * @par DERIVED_SUB (\,\): * This derived type defines a new event that will be the difference between two other * events. It has a value of 'baseEvent1' minus 'baseEvent2'.
* @par DERIVED_POSTFIX (\,\,\, ... ,\): * This derived type defines a new event whose value is computed from several native events using * a postfix (reverse polish notation) formula. Its value is the result of processing the postfix * formula. The 'pfFormula' is of the form 'N0|N1|N2|5|*|+|-|' where the '|' acts as a token * separator and the tokens N0, N1, and N2 are place holders that represent baseEvent0, baseEvent1, * and baseEvent2 respectively.
* @par DERIVED_INFIX (\,\,\, ... ,\): * This derived type defines a new event whose value is computed from several native events using * an infix (algebraic notation) formula. Its value is the result of processing the infix * formula. The 'ifFormula' is of the form 'N0-(N1+(N2*5))' where the tokens N0, N1, and N2 * are place holders that represent baseEvent0, baseEvent1, and baseEvent2 respectively.
* *
* @subsection example Example: * In the following example, the events PAPI_SP_OPS, USER_SP_OPS, and ALIAS_SP_OPS will all measure the same events and return * the same value. They just demonstrate different ways to use the PRESET and EVENT event definition commands.

* *
    *
  • # The following lines define pmu names that all share the following events
  • *
  • CPU nhm
  • *
  • CPU nhm-ex
  • *
  • \# Events which should be defined for either of the above pmu types
  • *
  • PRESET,PAPI_TOT_CYC,NOT_DERIVED,UNHALTED_CORE_CYCLES
  • *
  • PRESET,PAPI_REF_CYC,NOT_DERIVED,UNHALTED_REFERENCE_CYCLES
  • *
  • PRESET,PAPI_SP_OPS,DERIVED_POSTFIX,N0|N1|3|*|+|,FP_COMP_OPS_EXE:SSE_SINGLE_PRECISION,FP_COMP_OPS_EXE:SSE_FP_PACKED,NOTE,"Using a postfix formula"
  • *
  • EVENT,USER_SP_OPS,DERIVED_INFIX,N0+(N1*3),FP_COMP_OPS_EXE:SSE_SINGLE_PRECISION,FP_COMP_OPS_EXE:SSE_FP_PACKED,NOTE,"Using the same formula in infix format"
  • *
  • EVENT,ALIAS_SP_OPS,NOT_DERIVED,PAPI_SP_OPS,LDESC,"Alias for preset event PAPI_SP_OPS"
  • *
  • # End of event definitions for above pmu names and start of a section for a new pmu name.
  • *
  • CPU snb
  • *
* */ #include #include #include #include "papi.h" #include "print_header.h" static char * is_derived( PAPI_event_info_t * info ) { if ( strlen( info->derived ) == 0 ) return ( "No" ); else if ( strcmp( info->derived, "NOT_DERIVED" ) == 0 ) return ( "No" ); else if ( strcmp( info->derived, "DERIVED_CMPD" ) == 0 ) return ( "No" ); else return ( "Yes" ); } static void print_help( char **argv ) { printf( "This is the PAPI avail program.\n" ); printf( "It provides availability and details about PAPI Presets and User-defined Events.\n" ); printf( "PAPI Preset Event filters can be combined in a logical OR.\n" ); printf( "Usage: %s [options]\n", argv[0] ); printf( "Options:\n\n" ); printf( "General command options:\n" ); printf( "\t-h, --help Print this help message\n" ); printf( "\t-a, --avail Display only available PAPI preset and user defined events\n" ); printf( "\t-c, --check Display only available PAPI preset and user defined events after an availability check\n" ); printf( "\t-d, --detail Display detailed information about events\n" ); printf( "\t-e EVENTNAME Display detail information about specified event\n" ); printf( "\nEvent filtering options:\n" ); printf( "\t--br Display branch related PAPI preset events\n" ); printf( "\t--cache Display cache related PAPI preset events\n" ); printf( "\t--cnd Display conditional PAPI preset events\n" ); printf( "\t--fp Display Floating Point related PAPI preset events\n" ); printf( "\t--ins Display instruction related PAPI preset events\n" ); printf( "\t--idl Display Stalled or Idle PAPI preset events\n" ); printf( "\t--l1 Display level 1 cache related PAPI preset events\n" ); printf( "\t--l2 Display level 2 cache related PAPI preset events\n" ); printf( "\t--l3 Display level 3 cache related PAPI preset events\n" ); printf( "\t--mem Display memory related PAPI preset events\n" ); printf( "\t--msc Display miscellaneous PAPI preset events\n" ); printf( "\t--tlb Display Translation Lookaside Buffer PAPI preset events\n" ); printf( "\n" ); } static int parse_unit_masks( PAPI_event_info_t * info ) { char *pmask; if ( ( pmask = strchr( info->symbol, ':' ) ) == NULL ) { return ( 0 ); } memmove( info->symbol, pmask, ( strlen( pmask ) + 1 ) * sizeof ( char ) ); pmask = strchr( info->long_descr, ':' ); if ( pmask == NULL ) info->long_descr[0] = 0; else memmove( info->long_descr, pmask + sizeof ( char ), ( strlen( pmask ) + 1 ) * sizeof ( char ) ); return 1; } static int checkCounter (int eventcode) { int EventSet = PAPI_NULL; if (PAPI_create_eventset(&EventSet) != PAPI_OK) return 0; if (PAPI_add_event (EventSet, eventcode) != PAPI_OK) return 0; if (PAPI_cleanup_eventset (EventSet) != PAPI_OK) return 0; if (PAPI_destroy_eventset (&EventSet) != PAPI_OK) return 0; return 1; } int main( int argc, char **argv ) { int args, i, j, k; int retval; unsigned int filter = 0; int print_event_info = 0; char *name = NULL; int print_avail_only = PAPI_ENUM_EVENTS; int print_tabular = 1; PAPI_event_info_t info; const PAPI_hw_info_t *hwinfo = NULL; int tot_count = 0; int avail_count = 0; int deriv_count = 0; int check_counter = 0; int event_code; PAPI_event_info_t n_info; /* Parse command line arguments */ for( args = 1; args < argc; args++ ) { if ( strstr( argv[args], "-e" ) ) { print_event_info = 1; name = argv[args + 1]; if ( ( name == NULL ) || ( strlen( name ) == 0 ) ) { print_help( argv ); exit( 1 ); } } else if ( strstr( argv[args], "-c" ) || strstr (argv[args], "--check") ) { print_avail_only = PAPI_PRESET_ENUM_AVAIL; check_counter = 1; } else if ( strstr( argv[args], "-a" )) print_avail_only = PAPI_PRESET_ENUM_AVAIL; else if ( strstr( argv[args], "-d" ) ) print_tabular = 0; else if ( strstr( argv[args], "-h" ) ) { print_help( argv ); exit( 1 ); } else if ( strstr( argv[args], "--br" ) ) filter |= PAPI_PRESET_BIT_BR; else if ( strstr( argv[args], "--cache" ) ) filter |= PAPI_PRESET_BIT_CACH; else if ( strstr( argv[args], "--cnd" ) ) filter |= PAPI_PRESET_BIT_CND; else if ( strstr( argv[args], "--fp" ) ) filter |= PAPI_PRESET_BIT_FP; else if ( strstr( argv[args], "--ins" ) ) filter |= PAPI_PRESET_BIT_INS; else if ( strstr( argv[args], "--idl" ) ) filter |= PAPI_PRESET_BIT_IDL; else if ( strstr( argv[args], "--l1" ) ) filter |= PAPI_PRESET_BIT_L1; else if ( strstr( argv[args], "--l2" ) ) filter |= PAPI_PRESET_BIT_L2; else if ( strstr( argv[args], "--l3" ) ) filter |= PAPI_PRESET_BIT_L3; else if ( strstr( argv[args], "--mem" ) ) filter |= PAPI_PRESET_BIT_BR; else if ( strstr( argv[args], "--msc" ) ) filter |= PAPI_PRESET_BIT_MSC; else if ( strstr( argv[args], "--tlb" ) ) filter |= PAPI_PRESET_BIT_TLB; } if ( filter == 0 ) { filter = ( unsigned int ) ( -1 ); } /* Init PAPI */ retval = PAPI_library_init( PAPI_VER_CURRENT ); if ( retval != PAPI_VER_CURRENT ) { fprintf(stderr,"Error! PAPI library mismatch!\n"); return 1; } retval = PAPI_set_debug( PAPI_VERB_ECONT ); if ( retval != PAPI_OK ) { fprintf(stderr,"Error with PAPI_set debug!\n"); return 1; } retval=papi_print_header("Available PAPI preset and user defined events plus hardware information.\n", &hwinfo ); if ( retval != PAPI_OK ) { fprintf(stderr,"Error with PAPI_get_hardware_info!\n"); return 1; } /* Code for info on just one event */ if ( print_event_info ) { if ( PAPI_event_name_to_code( name, &event_code ) == PAPI_OK ) { if ( PAPI_get_event_info( event_code, &info ) == PAPI_OK ) { if ( event_code & PAPI_PRESET_MASK ) { printf( "%-30s%s\n%-30s%#-10x\n%-30s%d\n", "Event name:", info.symbol, "Event Code:", info.event_code, "Number of Native Events:", info.count ); printf( "%-29s|%s|\n%-29s|%s|\n%-29s|%s|\n", "Short Description:", info.short_descr, "Long Description:", info.long_descr, "Developer's Notes:", info.note ); printf( "%-29s|%s|\n%-29s|%s|\n", "Derived Type:", info.derived, "Postfix Processing String:", info.postfix ); for( j = 0; j < ( int ) info.count; j++ ) { printf( " Native Code[%d]: %#x |%s|\n", j, info.code[j], info.name[j] ); PAPI_get_event_info( (int) info.code[j], &n_info ); printf(" Number of Register Values: %d\n", n_info.count ); for( k = 0; k < ( int ) n_info.count; k++ ) { printf( " Register[%2d]: %#08x |%s|\n", k, n_info.code[k], n_info.name[k] ); } printf( " Native Event Description: |%s|\n\n", n_info.long_descr ); } } else { /* must be a native event code */ printf( "%-30s%s\n%-30s%#-10x\n%-30s%d\n", "Event name:", info.symbol, "Event Code:", info.event_code, "Number of Register Values:", info.count ); printf( "%-29s|%s|\n", "Description:", info.long_descr ); for ( k = 0; k < ( int ) info.count; k++ ) { printf( " Register[%2d]: %#08x |%s|\n", k, info.code[k], info.name[k] ); } /* if unit masks exist but none are specified, process all */ if ( !strchr( name, ':' ) ) { if ( 1 ) { if ( PAPI_enum_event( &event_code, PAPI_NTV_ENUM_UMASKS ) == PAPI_OK ) { printf( "\nUnit Masks:\n" ); do { retval = PAPI_get_event_info(event_code, &info ); if ( retval == PAPI_OK ) { if ( parse_unit_masks( &info ) ) { printf( "%-29s|%s|%s|\n", " Mask Info:", info.symbol, info.long_descr ); for ( k = 0; k < ( int ) info.count;k++ ) { printf( " Register[%2d]: %#08x |%s|\n", k, info.code[k], info.name[k] ); } } } } while ( PAPI_enum_event( &event_code, PAPI_NTV_ENUM_UMASKS ) == PAPI_OK ); } } } } } } else { printf( "Sorry, an event by the name '%s' could not be found.\n" " Is it typed correctly?\n\n", name ); } } else { /* Print *ALL* Events */ for (i=0 ; i<2 ; i++) { // set the event code to fetch preset events the first time through loop and user events the second time through the loop if (i== 0) { event_code = 0 | PAPI_PRESET_MASK; } else { event_code = 0 | PAPI_UE_MASK; } /* For consistency, always ASK FOR the first event, if there is not one then nothing to process */ if (PAPI_enum_event( &event_code, PAPI_ENUM_FIRST ) != PAPI_OK) { continue; } // print heading to show which kind of events follow if (i== 0) { printf( "================================================================================\n" ); printf( " PAPI Preset Events\n" ); printf( "================================================================================\n" ); } else { printf( "\n"); // put a blank line after the presets before strarting the user events printf( "================================================================================\n" ); printf( " User Defined Events\n" ); printf( "================================================================================\n" ); } if ( print_tabular ) { printf( " Name Code " ); if ( !print_avail_only ) { printf( "Avail " ); } printf( "Deriv Description (Note)\n" ); } else { printf( "%-13s%-11s%-8s%-16s\n |Long Description|\n" " |Developer's Notes|\n |Derived|\n |PostFix|\n" " Native Code[n]: |name|\n", "Symbol", "Event Code", "Count", "|Short Description|" ); } do { if ( PAPI_get_event_info( event_code, &info ) == PAPI_OK ) { if ( print_tabular ) { // if this is a user defined event or its a preset and matches the preset event filters, display its information if ( (i==1) || (filter & info.event_type)) { if ( print_avail_only ) { if ( info.count ) { if ( (check_counter && checkCounter (event_code)) || !check_counter) { printf( "%-13s%#x %-5s%s", info.symbol, info.event_code, is_derived( &info ), info.long_descr ); } } if ( info.note[0] ) { printf( " (%s)", info.note ); } printf( "\n" ); } else { printf( "%-13s%#x %-6s%-4s %s", info.symbol, info.event_code, ( info.count ? "Yes" : "No" ), is_derived( &info ), info.long_descr ); if ( info.note[0] ) { printf( " (%s)", info.note ); } printf( "\n" ); } tot_count++; if ( info.count ) { if ((check_counter && checkCounter (event_code)) || !check_counter ) avail_count++; } if ( !strcmp( is_derived( &info ), "Yes" ) ) { deriv_count++; } } } else { if ( ( print_avail_only && info.count ) || ( print_avail_only == 0 ) ) { if ((check_counter && checkCounter (event_code)) || !check_counter) { printf( "%s\t%#x\t%d\t|%s|\n |%s|\n" " |%s|\n |%s|\n |%s|\n", info.symbol, info.event_code, info.count, info.short_descr, info.long_descr, info.note, info.derived, info.postfix ); for ( j = 0; j < ( int ) info.count; j++ ) { printf( " Native Code[%d]: %#x |%s|\n", j, info.code[j], info.name[j] ); } } } tot_count++; if ( info.count ) { if ((check_counter && checkCounter (event_code)) || !check_counter ) avail_count++; } if ( !strcmp( is_derived( &info ), "Yes" ) ) { deriv_count++; } } } } while (PAPI_enum_event( &event_code, print_avail_only ) == PAPI_OK); } } printf( "--------------------------------------------------------------------------------\n" ); if ( !print_event_info ) { if ( print_avail_only ) { printf( "Of %d available events, %d ", avail_count, deriv_count ); } else { printf( "Of %d possible events, %d are available, of which %d ", tot_count, avail_count, deriv_count ); } if ( deriv_count == 1 ) { printf( "is derived.\n\n" ); } else { printf( "are derived.\n\n" ); } } return 0; }