Nugget
Loading...
Searching...
No Matches
Macros | Functions | Variables
memops-unroll.c File Reference
#include <stdint.h>
#include "common/hardware/counters.h"
#include "common/syscalls/syscalls.h"
#include "exotic/cester.h"
Include dependency graph for memops-unroll.c:

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
 

Macro Definition Documentation

◆ BIGWORDS

#define BIGWORDS   4096

◆ CESTER_MAYBE_TEST

#define CESTER_MAYBE_TEST   CESTER_TEST

◆ CESTER_NO_SIGNAL

#define CESTER_NO_SIGNAL

◆ CESTER_NO_TIME

#define CESTER_NO_TIME

◆ EXIT_FAILURE

#define EXIT_FAILURE   1

◆ EXIT_SUCCESS

#define EXIT_SUCCESS   0

◆ PCSX_TESTS

#define PCSX_TESTS   0

◆ SCRATCH

#define SCRATCH   ((uint32_t *)0x1f800000u)

◆ UNCACHED

#define UNCACHED (   p)    ((uint32_t *)(((uintptr_t)(p) & 0x1fffffffu) | 0xa0000000u))

◆ WORDS

#define WORDS   256

Function Documentation

◆ cester_assert_true() [1/2]

cester_assert_true ( wcopy<=best_copy+best_copy/  8u)

◆ cester_assert_true() [2/2]

cester_assert_true ( wset<=best_set+best_set/  8u)

◆ CESTER_BODY()

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()

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()

for ( )

◆ ramsyscall_printf() [1/2]

ramsyscall_printf ( = == cold cost per call)

◆ ramsyscall_printf() [2/2]

ramsyscall_printf ( )

◆ reportRate() [1/4]

reportRate ( "__wrap_memcpy"  ,
wcopy   
)

◆ reportRate() [2/4]

reportRate ( "__wrap_memset"  ,
wset   
)

◆ reportRate() [3/4]

reportRate ( "kernel copy B8U8"  ,
best_copy   
)

◆ reportRate() [4/4]

reportRate ( )

Variable Documentation

◆ memops

memops