00001 #ifndef PfmCodeAnalyserH
00002 #define PfmCodeAnalyserH 1
00003
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include <perfmon/pfmlib.h>
00007 #include <perfmon/perfmon.h>
00008 #include <perfmon/perfmon_dfl_smpl.h>
00009 #include <perfmon/pfmlib_core.h>
00010 #include <perfmon/pfmlib_intel_nhm.h>
00011 #include <string.h>
00012 #include <sys/types.h>
00013 #include <unistd.h>
00014
00015 #define MAX_EVT_NAME_LEN 256
00016 #define NUM_PMCS PFMLIB_MAX_PMCS
00017 #define NUM_PMDS PFMLIB_MAX_PMDS
00018 #define FMT_NAME PFM_DFL_SMPL_NAME
00019 #define MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS 4
00020 #define cpuid(func,eax,ebx,ecx,edx) __asm__ __volatile__ ("cpuid": "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (func));
00021
00022 class PfmCodeAnalyser
00023 {
00024 private:
00025 int used_counters_number;
00026 int nehalem;
00027 pfmlib_input_param_t inp;
00028 pfmlib_output_param_t outp;
00029 pfarg_ctx_t ctx;
00030 pfarg_pmd_t pd[NUM_PMDS];
00031 pfarg_pmc_t pc[NUM_PMCS];
00032 pfarg_load_t load_arg;
00033 int fd;
00034 char event_str[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS][MAX_EVT_NAME_LEN];
00035 bool inv[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS];
00036 unsigned int cmask[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS];
00037 pfmlib_core_input_param_t params;
00038 pfmlib_nhm_input_param_t nhm_params;
00039 int ret;
00040 unsigned i;
00041 unsigned long sum[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS];
00042 unsigned count;
00043 unsigned overhead_avg[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS];
00044
00045 private:
00046 PfmCodeAnalyser(const char *event0, unsigned int cmask_v0, bool inv_v0,
00047 const char *event1, unsigned int cmask_v1, bool inv_v1,
00048 const char *event2, unsigned int cmask_v2, bool inv_v2,
00049 const char *event3, unsigned int cmask_v3, bool inv_v3);
00050 PfmCodeAnalyser(PfmCodeAnalyser const&);
00051 PfmCodeAnalyser& operator=(PfmCodeAnalyser const&);
00052 ~PfmCodeAnalyser();
00053
00054 public:
00055 static PfmCodeAnalyser& Instance(const char *event0 = "UNHALTED_CORE_CYCLES", unsigned int cmask_v0 = 0, bool inv_v0 = false,
00056 const char *event1 = "", unsigned int cmask_v1 = 0, bool inv_v1 = false,
00057 const char *event2 = "", unsigned int cmask_v2 = 0, bool inv_v2 = false,
00058 const char *event3 = "", unsigned int cmask_v3 = 0, bool inv_v3 = false);
00059 void start();
00060 void stop();
00061 void stop_init();
00062 };
00063
00064 PfmCodeAnalyser::PfmCodeAnalyser(const char *event0, unsigned int cmask_v0, bool inv_v0,
00065 const char *event1, unsigned int cmask_v1, bool inv_v1,
00066 const char *event2, unsigned int cmask_v2, bool inv_v2,
00067 const char *event3, unsigned int cmask_v3, bool inv_v3)
00068 {
00069 int ax,bx,cx,dx;
00070 cpuid(1,ax,bx,cx,dx);
00071 int sse4_2_mask = 1 << 20;
00072 nehalem = cx & sse4_2_mask;
00073 strcpy(event_str[0], event0);
00074 strcpy(event_str[1], event1);
00075 strcpy(event_str[2], event2);
00076 strcpy(event_str[3], event3);
00077 cmask[0] = cmask_v0;
00078 cmask[1] = cmask_v1;
00079 cmask[2] = cmask_v2;
00080 cmask[3] = cmask_v3;
00081 inv[0] = inv_v0;
00082 inv[1] = inv_v1;
00083 inv[2] = inv_v2;
00084 inv[3] = inv_v3;
00085 used_counters_number = 0;
00086 for(int i=0; i<MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS; i++)
00087 {
00088 if(strlen(event_str[i])>0) used_counters_number++;
00089 }
00090 for(int i=0; i<used_counters_number; i++)
00091 {
00092 sum[i] = 0;
00093 overhead_avg[i] = 0;
00094 }
00095 count = 0;
00096 if(pfm_initialize() != PFMLIB_SUCCESS)
00097 {
00098 printf("Cannot initialize perfmon!!\nExiting...\n");
00099 exit(0);
00100 }
00101 while(count<3)
00102 {
00103 start();
00104 stop_init();
00105 }
00106 for(int i=0; i<used_counters_number; i++)
00107 {
00108 sum[i] = 0;
00109 }
00110 count = 0;
00111 while(count<10)
00112 {
00113 start();
00114 stop_init();
00115 }
00116 for(int i=0; i<used_counters_number; i++)
00117 {
00118 overhead_avg[i] = sum[i]/count;
00119 sum[i] = 0;
00120 }
00121 count = 0;
00122 }
00123
00124 PfmCodeAnalyser& PfmCodeAnalyser::Instance(const char *event0, unsigned int cmask_v0, bool inv_v0,
00125 const char *event1, unsigned int cmask_v1, bool inv_v1,
00126 const char *event2, unsigned int cmask_v2, bool inv_v2,
00127 const char *event3, unsigned int cmask_v3, bool inv_v3)
00128 {
00129 static PfmCodeAnalyser theSingleton(event0, cmask_v0, inv_v0, event1, cmask_v1, inv_v1, event2, cmask_v2, inv_v2, event3, cmask_v3, inv_v3);
00130 return theSingleton;
00131 }
00132
00133
00134
00135 void PfmCodeAnalyser::start()
00136 {
00137 memset(&ctx,0, sizeof(ctx));
00138 memset(&inp,0, sizeof(inp));
00139 memset(&outp,0, sizeof(outp));
00140 memset(pd, 0, sizeof(pd));
00141 memset(pc, 0, sizeof(pc));
00142 memset(&load_arg, 0, sizeof(load_arg));
00143 memset(¶ms, 0, sizeof(params));
00144 for(int i=0; i<used_counters_number; i++)
00145 {
00146 ret = pfm_find_full_event(event_str[i], &inp.pfp_events[i]);
00147 if(ret != PFMLIB_SUCCESS)
00148 {
00149 fprintf(stderr, "ERROR: cannot find event: %s\naborting...\n", event_str[i]);
00150 exit(1);
00151 }
00152 }
00153 inp.pfp_dfl_plm = PFM_PLM3;
00154 inp.pfp_event_count = used_counters_number;
00155 for(int i=0; i<used_counters_number; i++)
00156 {
00157 if(inv[i])
00158 {
00159 (params.pfp_core_counters[i]).flags |= PFM_CORE_SEL_INV;
00160 (nhm_params.pfp_nhm_counters[i]).flags |= PFM_NHM_SEL_INV;
00161 }
00162 if(cmask[i]>0)
00163 {
00164 (params.pfp_core_counters[i]).cnt_mask = cmask[i];
00165 (nhm_params.pfp_nhm_counters[i]).cnt_mask = cmask[i];
00166 }
00167 }
00168 if(nehalem)
00169 {
00170 ret = pfm_dispatch_events(&inp, &nhm_params, &outp, NULL);
00171 }
00172 else
00173 {
00174 ret = pfm_dispatch_events(&inp, ¶ms, &outp, NULL);
00175 }
00176 if(ret != PFMLIB_SUCCESS)
00177 {
00178 fprintf(stderr, "ERROR: cannot dispatch events: %s\naborting...\n", pfm_strerror(ret));
00179 exit(1);
00180 }
00181 for(unsigned int i=0; i<outp.pfp_pmc_count; i++)
00182 {
00183 pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
00184 pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
00185 }
00186 for(unsigned int i=0; i<outp.pfp_pmd_count; i++)
00187 {
00188 pd[i].reg_num = outp.pfp_pmds[i].reg_num;
00189 pd[i].reg_value = 0;
00190 }
00191 fd = pfm_create_context(&ctx, NULL, 0, 0);
00192 if(fd == -1)
00193 {
00194 fprintf(stderr, "ERROR: Context not created\naborting...\n");
00195 exit(1);
00196 }
00197 if(pfm_write_pmcs(fd, pc, outp.pfp_pmc_count) == -1)
00198 {
00199 fprintf(stderr, "ERROR: Could not write pmcs\naborting...\n");
00200 exit(1);
00201 }
00202 if(pfm_write_pmds(fd, pd, outp.pfp_pmd_count) == -1)
00203 {
00204 fprintf(stderr, "ERROR: Could not write pmds\naborting...\n");
00205 exit(1);
00206 }
00207 load_arg.load_pid = getpid();
00208 if(pfm_load_context(fd, &load_arg) == -1)
00209 {
00210 fprintf(stderr, "ERROR: Could not load context\naborting...\n");
00211 exit(1);
00212 }
00213 pfm_start(fd, NULL);
00214 }
00215
00216
00217
00218
00219
00220
00221 void PfmCodeAnalyser::stop()
00222 {
00223 pfm_stop(fd);
00224 if(pfm_read_pmds(fd, pd, inp.pfp_event_count) == -1)
00225 {
00226 fprintf(stderr, "ERROR: Could not read pmds\naborting...\n");
00227 exit(1);
00228 }
00229
00230 for(int i=0; i<used_counters_number; i++)
00231 {
00232 sum[i] += (pd[i].reg_value - overhead_avg[i]);
00233 }
00234 count++;
00235 close(fd);
00236 }
00237
00238 void PfmCodeAnalyser::stop_init()
00239 {
00240 pfm_stop(fd);
00241 if(pfm_read_pmds(fd, pd, inp.pfp_event_count) == -1)
00242 {
00243 fprintf(stderr, "ERROR: Could not read pmds\naborting...\n");
00244 exit(1);
00245 }
00246
00247 for(int i=0; i<used_counters_number; i++)
00248 {
00249 sum[i] += (pd[i].reg_value);
00250 }
00251 count++;
00252 close(fd);
00253 }
00254
00255 PfmCodeAnalyser::~PfmCodeAnalyser()
00256 {
00257 for(int i=0; i<used_counters_number; i++)
00258 {
00259 printf("Event: %s\nTotal count:%lu\nNumber of counts:%u\nAverage count:%f\nOverhead removed:%u\n", event_str[i], sum[i], count, (double)sum[i]/count, overhead_avg[i]);
00260 }
00261 }
00262
00263 #endif //PfmCodeAnalyserH