Blame src/papi_hl.c

Packit 577717
/****************************/
Packit 577717
/* THIS IS OPEN SOURCE CODE */
Packit 577717
/****************************/
Packit 577717
Packit 577717
/**
Packit 577717
* @file		papi_hl.c
Packit 577717
* @author	Philip Mucci
Packit 577717
*			mucci@cs.utk.edu
Packit 577717
* @author	Kevin London
Packit 577717
*           london@cs.utk.edu
Packit 577717
* @author	dan terpstra
Packit 577717
*			terpstra@cs.utk.edu
Packit 577717
* @brief This file contains the 'high level' interface to PAPI.
Packit 577717
*  BASIC is a high level language. ;-) */
Packit 577717
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_internal.h"
Packit 577717
#include "papi_memory.h"
Packit 577717
#include <string.h>
Packit 577717
Packit 577717
/* high level papi functions*/
Packit 577717
Packit 577717
/*
Packit 577717
 * Which high-level interface are we using?
Packit 577717
 */
Packit 577717
#define HL_STOP		0
Packit 577717
#define HL_START	1
Packit 577717
#define HL_FLIP		2
Packit 577717
#define HL_FLOP		3
Packit 577717
#define HL_IPC		4
Packit 577717
#define HL_EPC		5
Packit 577717
#define HL_READ		6
Packit 577717
#define HL_ACCUM	7
Packit 577717
Packit 577717
/** \internal 
Packit 577717
 * This is stored per thread
Packit 577717
 */
Packit 577717
typedef struct _HighLevelInfo
Packit 577717
{
Packit 577717
	int EventSet;					/**< EventSet of the thread */
Packit 577717
	short int num_evts;				/**< number of events in the eventset */
Packit 577717
	short int running;				/**< STOP, START, or RATE */
Packit 577717
	long long initial_real_time;	/**< Start real time */
Packit 577717
	long long initial_proc_time;	/**< Start processor time */
Packit 577717
	long long last_real_time;		/**< Previous value of real time */
Packit 577717
	long long last_proc_time;		/**< Previous value of processor time */
Packit 577717
	long long total_ins;			/**< Total instructions */
Packit 577717
} HighLevelInfo;
Packit 577717
Packit 577717
int _hl_rate_calls( float *real_time, float *proc_time, int *events, 
Packit 577717
					long long *values, long long *ins, float *rate, int mode );
Packit 577717
void _internal_cleanup_hl_info( HighLevelInfo * state );
Packit 577717
int _internal_check_state( HighLevelInfo ** state );
Packit 577717
int _internal_start_hl_counters( HighLevelInfo * state );
Packit 577717
int _internal_hl_read_cnts( long long *values, int array_len, int flag );
Packit 577717
Packit 577717
/* CHANGE LOG:
Packit 577717
  - ksl 10/17/03
Packit 577717
   Pretty much a complete rewrite of the high level interface.  Now
Packit 577717
   the interface is thread safe and you don't have to worry as much
Packit 577717
   about mixing the various high level calls.
Packit 577717
Packit 577717
  - dkt 11/19/01:
Packit 577717
   After much discussion with users and developers, removed FMA and SLOPE
Packit 577717
   fudge factors. SLOPE was not being used, and we decided the place to
Packit 577717
   apply FMA was at a higher level where there could be a better understanding
Packit 577717
   of platform discrepancies and code implications.
Packit 577717
   ALL PAPI CALLS NOW RETURN EXACTLY WHAT THE HARDWARE REPORTS
Packit 577717
  - dkt 08/14/01:
Packit 577717
   Added reinitialization of values and proc_time to new reinit code.
Packit 577717
   Added SLOPE and FMA constants to correct for systemic errors on a
Packit 577717
   platform-by-platform basis.
Packit 577717
   SLOPE is a factor subtracted from flpins on each call to compensate
Packit 577717
   for platform overhead in the call.
Packit 577717
   FMA is a shifter that doubles floating point counts on platforms that
Packit 577717
   count FMA as one op instead of two.
Packit 577717
   NOTE: We are making the FLAWED assumption that ALL flpins are FMA!
Packit 577717
   This will result in counts that are TOO HIGH on the affected platforms
Packit 577717
   in instances where the code is NOT mostly FMA.
Packit 577717
  - dkt 08/01/01:
Packit 577717
   NOTE: Calling semantics have changed!
Packit 577717
   Now, if flpins < 0 (an invalid value) a PAPI_reset is issued to reset the
Packit 577717
   counter values. The internal start time is also reset. This should be a 
Packit 577717
   benign change, exept in the rare case where a user passes an uninitialized
Packit 577717
   (and possibly negative) value for flpins to the routine *AFTER* it has been
Packit 577717
   called the first time. This is unlikely, since the first call clears and
Packit 577717
   returns th is value.
Packit 577717
  - dkt 08/01/01:
Packit 577717
   Internal sequencing changes:
Packit 577717
   -- initial PAPI_get_real_usec() call moved above PAPI_start to avoid unwanted flops.
Packit 577717
   -- PAPI_accum() replaced with PAPI_start() / PAPI_stop pair for same reason.
Packit 577717
*/
Packit 577717
Packit 577717
/** @internal 
Packit 577717
 * This function is called to determine the state of the system.
Packit 577717
 * We may as well set the HighLevelInfo so you don't have to look it
Packit 577717
 * up again.
Packit 577717
 */
