| 1 |
#include "driver.h" |
| 2 |
#include "osinline.h" |
| 3 |
|
| 4 |
static int use_profiler; |
| 5 |
|
| 6 |
/* |
| 7 |
* Versions of GNU C earlier that 2.7 have big problems with the UINT64 |
| 8 |
* so we make it into an unsigned long here. |
| 9 |
*/ |
| 10 |
|
| 11 |
#ifdef __GNUC__ |
| 12 |
#if (__GNUC__ < 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7)) |
| 13 |
#define UINT64 unsigned long |
| 14 |
#endif |
| 15 |
#endif |
| 16 |
|
| 17 |
#define MEMORY 6 |
| 18 |
|
| 19 |
struct profile_data |
| 20 |
{ |
| 21 |
UINT64 count[MEMORY][PROFILER_TOTAL]; |
| 22 |
unsigned int cpu_context_switches[MEMORY]; |
| 23 |
}; |
| 24 |
|
| 25 |
static struct profile_data profile; |
| 26 |
static int memory; |
| 27 |
|
| 28 |
|
| 29 |
static int FILO_type[10]; |
| 30 |
static unsigned int FILO_start[10]; |
| 31 |
static int FILO_length; |
| 32 |
|
| 33 |
void profiler_start(void) |
| 34 |
{ |
| 35 |
use_profiler = 1; |
| 36 |
FILO_length = 0; |
| 37 |
} |
| 38 |
|
| 39 |
void profiler_stop(void) |
| 40 |
{ |
| 41 |
use_profiler = 0; |
| 42 |
} |
| 43 |
|
| 44 |
void profiler__mark(int type) |
| 45 |
{ |
| 46 |
unsigned int curr_cycles; |
| 47 |
|
| 48 |
|
| 49 |
if (!use_profiler) |
| 50 |
{ |
| 51 |
FILO_length = 0; |
| 52 |
return; |
| 53 |
} |
| 54 |
|
| 55 |
if (type >= PROFILER_CPU1 && type <= PROFILER_CPU8) |
| 56 |
profile.cpu_context_switches[memory]++; |
| 57 |
|
| 58 |
curr_cycles = osd_cycles(); |
| 59 |
|
| 60 |
if (type != PROFILER_END) |
| 61 |
{ |
| 62 |
if (FILO_length >= 10) |
| 63 |
{ |
| 64 |
logerror("Profiler error: FILO buffer overflow\n"); |
| 65 |
return; |
| 66 |
} |
| 67 |
|
| 68 |
if (FILO_length > 0) |
| 69 |
{ |
| 70 |
/* handle nested calls */ |
| 71 |
profile.count[memory][FILO_type[FILO_length-1]] += (unsigned int)(curr_cycles - FILO_start[FILO_length-1]); |
| 72 |
} |
| 73 |
FILO_type[FILO_length] = type; |
| 74 |
FILO_start[FILO_length] = curr_cycles; |
| 75 |
FILO_length++; |
| 76 |
} |
| 77 |
else |
| 78 |
{ |
| 79 |
if (FILO_length <= 0) |
| 80 |
{ |
| 81 |
logerror("Profiler error: FILO buffer underflow\n"); |
| 82 |
return; |
| 83 |
} |
| 84 |
|
| 85 |
profile.count[memory][FILO_type[FILO_length-1]] += (unsigned int)(curr_cycles - FILO_start[FILO_length-1]); |
| 86 |
FILO_length--; |
| 87 |
if (FILO_length > 0) |
| 88 |
{ |
| 89 |
/* handle nested calls */ |
| 90 |
FILO_start[FILO_length-1] = curr_cycles; |
| 91 |
} |
| 92 |
} |
| 93 |
} |
| 94 |
|
| 95 |
void profiler_show(struct mame_bitmap *bitmap) |
| 96 |
{ |
| 97 |
int i,j; |
| 98 |
UINT64 total,normalize; |
| 99 |
UINT64 computed; |
| 100 |
int line; |
| 101 |
char buf[30]; |
| 102 |
static char *names[PROFILER_TOTAL] = |
| 103 |
{ |
| 104 |
"CPU 1 ", |
| 105 |
"CPU 2 ", |
| 106 |
"CPU 3 ", |
| 107 |
"CPU 4 ", |
| 108 |
"CPU 5 ", |
| 109 |
"CPU 6 ", |
| 110 |
"CPU 7 ", |
| 111 |
"CPU 8 ", |
| 112 |
"Mem rd ", |
| 113 |
"Mem wr ", |
| 114 |
"Video ", |
| 115 |
"drawgfx", |
| 116 |
"copybmp", |
| 117 |
"tmdraw ", |
| 118 |
"tmdrroz", |
| 119 |
"tmupdat", |
| 120 |
"Blit ", |
| 121 |
"Sound ", |
| 122 |
"Mixer ", |
| 123 |
"Callbck", |
| 124 |
"Hiscore", |
| 125 |
"Input ", |
| 126 |
"Extra ", |
| 127 |
"User1 ", |
| 128 |
"User2 ", |
| 129 |
"User3 ", |
| 130 |
"User4 ", |
| 131 |
"Profilr", |
| 132 |
"Idle ", |
| 133 |
}; |
| 134 |
static int showdelay[PROFILER_TOTAL]; |
| 135 |
|
| 136 |
|
| 137 |
if (!use_profiler) return; |
| 138 |
|
| 139 |
profiler_mark(PROFILER_PROFILER); |
| 140 |
|
| 141 |
computed = 0; |
| 142 |
i = 0; |
| 143 |
while (i < PROFILER_PROFILER) |
| 144 |
{ |
| 145 |
for (j = 0;j < MEMORY;j++) |
| 146 |
computed += profile.count[j][i]; |
| 147 |
i++; |
| 148 |
} |
| 149 |
normalize = computed; |
| 150 |
while (i < PROFILER_TOTAL) |
| 151 |
{ |
| 152 |
for (j = 0;j < MEMORY;j++) |
| 153 |
computed += profile.count[j][i]; |
| 154 |
i++; |
| 155 |
} |
| 156 |
total = computed; |
| 157 |
|
| 158 |
if (total == 0 || normalize == 0) return; /* we have been just reset */ |
| 159 |
|
| 160 |
line = 0; |
| 161 |
for (i = 0;i < PROFILER_TOTAL;i++) |
| 162 |
{ |
| 163 |
computed = 0; |
| 164 |
{ |
| 165 |
for (j = 0;j < MEMORY;j++) |
| 166 |
computed += profile.count[j][i]; |
| 167 |
} |
| 168 |
if (computed || showdelay[i]) |
| 169 |
{ |
| 170 |
if (computed) showdelay[i] = Machine->drv->frames_per_second; |
| 171 |
showdelay[i]--; |
| 172 |
|
| 173 |
if (i < PROFILER_PROFILER) |
| 174 |
sprintf(buf,"%s%3d%%%3d%%",names[i], |
| 175 |
(int)((computed * 100 + total/2) / total), |
| 176 |
(int)((computed * 100 + normalize/2) / normalize)); |
| 177 |
else |
| 178 |
sprintf(buf,"%s%3d%%",names[i], |
| 179 |
(int)((computed * 100 + total/2) / total)); |
| 180 |
ui_text(bitmap,buf,0,(line++)*Machine->uifontheight); |
| 181 |
} |
| 182 |
} |
| 183 |
|
| 184 |
i = 0; |
| 185 |
for (j = 0;j < MEMORY;j++) |
| 186 |
i += profile.cpu_context_switches[j]; |
| 187 |
sprintf(buf,"CPU switches%4d",i / MEMORY); |
| 188 |
ui_text(bitmap,buf,0,(line++)*Machine->uifontheight); |
| 189 |
|
| 190 |
/* reset the counters */ |
| 191 |
memory = (memory + 1) % MEMORY; |
| 192 |
profile.cpu_context_switches[memory] = 0; |
| 193 |
for (i = 0;i < PROFILER_TOTAL;i++) |
| 194 |
profile.count[memory][i] = 0; |
| 195 |
|
| 196 |
profiler_mark(PROFILER_END); |
| 197 |
} |