gintctl/src/perf/cpucache.c

161 lines
3.4 KiB
C

#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/clock.h>
#include <gintctl/perf.h>
#include <gintctl/util.h>
#include <gintctl/plot.h>
#include <libprof.h>
#include <stdio.h>
#define CACHE_MAX 4096
#define SAMPLES 129
extern void cpucache_nop1024(int repeats);
extern void cpucache_rounds(uint8_t const *buf, size_t len, int rounds);
uint32_t test_nop4096(void)
{
prof_t prof = prof_make();
prof_enter(prof);
cpucache_nop1024(4);
prof_leave(prof);
/* Return the amount in Iphi cycles computed from the Pphi/4 measure */
clock_frequency_t const *freq = clock_freq();
uint64_t PLL_cycles = ((uint64_t)prof.elapsed * 4) * freq->Pphi_div;
return PLL_cycles / freq->Iphi_div;
}
uint32_t test_cpucache_rounds(uint8_t const *buf, size_t len, int rounds)
{
prof_t prof = prof_make();
prof_enter(prof);
cpucache_rounds(buf, len, rounds);
prof_leave(prof);
clock_frequency_t const *freq = clock_freq();
uint64_t PLL_cycles = ((uint64_t)prof.elapsed * 4) * freq->Pphi_div;
return PLL_cycles / freq->Iphi_div;
}
#ifdef FX9860G
static void tick_formatter(char *str, size_t size, int32_t v)
{
if(v == 0) snprintf(str, size, "0");
else snprintf(str, size, "%dk", v/1000);
}
#endif
/* gintctl_perf_cpucache(): CPU speed and cache size */
void gintctl_perf_cpucache(void)
{
int key = 0;
/* Test twice because this is sensitive to libprof initialization */
uint32_t nop4096 = test_nop4096();
nop4096 = test_nop4096();
uint8_t buf[CACHE_MAX];
int32_t x_size[SAMPLES];
int32_t y_time[SAMPLES];
struct plot plotspec = {
.data_x = x_size,
.data_y = y_time,
.data_len = SAMPLES,
#ifdef FX9860G
.area = {
.x = 0, .y = 18,
.w = 128, .h = 44,
},
.color = C_BLACK,
.ticks_x = {
.multiples = 250,
.subtick_divisions = 4,
.formatter = tick_formatter,
},
.ticks_y = {
.multiples = 20000,
.subtick_divisions = 2,
.formatter = tick_formatter,
},
.grid = {
.level = PLOT_MAINGRID,
.primary_color = C_BLACK,
.dotted = 1,
},
#endif
#ifdef FXCG50
.area = {
.x = 24, .y = 51,
.w = 340, .h = 120,
},
.color = C_RED,
.ticks_x = {
.multiples = CACHE_MAX / 16,
.subtick_divisions = 4,
},
.ticks_y = {
.multiples = 10000,
.subtick_divisions = 2,
},
.grid = {
.level = PLOT_FULLGRID,
.primary_color = C_RGB(20, 20, 20),
.secondary_color = C_RGB(28, 28, 28),
.dotted = 1,
},
#endif
};
int y_min = -1;
int y_max = -1;
for(int i = 0; i < SAMPLES; i++)
{
x_size[i] = (CACHE_MAX / (SAMPLES-1)) * i;
y_time[i] = test_cpucache_rounds(buf, x_size[i], 16);
if(y_time[i] < y_min || y_min == -1) y_min = y_time[i];
if(y_time[i] > y_max || y_max == -1) y_max = y_time[i];
}
while(key != KEY_EXIT)
{
dclear(C_WHITE);
row_title(_("CPU and cache", "CPU speed and cache size"));
#ifdef FX9860G
row_print(2, 1, "4096 nop: %d Iϕ", nop4096);
extern font_t font_hexa;
font_t const *old = dfont(&font_hexa);
plot(&plotspec);
dfont(old);
#endif
#ifdef FXCG50
row_print(1, 1, "Time for 4096 nop (with overhead): %d Iphi",
nop4096);
row_print(2, 1, "Time needed to read a buffer multiple times:");
plot(&plotspec);
row_print(12, 1, "X: Size of buffer (bytes)");
row_print(13, 1, "Y: Iphi cycles for 16 8-bit traversals");
row_print(14, 1, "Last samples suggests: %.2j Iphi/byte access",
100 * y_time[SAMPLES-1] / x_size[SAMPLES-1] / 16);
#endif
dupdate();
key = getkey().key;
}
}