Packit 577717
int
Packit 577717
_internal_check_state( HighLevelInfo ** outgoing )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
	HighLevelInfo *state = NULL;
Packit 577717
Packit 577717
	/* Only allow one thread at a time in here */
Packit 577717
	if ( init_level == PAPI_NOT_INITED ) {
Packit 577717
		retval = PAPI_library_init( PAPI_VER_CURRENT );
Packit 577717
		if ( retval != PAPI_VER_CURRENT ) {
Packit 577717
			return ( retval );
Packit 577717
		} else {
Packit 577717
			_papi_hwi_lock( HIGHLEVEL_LOCK );
Packit 577717
			init_level = PAPI_HIGH_LEVEL_INITED;
Packit 577717
			_papi_hwi_unlock( HIGHLEVEL_LOCK );
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	/*
Packit 577717
	 * Do we have the thread specific data setup yet?
Packit 577717
	 */
Packit 577717
	if ( ( retval =
Packit 577717
		   PAPI_get_thr_specific( PAPI_HIGH_LEVEL_TLS, ( void ** ) &state ) )
Packit 577717
		 != PAPI_OK || state == NULL ) {
Packit 577717
		state = ( HighLevelInfo * ) papi_malloc( sizeof ( HighLevelInfo ) );
Packit 577717
		if ( state == NULL )
Packit 577717
			return ( PAPI_ENOMEM );
Packit 577717
Packit 577717
		memset( state, 0, sizeof ( HighLevelInfo ) );
Packit 577717
		state->EventSet = -1;
Packit 577717
Packit 577717
		if ( ( retval = PAPI_create_eventset( &state->EventSet ) ) != PAPI_OK )
Packit 577717
			return ( retval );
Packit 577717
Packit 577717
		if ( ( retval =
Packit 577717
			   PAPI_set_thr_specific( PAPI_HIGH_LEVEL_TLS,
Packit 577717
									  state ) ) != PAPI_OK )
Packit 577717
			return ( retval );
Packit 577717
	}
Packit 577717
	*outgoing = state;
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
/** @internal 
Packit 577717
 * Make sure to allocate space for values 
Packit 577717
 */
Packit 577717
int
Packit 577717
_internal_start_hl_counters( HighLevelInfo * state )
Packit 577717
{
Packit 577717
	return ( PAPI_start( state->EventSet ) );
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
_internal_cleanup_hl_info( HighLevelInfo * state )
Packit 577717
{
Packit 577717
	state->num_evts = 0;
Packit 577717
	state->running = HL_STOP;
Packit 577717
	state->initial_real_time = -1;
Packit 577717
   	state->initial_proc_time = -1;
Packit 577717
	state->total_ins = 0;
Packit 577717
	return;
Packit 577717
}
Packit 577717
Packit 577717
/** @class PAPI_flips
Packit 577717
  *	@brief Simplified call to get Mflips/s (floating point instruction rate), real and processor time. 
Packit 577717
  *
Packit 577717
  *	@par C Interface: 
Packit 577717
  *	\#include <papi.h> @n
Packit 577717
  *	int PAPI_flips( float *rtime, float *ptime, long long *flpins, float *mflips );
Packit 577717
  *
Packit 577717
  * @param *rtime
Packit 577717
  *		total realtime since the first call
Packit 577717
  *	@param *ptime
Packit 577717
  *		total process time since the first call
Packit 577717
  *	@param *flpins
Packit 577717
  *		total floating point instructions since the first call
Packit 577717
  *	@param *mflips
Packit 577717
  *		incremental (Mega) floating point instructions per seconds since the last call
Packit 577717
  *  
Packit 577717
  *	@retval PAPI_EINVAL 
Packit 577717
  *		The counters were already started by something other than PAPI_flips().
Packit 577717
  *	@retval PAPI_ENOEVNT 
Packit 577717
  *		The floating point instructions event does not exist.
Packit 577717
  *	@retval PAPI_ENOMEM 
Packit 577717
  *		Insufficient memory to complete the operation. 
Packit 577717
  *
Packit 577717
  * The first call to PAPI_flips() will initialize the PAPI High Level interface, 
Packit 577717
  * set up the counters to monitor the PAPI_FP_INS event and start the counters.
Packit 577717
  *
Packit 577717
  * Subsequent calls will read the counters and return total real time, 
Packit 577717
  * total process time, total floating point instructions since the start of the 
Packit 577717
  * measurement and the Mflip/s rate since latest call to PAPI_flips(). 
Packit 577717
  * A call to PAPI_stop_counters() will stop the counters from running and then 
Packit 577717
  * calls such as PAPI_start_counters() or other rate calls can safely be used. 
Packit 577717
  *
Packit 577717
  * PAPI_flips returns information related to floating point instructions using 
Packit 577717
  * the PAPI_FP_INS event. This is intended to measure instruction rate through the 
Packit 577717
  * floating point pipe with no massaging.
Packit 577717
  *
Packit 577717
  * @see PAPI_flops()
Packit 577717
  * @see PAPI_ipc()
Packit 577717
  * @see PAPI_epc()
Packit 577717
  * @see PAPI_stop_counters()
Packit 577717
 */
Packit 577717
int
Packit 577717
PAPI_flips( float *rtime, float *ptime, long long *flpins, float *mflips )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
   int events[1] = {PAPI_FP_INS};
Packit 577717
	long long values = 0;
Packit 577717
Packit 577717
	if ( rtime == NULL || ptime == NULL || flpins == NULL || mflips == NULL )
Packit 577717
		return PAPI_EINVAL;
Packit 577717
Packit 577717
   retval = _hl_rate_calls( rtime, ptime, events, &values, flpins, mflips, HL_FLIP );
Packit 577717
	return ( retval );
Packit 577717
}
Packit 577717
Packit 577717
/** @class PAPI_flops
Packit 577717
  *	@brief Simplified call to get Mflops/s (floating point operation rate), real and processor time. 
Packit 577717
  *
Packit 577717
  *	@par C Interface: 
Packit 577717
  *	\#include <papi.h> @n
Packit 577717
  *	int PAPI_flops( float *rtime, float *ptime, long long *flpops, float *mflops );
Packit 577717
  *
Packit 577717
  * @param *rtime
Packit 577717
  *		total realtime since the first call
Packit 577717
  *	@param *ptime
Packit 577717
  *		total process time since the first call
Packit 577717
  *	@param *flpops
Packit 577717
  *		total floating point operations since the first call
Packit 577717
  *	@param *mflops
Packit 577717
  *		incremental (Mega) floating point operations per seconds since the last call
Packit 577717
  * 
Packit 577717
  *	@retval PAPI_EINVAL 
Packit 577717
  *		The counters were already started by something other than PAPI_flops().
Packit 577717
  *	@retval PAPI_ENOEVNT 
Packit 577717
  *		The floating point operations event does not exist.
Packit 577717
  *	@retval PAPI_ENOMEM 
Packit 577717
  *		Insufficient memory to complete the operation. 
Packit 577717
  *
Packit 577717
  * The first call to PAPI_flops() will initialize the PAPI High Level interface, 
Packit 577717
  * set up the counters to monitor the PAPI_FP_OPS event and start the counters. 
Packit 577717
  *
Packit 577717
  * Subsequent calls will read the counters and return total real time, 
Packit 577717
  * total process time, total floating point operations since the start of the 
Packit 577717
  * measurement and the Mflop/s rate since latest call to PAPI_flops(). 
Packit 577717
  * A call to PAPI_stop_counters() will stop the counters from running and then 
Packit 577717
  * calls such as PAPI_start_counters() or other rate calls can safely be used.
Packit 577717
  *
Packit 577717
  * PAPI_flops returns information related to theoretical floating point operations
Packit 577717
  * rather than simple instructions. It uses the PAPI_FP_OPS event which attempts to 
Packit 577717
  * 'correctly' account for, e.g., FMA undercounts and FP Store overcounts, etc.
Packit 577717
  *
Packit 577717
  * @see PAPI_flips()
Packit 577717
  * @see PAPI_ipc()
Packit 577717
  * @see PAPI_epc()
Packit 577717
  * @see PAPI_stop_counters()
Packit 577717
 */
Packit 577717
int
Packit 577717
PAPI_flops( float *rtime, float *ptime, long long *flpops, float *mflops )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
   int events[1] = {PAPI_FP_OPS};
Packit 577717
	long long values = 0;
Packit 577717
Packit 577717
	if ( rtime == NULL || ptime == NULL || flpops == NULL || mflops == NULL )
Packit 577717
		return PAPI_EINVAL;
Packit 577717
Packit 577717
   retval = _hl_rate_calls( rtime, ptime, events, &values, flpops, mflops, HL_FLOP );
Packit 577717
	return ( retval );
Packit 577717
}
Packit 577717
Packit 577717
/** @class PAPI_ipc
Packit 577717
  *	@brief Simplified call to get instructions per cycle, real and processor time. 
Packit 577717
  *
Packit 577717
  *	@par C Interface: 
Packit 577717
  *	\#include <papi.h> @n
Packit 577717
  *	int PAPI_ipc( float *rtime, float *ptime, long long *ins, float *ipc );
Packit 577717
  *
Packit 577717
  * @param *rtime
Packit 577717
  *		total realtime since the first call
Packit 577717
  *	@param *ptime
Packit 577717
  *		total process time since the first call
Packit 577717
  *	@param *ins
Packit 577717
  *		total instructions since the first call
Packit 577717
  *	@param *ipc
Packit 577717
  *		incremental instructions per cycle since the last call
Packit 577717
  * 
Packit 577717
  *	@retval PAPI_EINVAL 
Packit 577717
  *		The counters were already started by something other than PAPI_ipc().
Packit 577717
  *	@retval PAPI_ENOEVNT 
Packit 577717
  *		The floating point operations event does not exist.
Packit 577717
  *	@retval PAPI_ENOMEM 
Packit 577717
  *		Insufficient memory to complete the operation. 
Packit 577717
  *
Packit 577717
  * The first call to PAPI_ipc() will initialize the PAPI High Level interface, 
Packit 577717
  * set up the counters to monitor PAPI_TOT_INS and PAPI_TOT_CYC events 
Packit 577717
  * and start the counters. 
Packit 577717
  *
Packit 577717
  * Subsequent calls will read the counters and return total real time, 
Packit 577717
  * total process time, total instructions since the start of the 
Packit 577717
  * measurement and the IPC rate since the latest call to PAPI_ipc().
Packit 577717
  *
Packit 577717
  * A call to PAPI_stop_counters() will stop the counters from running and then 
Packit 577717
  * calls such as PAPI_start_counters() or other rate calls can safely be used.
Packit 577717
  *
Packit 577717
  * PAPI_ipc should return a ratio greater than 1.0, indicating instruction level
Packit 577717
  * parallelism within the chip. The larger this ratio the more effeciently the program
Packit 577717
  * is running.
Packit 577717
  *
Packit 577717
  * @see PAPI_flips()
Packit 577717
  * @see PAPI_flops()
Packit 577717
  * @see PAPI_epc()
Packit 577717
  * @see PAPI_stop_counters()
Packit 577717
 */
Packit 577717
int
Packit 577717
PAPI_ipc( float *rtime, float *ptime, long long *ins, float *ipc )
Packit 577717
{
Packit 577717
	long long values[2] = { 0, 0 };
Packit 577717
	int events[2] = {PAPI_TOT_INS, PAPI_TOT_CYC};
Packit 577717
    int retval = 0;
Packit 577717
Packit 577717
	if ( rtime == NULL || ptime == NULL || ins == NULL || ipc == NULL )
Packit 577717
		return PAPI_EINVAL;
Packit 577717
Packit 577717
	retval = _hl_rate_calls( rtime, ptime, events, values, ins, ipc, HL_IPC );
Packit 577717
	return ( retval );
Packit 577717
}
Packit 577717
Packit 577717
/** @class PAPI_epc
Packit 577717
  *	@brief Simplified call to get arbitrary events per cycle, real and processor time. 
Packit 577717
  *
Packit 577717
  *	@par C Interface: 
Packit 577717
  *	\#include <papi.h> @n
Packit 577717
  *	int PAPI_epc( int event, float *rtime, float *ptime, long long *ref, long long *core, long long *evt, float *epc );
Packit 577717
  *
Packit 577717
  * @param event
Packit 577717
  *		event code to be measured (0 defaults to PAPI_TOT_INS)
Packit 577717
  * @param *rtime
Packit 577717
  *		total realtime since the first call
Packit 577717
  *	@param *ptime
Packit 577717
  *		total process time since the first call
Packit 577717
  *	@param *ref
Packit 577717
  *		incremental reference clock cycles since the last call
Packit 577717
  *	@param *core
Packit 577717
  *		incremental core clock cycles since the last call
Packit 577717
  *	@param *evt
Packit 577717
  *		total events since the first call
Packit 577717
  *	@param *epc
Packit 577717
  *		incremental events per cycle since the last call
Packit 577717
  * 
Packit 577717
  *	@retval PAPI_EINVAL 
Packit 577717
  *		The counters were already started by something other than PAPI_epc().
Packit 577717
  *	@retval PAPI_ENOEVNT 
Packit 577717
  *		One of the requested events does not exist.
Packit 577717
  *	@retval PAPI_ENOMEM 
Packit 577717
  *		Insufficient memory to complete the operation. 
Packit 577717
  *
Packit 577717
  * The first call to PAPI_epc() will initialize the PAPI High Level interface, 
Packit 577717
  * set up the counters to monitor the user specified event, PAPI_TOT_CYC, 
Packit 577717
  * and PAPI_REF_CYC (if it exists) and start the counters. 
Packit 577717
  *
Packit 577717
  * Subsequent calls will read the counters and return total real time, 
Packit 577717
  * total process time, total event counts since the start of the 
Packit 577717
  * measurement and the core and reference cycle count and EPC rate since the 
Packit 577717
  * latest call to PAPI_epc(). 
Packit 577717
  
Packit 577717
  * A call to PAPI_stop_counters() will stop the counters from running and then 
Packit 577717
  * calls such as PAPI_start_counters() or other rate calls can safely be used.
Packit 577717
  *
Packit 577717
  * PAPI_epc can provide a more detailed look at algorithm efficiency in light of clock
Packit 577717
  * variability in modern cpus. MFLOPS is no longer an adequate description of peak
Packit 577717
  * performance if clock rates can arbitrarily speed up or slow down. By allowing a
Packit 577717
  * user specified event and reporting reference cycles, core cycles and real time,
Packit 577717
  * PAPI_epc provides the information to compute an accurate effective clock rate, and
Packit 577717
  * an accurate measure of computational throughput.
Packit 577717
  *
Packit 577717
  * @see PAPI_flips()
Packit 577717
  * @see PAPI_flops()
Packit 577717
  * @see PAPI_ipc()
Packit 577717
  * @see PAPI_stop_counters()
Packit 577717
 */
Packit 577717
int
Packit 577717
PAPI_epc( int event, float *rtime, float *ptime, long long *ref, long long *core, long long *evt, float *epc )
Packit 577717
{
Packit 577717
	long long values[3] = { 0, 0, 0 };
Packit 577717
	int events[3] = {PAPI_TOT_INS, PAPI_TOT_CYC, PAPI_REF_CYC};
Packit 577717
	int retval = 0;
Packit 577717
Packit 577717
	if ( rtime == NULL || ptime == NULL || ref == NULL ||core == NULL || evt == NULL || epc == NULL )
Packit 577717
		return PAPI_EINVAL;
Packit 577717
Packit 577717
	// if an event is provided, use it; otherwise use TOT_INS
Packit 577717
	if (event != 0 ) events[0] = event;
Packit 577717
	
Packit 577717
	if ( PAPI_query_event( ( int ) PAPI_REF_CYC ) != PAPI_OK )
Packit 577717
		events[2] = 0;
Packit 577717
Packit 577717
	retval = _hl_rate_calls( rtime, ptime, events, values, evt, epc, HL_EPC );
Packit 577717
	*core = values[1];
Packit 577717
	*ref = values[2];
Packit 577717
	return ( retval );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_hl_rate_calls( float *real_time, float *proc_time, int *events,
Packit 577717
		long long *values, long long *ins, float *rate, int mode )
Packit 577717
{
Packit 577717
	long long rt, pt; // current elapsed real and process times in usec
Packit 577717
	int num_events = 2;
Packit 577717
	int retval = 0;
Packit 577717
	HighLevelInfo *state = NULL;
Packit 577717
Packit 577717
	if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK ) {
Packit 577717
		return ( retval );
Packit 577717
	}
Packit 577717
	
Packit 577717
	if ( state->running != HL_STOP && state->running != mode ) {
Packit 577717
		return PAPI_EINVAL;
Packit 577717
	}
Packit 577717
Packit 577717
	if ( state->running == HL_STOP ) {
Packit 577717
	
Packit 577717
		switch (mode) {
Packit 577717
			case HL_FLOP:
Packit 577717
			case HL_FLIP:
Packit 577717
				num_events = 1;
Packit 577717
				break;
Packit 577717
			case HL_IPC:
Packit 577717
				break;
Packit 577717
			case HL_EPC:
Packit 577717
				if ( events[2] != 0 ) num_events = 3;
Packit 577717
				break;
Packit 577717
			default:
Packit 577717
				return PAPI_EINVAL;
Packit 577717
		}
Packit 577717
		if (( retval = PAPI_add_events( state->EventSet, events, num_events )) != PAPI_OK ) {
Packit 577717
			_internal_cleanup_hl_info( state );
Packit 577717
			PAPI_cleanup_eventset( state->EventSet );
Packit 577717
			return retval;
Packit 577717
		}
Packit 577717
Packit 577717
		state->total_ins = 0;
Packit 577717
		state->initial_real_time = state->last_real_time = PAPI_get_real_usec( );
Packit 577717
		state->initial_proc_time = state->last_proc_time = PAPI_get_virt_usec( );
Packit 577717
Packit 577717
		if ( ( retval = PAPI_start( state->EventSet ) ) != PAPI_OK ) {
Packit 577717
			return retval;
Packit 577717
		}
Packit 577717
		
Packit 577717
		/* Initialize the interface */
Packit 577717
		state->running = mode;
Packit 577717
		*real_time 	= 0.0;
Packit 577717
		*proc_time 	= 0.0;
Packit 577717
		*rate 		= 0.0;
Packit 577717
Packit 577717
	} else {
Packit 577717
		if ( ( retval = PAPI_stop( state->EventSet, values ) ) != PAPI_OK ) {
Packit 577717
			state->running = HL_STOP;
Packit 577717
			return retval;
Packit 577717
		}
Packit 577717
Packit 577717
		/* Read elapsed real and process times  */
Packit 577717
		rt = PAPI_get_real_usec();
Packit 577717
		pt = PAPI_get_virt_usec();
Packit 577717
Packit 577717
		/* Convert to seconds with multiplication because it is much faster */
Packit 577717
		*real_time = ((float)( rt - state->initial_real_time )) * .000001;
Packit 577717
		*proc_time = ((float)( pt - state->initial_proc_time )) * .000001;
Packit 577717
Packit 577717
		state->total_ins += values[0];
Packit 577717
Packit 577717
		switch (mode) {
Packit 577717
			case HL_FLOP:
Packit 577717
			case HL_FLIP:
Packit 577717
				/* Calculate MFLOP and MFLIP rates */
Packit 577717
				if ( pt > 0 ) {
Packit 577717
					 *rate = (float)values[0] / (pt - state->last_proc_time);
Packit 577717
				} else *rate = 0;
Packit 577717
				break;
Packit 577717
			case HL_IPC:
Packit 577717
			case HL_EPC:
Packit 577717
				/* Calculate IPC */
Packit 577717
				if (values[1]!=0) {
Packit 577717
					*rate = (float) ((float)values[0] / (float) ( values[1]));
Packit 577717
				}
Packit 577717
				break;
Packit 577717
			default:
Packit 577717
				return PAPI_EINVAL;
Packit 577717
		}
Packit 577717
		state->last_real_time = rt;
Packit 577717
		state->last_proc_time = pt;
Packit 577717
	
Packit 577717
		if ( ( retval = PAPI_start( state->EventSet ) ) != PAPI_OK ) {
Packit 577717
			state->running = HL_STOP;
Packit 577717
			return retval;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	*ins = state->total_ins;
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** @class PAPI_num_counters
Packit 577717
  *	@brief Get the number of hardware counters available on the system.
Packit 577717
  *
Packit 577717
  *	@par C Interface:
Packit 577717
  *	\#include <papi.h> @n
Packit 577717
  *	int PAPI_num_counters( void );
Packit 577717
  *
Packit 577717
  * @post 
Packit 577717
  *		Initializes the library to PAPI_HIGH_LEVEL_INITED if necessary.
Packit 577717
  *
Packit 577717
  *	@retval PAPI_EINVAL 
Packit 577717
  *		papi.h is different from the version used to compile the PAPI library.
Packit 577717
  *	@retval PAPI_ENOMEM 
Packit 577717
  *		Insufficient memory to complete the operation.
Packit 577717
  *	@retval PAPI_ESYS 
Packit 577717
  *		A system or C library call failed inside PAPI, see the errno variable. 
Packit 577717
  *
Packit 577717
  *	@par Examples:
Packit 577717
  * @code
Packit 577717
  * int num_hwcntrs;
Packit 577717
  * //  The installation does not support PAPI 
Packit 577717
  * if ((num_hwcntrs = PAPI_num_counters()) < 0 )
Packit 577717
  * 	handle_error(1);
Packit 577717
  * //  The installation supports PAPI, but has no counters 
Packit 577717
  * if ((num_hwcntrs = PAPI_num_counters()) == 0 )
Packit 577717
  * 	fprintf(stderr,"Info:: This machine does not provide hardware counters.\n");
Packit 577717
  *	@endcode
Packit 577717
  *
Packit 577717
  * PAPI_num_counters() returns the optimal length of the values array for the high level functions. 
Packit 577717
  * This value corresponds to the number of hardware counters supported by the current CPU component.
Packit 577717
  *
Packit 577717
  * @note This function only works for the CPU component. To determine the number of counters on
Packit 577717
  * another component, use the low level PAPI_num_cmp_hwctrs().
Packit 577717
  */
Packit 577717
int
Packit 577717
PAPI_num_counters( void )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
	HighLevelInfo *tmp = NULL;
Packit 577717
Packit 577717
	/* Make sure the Library is initialized, etc... */
Packit 577717
	if ( ( retval = _internal_check_state( &tmp ) ) != PAPI_OK )
Packit 577717
		return ( retval );
Packit 577717
Packit 577717
	return ( PAPI_get_opt( PAPI_MAX_HWCTRS, NULL ) );
Packit 577717
}
Packit 577717
Packit 577717
/** @class PAPI_start_counters
Packit 577717
 *	@brief Start counting hardware events.
Packit 577717
 *
Packit 577717
 *	@par C Interface:
Packit 577717
 *	\#include <papi.h> @n
Packit 577717
 *	int PAPI_start_counters( int *events, int array_len );
Packit 577717
 *
Packit 577717
 * @param *events
Packit 577717
 *		an array of codes for events such as PAPI_INT_INS or a native event code 
Packit 577717
 * @param array_len
Packit 577717
 *		the number of items in the *events array 
Packit 577717
 *
Packit 577717
 *	@retval PAPI_EINVAL 
Packit 577717
 *		One or more of the arguments is invalid.
Packit 577717
 *	@retval PAPI_EISRUN 
Packit 577717
 *		Counters have already been started, you must call PAPI_stop_counters() 
Packit 577717
 *		before you call this function again.
Packit 577717
 *	@retval PAPI_ESYS 
Packit 577717
 *		A system or C library call failed inside PAPI, see the errno variable.
Packit 577717
 *	@retval PAPI_ENOMEM 
Packit 577717
 *		Insufficient memory to complete the operation.
Packit 577717
 *	@retval PAPI_ECNFLCT 
Packit 577717
 *		The underlying counter hardware cannot count this event and other events 
Packit 577717
 *		in the EventSet simultaneously.
Packit 577717
 *	@retval PAPI_ENOEVNT 
Packit 577717
 *		The PAPI preset is not available on the underlying hardware. 
Packit 577717
 *
Packit 577717
 * PAPI_start_counters() starts counting the events named in the *events array. 
Packit 577717
 * This function cannot be called if the counters have already been started. 
Packit 577717
 * The user must call PAPI_stop_counters() to stop the events explicitly if 
Packit 577717
 * he/she wants to call this function again. 
Packit 577717
 * It is the user's responsibility to choose events that can be counted 
Packit 577717
 * simultaneously by reading the vendor's documentation. 
Packit 577717
 * The length of the *events array should be no longer than the value returned 
Packit 577717
 * by PAPI_num_counters(). 
Packit 577717
 *
Packit 577717
 *	@code
Packit 577717
if( PAPI_start_counters( Events, num_hwcntrs ) != PAPI_OK )
Packit 577717
	handle_error(1);
Packit 577717
 *	@endcode
Packit 577717
 *
Packit 577717
 * @see PAPI_stop_counters() PAPI_add_event() PAPI_create_eventset()
Packit 577717
 */
Packit 577717
int
Packit 577717
PAPI_start_counters( int *events, int array_len )
Packit 577717
{
Packit 577717
	int i, retval;
Packit 577717
	HighLevelInfo *state = NULL;
Packit 577717
Packit 577717
	if ( events == NULL || array_len <= 0 )
Packit 577717
		return PAPI_EINVAL;
Packit 577717
Packit 577717
	if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK )
Packit 577717
		return ( retval );
Packit 577717
Packit 577717
	if ( state->running != 0 )
Packit 577717
		return ( PAPI_EINVAL );
Packit 577717
Packit 577717
	/* load events to the new EventSet */
Packit 577717
	for ( i = 0; i < array_len; i++ ) {
Packit 577717
		retval = PAPI_add_event( state->EventSet, events[i] );
Packit 577717
		if ( retval == PAPI_EISRUN )
Packit 577717
			return ( retval );
Packit 577717
Packit 577717
		if ( retval ) {
Packit 577717
			/* remove any prior events that may have been added 
Packit 577717
			 * and cleanup the high level information
Packit 577717
			 */
Packit 577717
			_internal_cleanup_hl_info( state );
Packit 577717
			PAPI_cleanup_eventset( state->EventSet );
Packit 577717
			return ( retval );
Packit 577717
		}
Packit 577717
	}
Packit 577717
	/* start the EventSet */
Packit 577717
	if ( ( retval = _internal_start_hl_counters( state ) ) == PAPI_OK ) {
Packit 577717
		state->running = HL_START;
Packit 577717
		state->num_evts = ( short ) array_len;
Packit 577717
	}
Packit 577717
	return ( retval );
Packit 577717
}
Packit 577717
Packit 577717
/*========================================================================*/
Packit 577717
/* int PAPI_read_counters(long long *values, int array_len)      */
Packit 577717
/*                                                                        */
Packit 577717
/* Read the running counters into the values array. This call             */
Packit 577717
/* implicitly initializes the internal counters to zero and allows        */
Packit 577717
/* them continue to run upon return.                                      */
Packit 577717
/*========================================================================*/
Packit 577717
Packit 577717
int
Packit 577717
_internal_hl_read_cnts( long long *values, int array_len, int flag )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
	HighLevelInfo *state = NULL;
Packit 577717
Packit 577717
	if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK )
Packit 577717
		return ( retval );
Packit 577717
Packit 577717
	if ( state->running != HL_START || array_len < state->num_evts )
Packit 577717
		return ( PAPI_EINVAL );
Packit 577717
Packit 577717
	if ( flag == HL_ACCUM )
Packit 577717
		return ( PAPI_accum( state->EventSet, values ) );
Packit 577717
	else if ( flag == HL_READ ) {
Packit 577717
		if ( ( retval = PAPI_read( state->EventSet, values ) ) != PAPI_OK )
Packit 577717
			return ( retval );
Packit 577717
		return ( PAPI_reset( state->EventSet ) );
Packit 577717
	}
Packit 577717
Packit 577717
	/* Invalid flag passed in */
Packit 577717
	return ( PAPI_EINVAL );
Packit 577717
}
Packit 577717
Packit 577717
/** @class PAPI_read_counters
Packit 577717
 *	@brief Read and reset counters.
Packit 577717
 *
Packit 577717
 *	@par C Interface:
Packit 577717
 *	\#include <papi.h> @n
Packit 577717
 *	int PAPI_read_counters( long long *values, int array_len );
Packit 577717
 *
Packit 577717
 * @param *values
Packit 577717
 *		an array to hold the counter values of the counting events
Packit 577717
 * @param arry_len
Packit 577717
 *		the number of items in the *events array
Packit 577717
 *
Packit 577717
 * @pre 
Packit 577717
 *		These calls assume an initialized PAPI library and a properly added event set.
Packit 577717
 *
Packit 577717
 * @post 
Packit 577717
 *		The counters are reset and left running after the call.
Packit 577717
 *
Packit 577717
 *	@retval PAPI_EINVAL 
Packit 577717
 *		One or more of the arguments is invalid.
Packit 577717
 *	@retval PAPI_ESYS 
Packit 577717
 *		A system or C library call failed inside PAPI, see the errno variable. 
Packit 577717
 *
Packit 577717
 * PAPI_read_counters() copies the event counters into the array *values. 
Packit 577717
 *
Packit 577717
 *	@code
Packit 577717
do_100events();
Packit 577717
if ( PAPI_read_counters( values, num_hwcntrs ) != PAPI_OK )
Packit 577717
	handlw_error(1);
Packit 577717
// values[0] now equals 100 
Packit 577717
do_100events();
Packit 577717
if ( PAPI_accum_counters( values, num_hwcntrs ) != PAPI_OK )
Packit 577717
	handle_error(1);
Packit 577717
// values[0] now equals 200
Packit 577717
values[0] = -100;
Packit 577717
do_100events();
Packit 577717
if ( PAPI_accum_counters(values, num_hwcntrs ) != PAPI_OK )
Packit 577717
	handle_error();
Packit 577717
// values[0] now equals 0
Packit 577717
 *	@endcode
Packit 577717
 *
Packit 577717
 * @see PAPI_set_opt() PAPI_start_counters()
Packit 577717
 */
