Skip to content

Commit 53b5eeb

Browse files
Add a simple statistical profiler
Enabled by -p, will sample program counter and store frequency. Using "-i 1" will make execution pause on every instruction and sample PC. host-sdl -p -i 1 foo.bin | grep times > log.txt cat log.txt | sort -n -k4 Can match addresses with riscv64-elf-objdump -S -d -f foo.bin
1 parent 6a6d7f1 commit 53b5eeb

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

hosts/host-sdl/host-sdl.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ int HEIGHT = 200;
2222
#define WINDOW_WIDTH WIDTH*3
2323
#define WINDOW_HEIGHT HEIGHT*3
2424

25+
static uint32_t *profiling_data = NULL;
26+
2527
// circular buffer of keypresses, so vm code can read them as it's ready
2628
typedef struct {
2729
bool down;
@@ -39,6 +41,29 @@ static int16_t audioBuffer[AUDIOBUFFER_LEN];
3941
static int audioBufferWr = 0;
4042
static int audioBufferRd = 0;
4143

44+
void profiling_init(uvm32_state_t *vmst) {
45+
profiling_data = malloc(sizeof(uint32_t) * UVM32_MEMORY_SIZE);
46+
memset(profiling_data, 0x00, sizeof(uint32_t) * UVM32_MEMORY_SIZE);
47+
}
48+
49+
void profiling_update(uvm32_state_t *vmst) {
50+
uint32_t pc_rel = uvm32_getProgramCounter(vmst) - 0x80000000;
51+
if (pc_rel > UVM32_MEMORY_SIZE) {
52+
// don't handle PC being in extram
53+
printf("pc > memory size! %08x\n", pc_rel);
54+
} else {
55+
profiling_data[pc_rel] += 1;
56+
}
57+
}
58+
59+
void profiling_dump(void) {
60+
for (int i=0;i<UVM32_MEMORY_SIZE;i++) {
61+
if (profiling_data[i] > 0) {
62+
printf("Addr %08x hit %d times\n", 0x80000000 + i, profiling_data[i]);
63+
}
64+
}
65+
}
66+
4267
void key_enq(uint16_t scancode, bool down) {
4368
keyBuffer[keyBufferWr].scancode = scancode;
4469
keyBuffer[keyBufferWr].down = down;
@@ -126,6 +151,7 @@ void usage(const char *name) {
126151
printf(" -h show help\n");
127152
printf(" -i <num instructions> max instrs before requiring a syscall\n");
128153
printf(" -e <extram size> numbers of bytes for extram\n");
154+
printf(" -p enable profiling\n");
129155
exit(1);
130156
}
131157

@@ -168,6 +194,7 @@ int main(int argc, char *argv[]) {
168194
SDL_Window *screen = NULL;
169195
SDL_Event event;
170196
SDL_Texture *render_target = NULL;
197+
bool use_profiling = false;
171198

172199
// memory for vmst is very large, so allocate
173200
vmst = (uvm32_state_t *)malloc(sizeof(uvm32_state_t));
@@ -177,7 +204,7 @@ int main(int argc, char *argv[]) {
177204
}
178205

179206
// parse commandline args
180-
while ((c = getopt(argc, argv, "hi:e:W:H:")) != -1) {
207+
while ((c = getopt(argc, argv, "hi:e:W:H:p")) != -1) {
181208
switch(c) {
182209
case 'h':
183210
usage(argv[0]);
@@ -197,6 +224,9 @@ int main(int argc, char *argv[]) {
197224
case 'H':
198225
HEIGHT = strtoll(optarg, NULL, 10);
199226
break;
227+
case 'p':
228+
use_profiling = true;
229+
break;
200230
}
201231
}
202232
if (optind < argc) {
@@ -261,6 +291,10 @@ int main(int argc, char *argv[]) {
261291
}
262292
SDL_ResumeAudioStreamDevice(stream);
263293

294+
if (use_profiling) {
295+
profiling_init(vmst);
296+
}
297+
264298
while (isrunning) {
265299
SDL_PollEvent(&event);
266300

@@ -280,6 +314,10 @@ int main(int argc, char *argv[]) {
280314
break;
281315
}
282316

317+
if (use_profiling) {
318+
profiling_update(vmst);
319+
}
320+
283321
total_instrs += uvm32_run(vmst, &evt, max_instrs_per_run); // num instructions before vm considered hung
284322
num_syscalls++;
285323

@@ -396,6 +434,10 @@ int main(int argc, char *argv[]) {
396434

397435
printf("Executed total of %lu instructions and %lu syscalls\n", (unsigned long)total_instrs, (unsigned long)num_syscalls);
398436

437+
if (use_profiling) {
438+
profiling_dump();
439+
}
440+
399441
free(rom);
400442
if (extram_buf != NULL) {
401443
free(extram_buf);

0 commit comments

Comments
 (0)