|
Nugget
|
#include <stdint.h>#include "common/hardware/counters.h"#include "common/syscalls/syscalls.h"#include "exotic/cester.h"
Macros | |
| #define | PCSX_TESTS 0 |
| #define | CESTER_MAYBE_TEST CESTER_TEST |
| #define | CESTER_NO_SIGNAL |
| #define | CESTER_NO_TIME |
| #define | EXIT_SUCCESS 0 |
| #define | EXIT_FAILURE 1 |
| #define | WORDS 256 |
| #define | BIGWORDS 4096 |
| #define | SCRATCH ((uint32_t *)0x1f800000u) |
| #define | UNCACHED(p) ((uint32_t *)(((uintptr_t)(p) & 0x1fffffffu) | 0xa0000000u)) |
Functions | |
| CESTER_BODY (static int s_interruptsWereEnabled;typedef void(*)(void *dst, const void *src, uint32_t words) copyfn;typedef void(*)(void *dst, uint32_t value, uint32_t words) setfn;void copy_b2_u2(void *, const void *, uint32_t);void copy_b4_u4(void *, const void *, uint32_t);void copy_b8_u8(void *, const void *, uint32_t);void copy_b8_u16(void *, const void *, uint32_t);void copy_b8_u32(void *, const void *, uint32_t);void copy_b2_u32(void *, const void *, uint32_t);void copy_b4_u32(void *, const void *, uint32_t);void copy_b16_u16(void *, const void *, uint32_t);void copy_b16_u32(void *, const void *, uint32_t);void *__wrap_memcpy(void *, const void *, uint32_t);void *__wrap_memset(void *, int, uint32_t);void set_u1(void *, uint32_t, uint32_t);void set_u2(void *, uint32_t, uint32_t);void set_u4(void *, uint32_t, uint32_t);void set_u8(void *, uint32_t, uint32_t);void set_u16(void *, uint32_t, uint32_t);void set_u32(void *, uint32_t, uint32_t);void set_u64(void *, uint32_t, uint32_t);#define BIGWORDS static uint32_t s_bigSrc;static uint32_t s_bigDst;static uint32_t s_src;static uint32_t s_dst;#define SCRATCH #define UNCACHED(p) static uint32_t timeCopyN(copyfn fn, void *dst, const void *src, uint32_t words, uint32_t *first) { uint32_t best=0xffffu;for(int i=0;i< 8;i++) { uint16_t before=COUNTERS[2].value;fn(dst, src, words);uint16_t after=COUNTERS[2].value;uint32_t d=(uint16_t)(after - before);if(i==0 &&first) *first=d;if(d< best) best=d;} return best;} static uint32_t timeSetN(setfn fn, void *dst, uint32_t v, uint32_t words, uint32_t *first) { uint32_t best=0xffffu;for(int i=0;i< 8;i++) { uint16_t before=COUNTERS[2].value;fn(dst, v, words);uint16_t after=COUNTERS[2].value;uint32_t d=(uint16_t)(after - before);if(i==0 &&first) *first=d;if(d< best) best=d;} return best;} static uint32_t timeCopy(copyfn fn, void *dst, const void *src) { uint32_t best=0xffffu;for(int i=0;i< 8;i++) { uint16_t before=COUNTERS[2].value;fn(dst, src, WORDS);uint16_t after=COUNTERS[2].value;uint32_t d=(uint16_t)(after - before);if(d< best) best=d;} return best;} static uint32_t timeSet(setfn fn, void *dst, uint32_t v) { uint32_t best=0xffffu;for(int i=0;i< 8;i++) { uint16_t before=COUNTERS[2].value;fn(dst, v, WORDS);uint16_t after=COUNTERS[2].value;uint32_t d=(uint16_t)(after - before);if(d< best) best=d;} return best;} static int copyCorrect(copyfn fn) { for(uint32_t i=0;i< WORDS;i++) s_src[i]=i *2654435761u+1u;for(uint32_t i=0;i< WORDS+4;i++) s_dst[i]=0xdeadbeefu;fn(s_dst, s_src, WORDS);for(uint32_t i=0;i< WORDS;i++) if(s_dst[i] !=s_src[i]) return 0;for(uint32_t i=WORDS;i< WORDS+4;i++) if(s_dst[i] !=0xdeadbeefu) return 0;return 1;} static int setCorrect(setfn fn) { for(uint32_t i=0;i< WORDS+4;i++) s_dst[i]=0xdeadbeefu;fn(s_dst, 0x55555555u, WORDS);for(uint32_t i=0;i< WORDS;i++) if(s_dst[i] !=0x55555555u) return 0;for(uint32_t i=WORDS;i< WORDS+4;i++) if(s_dst[i] !=0xdeadbeefu) return 0;return 1;} static void reportN(const char *name, uint32_t words, uint32_t first, uint32_t best) { uint32_t cc=(best *100u+words/2)/words;uint32_t fc=(first *100u+words/2)/words;ramsyscall_printf(" %-16s n=%4u cold=%5u (%u.%02u) min8=%5u (%u.%02u cyc/word)\n", name, words, first, fc/100u, fc % 100u, best, cc/100u, cc % 100u);} static void reportRate(const char *name, uint32_t ticks) { uint32_t cc=(ticks *100u+WORDS/2)/WORDS;ramsyscall_printf(" %-14s ticks=%5u %u.%02u cyc/word\n", name, ticks, cc/100u, cc % 100u);}[BIGWORDS][BIGWORDS][WORDS][WORDS+4]) | |
| for (int i=0;i< 8;i++) | |
| ramsyscall_printf ("=== shipped routines vs best swept kernel ===\n") | |
| reportRate ("kernel set U=4", best_set) | |
| reportRate ("__wrap_memset", wset) | |
| reportRate ("kernel copy B8U8", best_copy) | |
| reportRate ("__wrap_memcpy", wcopy) | |
| cester_assert_true (wset<=best_set+best_set/8u) | |
| cester_assert_true (wcopy<=best_copy+best_copy/8u) | |
| CESTER_MAYBE_TEST (bufferSizeAndIcache, memops, uint32_t f;ramsyscall_printf("=== buffer size and cold-vs-warm ===\n");uint32_t b;b=timeSetN(set_u4, s_dst, 0, WORDS, &f);reportN("set U=4", WORDS, f, b);b=timeSetN(set_u4, s_bigDst, 0, BIGWORDS, &f);reportN("set U=4", BIGWORDS, f, b);b=timeSetN(set_u64, s_dst, 0, WORDS, &f);reportN("set U=64", WORDS, f, b);b=timeSetN(set_u64, s_bigDst, 0, BIGWORDS, &f);reportN("set U=64", BIGWORDS, f, b);b=timeCopyN(copy_b8_u8, s_dst, s_src, WORDS, &f);reportN("copy B8 U8", WORDS, f, b);b=timeCopyN(copy_b8_u8, s_bigDst, s_bigSrc, BIGWORDS, &f);reportN("copy B8 U8", BIGWORDS, f, b);b=timeCopyN(copy_b8_u32, s_dst, s_src, WORDS, &f);reportN("copy B8 U32", WORDS, f, b);b=timeCopyN(copy_b8_u32, s_bigDst, s_bigSrc, BIGWORDS, &f);reportN("copy B8 U32", BIGWORDS, f, b);b=timeCopyN(copy_b4_u4, s_bigDst, s_bigSrc, BIGWORDS, &f);reportN("copy B4 U4", BIGWORDS, f, b);b=timeCopyN(copy_b2_u2, s_bigDst, s_bigSrc, BIGWORDS, &f);reportN("copy B2 U2", BIGWORDS, f, b);) CESTER_MAYBE_TEST(coldCrossover | |
| ramsyscall_printf ("=== cold cost per call, B4U4 vs B8U8 (icache evicted between) ===\n") | |
Variables | |
| memops | |
| #define BIGWORDS 4096 |
| #define CESTER_MAYBE_TEST CESTER_TEST |
| #define CESTER_NO_SIGNAL |
| #define CESTER_NO_TIME |
| #define EXIT_FAILURE 1 |
| #define EXIT_SUCCESS 0 |
| #define PCSX_TESTS 0 |
| #define SCRATCH ((uint32_t *)0x1f800000u) |
| #define UNCACHED | ( | p | ) | ((uint32_t *)(((uintptr_t)(p) & 0x1fffffffu) | 0xa0000000u)) |
| #define WORDS 256 |
| cester_assert_true | ( | wcopy<=best_copy+best_copy/ | 8u | ) |
| cester_assert_true | ( | wset<=best_set+best_set/ | 8u | ) |
| CESTER_BODY | ( | static int s_interruptsWereEnabled;typedef void(*)(void *dst, const void *src, uint32_t words) copyfn;typedef void(*)(void *dst, uint32_t value, uint32_t words) setfn;void copy_b2_u2(void *, const void *, uint32_t);void copy_b4_u4(void *, const void *, uint32_t);void copy_b8_u8(void *, const void *, uint32_t);void copy_b8_u16(void *, const void *, uint32_t);void copy_b8_u32(void *, const void *, uint32_t);void copy_b2_u32(void *, const void *, uint32_t);void copy_b4_u32(void *, const void *, uint32_t);void copy_b16_u16(void *, const void *, uint32_t);void copy_b16_u32(void *, const void *, uint32_t);void *__wrap_memcpy(void *, const void *, uint32_t);void *__wrap_memset(void *, int, uint32_t);void set_u1(void *, uint32_t, uint32_t);void set_u2(void *, uint32_t, uint32_t);void set_u4(void *, uint32_t, uint32_t);void set_u8(void *, uint32_t, uint32_t);void set_u16(void *, uint32_t, uint32_t);void set_u32(void *, uint32_t, uint32_t);void set_u64(void *, uint32_t, uint32_t);#define BIGWORDS static uint32_t s_bigSrc;static uint32_t s_bigDst;static uint32_t s_src;static uint32_t s_dst;#define SCRATCH #define UNCACHED(p) static uint32_t timeCopyN(copyfn fn, void *dst, const void *src, uint32_t words, uint32_t *first) { uint32_t best=0xffffu;for(int i=0;i< 8;i++) { uint16_t before=COUNTERS[2].value;fn(dst, src, words);uint16_t after=COUNTERS[2].value;uint32_t d=(uint16_t)(after - before);if(i==0 &&first) *first=d;if(d< best) best=d;} return best;} static uint32_t timeSetN(setfn fn, void *dst, uint32_t v, uint32_t words, uint32_t *first) { uint32_t best=0xffffu;for(int i=0;i< 8;i++) { uint16_t before=COUNTERS[2].value;fn(dst, v, words);uint16_t after=COUNTERS[2].value;uint32_t d=(uint16_t)(after - before);if(i==0 &&first) *first=d;if(d< best) best=d;} return best;} static uint32_t timeCopy(copyfn fn, void *dst, const void *src) { uint32_t best=0xffffu;for(int i=0;i< 8;i++) { uint16_t before=COUNTERS[2].value;fn(dst, src, WORDS);uint16_t after=COUNTERS[2].value;uint32_t d=(uint16_t)(after - before);if(d< best) best=d;} return best;} static uint32_t timeSet(setfn fn, void *dst, uint32_t v) { uint32_t best=0xffffu;for(int i=0;i< 8;i++) { uint16_t before=COUNTERS[2].value;fn(dst, v, WORDS);uint16_t after=COUNTERS[2].value;uint32_t d=(uint16_t)(after - before);if(d< best) best=d;} return best;} static int copyCorrect(copyfn fn) { for(uint32_t i=0;i< WORDS;i++) s_src[i]=i *2654435761u+1u;for(uint32_t i=0;i< WORDS+4;i++) s_dst[i]=0xdeadbeefu;fn(s_dst, s_src, WORDS);for(uint32_t i=0;i< WORDS;i++) if(s_dst[i] !=s_src[i]) return 0;for(uint32_t i=WORDS;i< WORDS+4;i++) if(s_dst[i] !=0xdeadbeefu) return 0;return 1;} static int setCorrect(setfn fn) { for(uint32_t i=0;i< WORDS+4;i++) s_dst[i]=0xdeadbeefu;fn(s_dst, 0x55555555u, WORDS);for(uint32_t i=0;i< WORDS;i++) if(s_dst[i] !=0x55555555u) return 0;for(uint32_t i=WORDS;i< WORDS+4;i++) if(s_dst[i] !=0xdeadbeefu) return 0;return 1;} static void reportN(const char *name, uint32_t words, uint32_t first, uint32_t best) { uint32_t cc=(best *100u+words/2)/words;uint32_t fc=(first *100u+words/2)/words;ramsyscall_printf(" %-16s n=%4u cold=%5u (%u.%02u) min8=%5u (%u.%02u cyc/word)\n", name, words, first, fc/100u, fc % 100u, best, cc/100u, cc % 100u);} static void reportRate(const char *name, uint32_t ticks) { uint32_t cc=(ticks *100u+WORDS/2)/WORDS;ramsyscall_printf(" %-14s ticks=%5u %u.%02u cyc/word\n", name, ticks, cc/100u, cc % 100u);} | [BIGWORDS][BIGWORDS][WORDS][WORDS+4] | ) |
| CESTER_MAYBE_TEST | ( | bufferSizeAndIcache | , |
| memops | , | ||
| uint32_t f;ramsyscall_printf("=== buffer size and cold-vs-warm ===\n");uint32_t b; | b = timeSetN(set_u4, s_dst, 0, WORDS, &f); reportN("set U=4", WORDS, f, b); b = timeSetN(set_u4, s_bigDst, 0, BIGWORDS, &f); reportN("set U=4", BIGWORDS, f, b); b = timeSetN(set_u64, s_dst, 0, WORDS, &f); reportN("set U=64", WORDS, f, b); b = timeSetN(set_u64, s_bigDst, 0, BIGWORDS, &f);reportN("set U=64", BIGWORDS, f, b); b = timeCopyN(copy_b8_u8, s_dst, s_src, WORDS, &f); reportN("copy B8 U8", WORDS, f, b); b = timeCopyN(copy_b8_u8, s_bigDst, s_bigSrc, BIGWORDS, &f); reportN("copy B8 U8", BIGWORDS, f, b); b = timeCopyN(copy_b8_u32, s_dst, s_src, WORDS, &f); reportN("copy B8 U32", WORDS, f, b); b = timeCopyN(copy_b8_u32, s_bigDst, s_bigSrc, BIGWORDS, &f); reportN("copy B8 U32", BIGWORDS, f, b); b = timeCopyN(copy_b4_u4, s_bigDst, s_bigSrc, BIGWORDS, &f); reportN("copy B4 U4", BIGWORDS, f, b); b = timeCopyN(copy_b2_u2, s_bigDst, s_bigSrc, BIGWORDS, &f); reportN("copy B2 U2", BIGWORDS, f, b); |
||
| ) |
| for | ( | ) |
| ramsyscall_printf | ( | " | = == cold cost per call | ) |
| ramsyscall_printf | ( | ) |
| reportRate | ( | "__wrap_memcpy" | , |
| wcopy | |||
| ) |
| reportRate | ( | "__wrap_memset" | , |
| wset | |||
| ) |
| reportRate | ( | "kernel copy B8U8" | , |
| best_copy | |||
| ) |
| reportRate | ( | ) |
| memops |