Packit 577717
int
Packit 577717
PAPI_read_counters( long long *values, int array_len )
Packit 577717
{
Packit 577717
	return ( _internal_hl_read_cnts( values, array_len, HL_READ ) );
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/** @class PAPI_accum_counters
Packit 577717
 *	@brief Accumulate and reset counters.
Packit 577717
 *
Packit 577717
 *	@par C Interface:
Packit 577717
 *	\#include <papi.h> @n
Packit 577717
 *	int PAPI_accum_counters( long long *values, int array_len );
Packit 577717
 *
Packit 577717
 * @param *values
Packit 577717
 *		an array to hold the counter values of the counting events
Packit 577717
 * @param arry_len
Packit 577717
 *		the number of items in the *events array
Packit 577717
 *
Packit 577717
 * @pre 
Packit 577717
 *		These calls assume an initialized PAPI library and a properly added event set.
Packit 577717
 *
Packit 577717
 * @post 
Packit 577717
 *		The counters are reset and left running after the call.
Packit 577717
 * 
Packit 577717
 *	@retval PAPI_EINVAL 
Packit 577717
 *		One or more of the arguments is invalid.
Packit 577717
 *	@retval PAPI_ESYS 
Packit 577717
 *		A system or C library call failed inside PAPI, see the errno variable. 
Packit 577717
 *
Packit 577717
 * PAPI_accum_counters() adds the event counters into the array *values. 
Packit 577717
 *
Packit 577717
 *	@code
Packit 577717
do_100events();
Packit 577717
if ( PAPI_read_counters( values, num_hwcntrs ) != PAPI_OK )
Packit 577717
	handlw_error(1);
Packit 577717
// values[0] now equals 100 
Packit 577717
do_100events();
Packit 577717
if ( PAPI_accum_counters( values, num_hwcntrs ) != PAPI_OK )
Packit 577717
	handle_error(1);
Packit 577717
// values[0] now equals 200
Packit 577717
values[0] = -100;
Packit 577717
do_100events();
Packit 577717
if ( PAPI_accum_counters(values, num_hwcntrs ) != PAPI_OK )
Packit 577717
	handle_error();
Packit 577717
// values[0] now equals 0
Packit 577717
 *	@endcode
Packit 577717
 *
Packit 577717
 * @see PAPI_set_opt() PAPI_start_counters()
Packit 577717
 */
Packit 577717
int
Packit 577717
PAPI_accum_counters( long long *values, int array_len )
Packit 577717
{
Packit 577717
	if ( values == NULL || array_len <= 0 )
Packit 577717
		return PAPI_EINVAL;
Packit 577717
Packit 577717
	return ( _internal_hl_read_cnts( values, array_len, HL_ACCUM ) );
Packit 577717
}
Packit 577717
Packit 577717
/** @class PAPI_stop_counters
Packit 577717
 *	@brief Stop counting hardware events and reset values to zero.
Packit 577717
 *
Packit 577717
 *	@par C Interface:
Packit 577717
 *	\#include <papi.h> @n
Packit 577717
 *	int PAPI_stop_counters( long long *values, int array_len );
Packit 577717
 *
Packit 577717
 * @param *values
Packit 577717
 *		an array where to put the counter values
Packit 577717
 * @param array_len
Packit 577717
 *		the number of items in the *values array 
Packit 577717
 *
Packit 577717
 * @post 
Packit 577717
 *	After this function is called, the values are reset to zero. 
Packit 577717
 *
Packit 577717
 *	@retval PAPI_EINVAL 
Packit 577717
 *		One or more of the arguments is invalid.
Packit 577717
 *	@retval PAPI_ENOTRUN 
Packit 577717
 *		The EventSet is not started yet.
Packit 577717
 *	@retval PAPI_ENOEVST 
Packit 577717
 *		The EventSet has not been added yet. 
Packit 577717
 *
Packit 577717
 * The PAPI_stop_counters() function stops the counters and copies the counts 
Packit 577717
 * into the *values array. 
Packit 577717
 * The counters must have been started by a previous call to PAPI_start_counters(). 
Packit 577717
 *
Packit 577717
 *	\code
Packit 577717
int Events[2] = { PAPI_TOT_CYC, PAPI_TOT_INS };
Packit 577717
long long values[2];
Packit 577717
if ( PAPI_start_counters( Events, 2 ) != PAPI_OK )
Packit 577717
	handle_error(1);
Packit 577717
your_slow_code();
Packit 577717
if ( PAPI_stop_counters( values, 2 ) != PAPI_OK )
Packit 577717
	handle_error(1);
Packit 577717
 *	\endcode
Packit 577717
 * 
Packit 577717
 * @see PAPI_read_counters() PAPI_start_counters() PAPI_set_opt()
Packit 577717
 */
Packit 577717
int
Packit 577717
PAPI_stop_counters( long long *values, int array_len )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
	HighLevelInfo *state = NULL;
Packit 577717
Packit 577717
	if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK )
