libprof/libprof.c

80 lines
1.8 KiB
C

#include <gint/timer.h>
#include <gint/clock.h>
#include <gint/mpu/tmu.h>
#include <gint/std/stdlib.h>
#include <gint/hardware.h>
#include <libprof.h>
/* Recursion depth of each function currently being executed */
uint8_t *prof_rec = NULL;
/* Time that has elapsed within each function; the value for a given function
is only relevant when it is not executing, due to optimizations */
uint32_t *prof_elapsed = NULL;
/* Timer counter */
uint32_t volatile *prof_tcnt = NULL;
/* Timer ID */
static int prof_timer = -1;
/* prof_init(): Initialize the profiler's data and timer */
int prof_init(int context_count)
{
prof_rec = malloc(context_count * sizeof *prof_rec);
prof_elapsed = malloc(context_count * sizeof *prof_elapsed);
/* Get a TMU with the exact constant 0xffffffff */
int timer = -1;
for(int t = 2; t >= 0 && timer == -1; t--)
{
timer = timer_setup(t, 0xffffffff, NULL);
}
if(!prof_rec || !prof_elapsed || timer == -1)
{
prof_quit();
return 1;
}
/* Fix the configuration done by gint by disabling the interrupt */
if(isSH3())
{
SH7705_TMU.TMU[timer].TCR.UNIE = 0;
prof_tcnt = &SH7705_TMU.TMU[timer].TCNT;
}
else
{
SH7305_TMU.TMU[timer].TCR.UNIE = 0;
prof_tcnt = &SH7305_TMU.TMU[timer].TCNT;
}
timer_start(timer);
prof_timer = timer;
return 0;
}
/* prof_quit(): Free the profiler's data and timer */
void prof_quit(void)
{
if(prof_timer >= 0) timer_stop(prof_timer);
if(prof_rec) free(prof_rec);
if(prof_elapsed) free(prof_elapsed);
prof_timer = -1;
prof_rec = NULL;
prof_elapsed = NULL;
}
//---
// Post-measurement analysis
//---
/* prof_time(): Time spent in a given context, in microseconds */
uint32_t prof_time(int ctx)
{
int Pphi = clock_freq()->Pphi_f;
uint64_t time = prof_elapsed[ctx];
return (time * 4 * 1000000) / Pphi;
}