Packit 577717
		return ( retval );
Packit 577717
Packit 577717
	if ( state->running == 0 )
Packit 577717
		return ( PAPI_ENOTRUN );
Packit 577717
Packit 577717
	if ( state->running == HL_START ) {
Packit 577717
		if ( array_len < state->num_evts  || values == NULL) {
Packit 577717
			return ( PAPI_EINVAL );
Packit 577717
		} else {
Packit 577717
			retval = PAPI_stop( state->EventSet, values );
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	if ( state->running > HL_START ) {
Packit 577717
		long long tmp_values[3];
Packit 577717
		retval = PAPI_stop( state->EventSet, tmp_values );
Packit 577717
	}
Packit 577717
	
Packit 577717
	if ( retval == PAPI_OK ) {
Packit 577717
		_internal_cleanup_hl_info( state );
Packit 577717
		PAPI_cleanup_eventset( state->EventSet );
Packit 577717
	}
Packit 577717
	APIDBG( "PAPI_stop_counters returns %d\n", retval );
Packit 577717
	return retval;
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
_papi_hwi_shutdown_highlevel(  )
Packit 577717
{
Packit 577717
	HighLevelInfo *state = NULL;
Packit 577717
Packit 577717
	if ( PAPI_get_thr_specific( PAPI_HIGH_LEVEL_TLS, ( void ** ) &state ) ==
Packit 577717
		 PAPI_OK ) {
Packit 577717
		if ( state )
Packit 577717
			papi_free( state );
Packit 577717
	}
Packit 577717
}