diff options
-rw-r--r-- | apps/plugins/test_mem.c | 159 |
1 files changed, 87 insertions, 72 deletions
diff --git a/apps/plugins/test_mem.c b/apps/plugins/test_mem.c index dca6d8cefa..0d9729f96b 100644 --- a/apps/plugins/test_mem.c +++ b/apps/plugins/test_mem.c | |||
@@ -30,62 +30,42 @@ | |||
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #define LOOP_REPEAT_DRAM 256 | 32 | #define LOOP_REPEAT_DRAM 256 |
33 | static int loop_repeat_dram = LOOP_REPEAT_DRAM; | ||
33 | static volatile int buf_dram[BUF_SIZE] MEM_ALIGN_ATTR; | 34 | static volatile int buf_dram[BUF_SIZE] MEM_ALIGN_ATTR; |
34 | 35 | ||
35 | #if defined(PLUGIN_USE_IRAM) | 36 | #if defined(PLUGIN_USE_IRAM) |
36 | #define LOOP_REPEAT_IRAM 1024 | 37 | #define LOOP_REPEAT_IRAM 256 |
38 | static int loop_repeat_iram = LOOP_REPEAT_DRAM; | ||
37 | static volatile int buf_iram[BUF_SIZE] IBSS_ATTR MEM_ALIGN_ATTR; | 39 | static volatile int buf_iram[BUF_SIZE] IBSS_ATTR MEM_ALIGN_ATTR; |
38 | #endif | 40 | #endif |
39 | 41 | ||
40 | /* (Byte per loop * loops)>>20 * ticks per s * 10 / ticks = dMB per s */ | 42 | /* (Byte per loop * loops)>>20 * ticks per s * 10 / ticks = dMB per s */ |
41 | #define dMB_PER_SEC(cnt, delta) ((((BUF_SIZE*sizeof(int)*cnt)>>20)*HZ*10)/delta) | 43 | #define dMB_PER_SEC(buf_size, cnt, delta) ((((buf_size*sizeof(int)*cnt)>>20)*HZ*10)/delta) |
42 | 44 | ||
43 | void memset_test(volatile int *buf, int buf_size, int loop_cnt, | 45 | static void memset_test(volatile int *buf, int buf_size, int loop_cnt) |
44 | int line, char *ramtype) | ||
45 | { | 46 | { |
46 | int delta, dMB, i; | 47 | size_t buf_bytes = buf_size*sizeof(buf[0]); |
47 | int last_tick = *rb->current_tick; | 48 | for(int i = 0; i < loop_cnt; i++) |
48 | |||
49 | for(i=0; i < loop_cnt; i++) | ||
50 | { | 49 | { |
51 | memset((void *)buf, 0xff, buf_size*sizeof(int)); | 50 | memset((void*)buf, 0xff, buf_bytes); |
52 | } | 51 | } |
53 | |||
54 | delta = *rb->current_tick - last_tick; | ||
55 | delta = delta>0 ? delta : delta+1; | ||
56 | dMB = dMB_PER_SEC(loop_cnt, delta); | ||
57 | rb->screens[0]->putsf(0, line, "%s st: %3d.%d MB/s (%3d ticks for %d MB)", | ||
58 | ramtype, dMB/10, dMB%10, delta, | ||
59 | (loop_cnt*BUF_SIZE*4)>>20); | ||
60 | } | 52 | } |
61 | 53 | ||
62 | void memcpy_test(volatile int *buf, int buf_size, int loop_cnt, | 54 | static void memcpy_test(volatile int *buf, int buf_size, int loop_cnt) |
63 | int line, char *ramtype) | ||
64 | { | 55 | { |
65 | int delta, dMB, i; | 56 | /* half-size memcpy since memory regions must not overlap */ |
66 | int last_tick = *rb->current_tick; | 57 | void* half_buf = (void*)(&buf[buf_size/2]); |
58 | size_t half_buf_bytes = buf_size * sizeof(buf[0]) / 2; | ||
67 | 59 | ||
68 | /* double loop count to compensate for half size memcpy */ | 60 | /* double loop count to compensate for half size memcpy */ |
69 | for(i=0; i < loop_cnt*2; i++) | 61 | for(int i = 0; i < loop_cnt*2; i++) |
70 | { | 62 | { |
71 | memcpy((void *)buf+(buf_size*sizeof(int)/2), | 63 | memcpy((void*)&buf[0], half_buf, half_buf_bytes); |
72 | (void *)buf, buf_size*sizeof(int)/2); | ||
73 | } | 64 | } |
74 | |||
75 | delta = *rb->current_tick - last_tick; | ||
76 | delta = delta>0 ? delta : delta+1; | ||
77 | dMB = dMB_PER_SEC(loop_cnt, delta); | ||
78 | rb->screens[0]->putsf(0, line, "%s cp: %3d.%d MB/s (%3d ticks for %d MB)", | ||
79 | ramtype, dMB/10, dMB%10, delta, | ||
80 | (loop_cnt*BUF_SIZE*4)>>21); | ||
81 | } | 65 | } |
82 | 66 | ||
83 | void write_test(volatile int *buf, int buf_size, int loop_cnt, | 67 | static void write_test(volatile int *buf, int buf_size, int loop_cnt) |
84 | int line, char *ramtype) | ||
85 | { | 68 | { |
86 | int delta, dMB; | ||
87 | int last_tick = *rb->current_tick; | ||
88 | |||
89 | #if defined(CPU_ARM) | 69 | #if defined(CPU_ARM) |
90 | asm volatile ( | 70 | asm volatile ( |
91 | "mov r0, #0 \n" | 71 | "mov r0, #0 \n" |
@@ -108,10 +88,9 @@ void write_test(volatile int *buf, int buf_size, int loop_cnt, | |||
108 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory", "cc" | 88 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory", "cc" |
109 | ); | 89 | ); |
110 | #else | 90 | #else |
111 | int i, j; | 91 | for(int i = 0; i < loop_cnt; i++) |
112 | for(i = 0; i < loop_cnt; i++) | ||
113 | { | 92 | { |
114 | for (j = 0; j < buf_size; j+=4) | 93 | for(int j = 0; j < buf_size; j+=4) |
115 | { | 94 | { |
116 | buf[j ] = j; | 95 | buf[j ] = j; |
117 | buf[j+1] = j+1; | 96 | buf[j+1] = j+1; |
@@ -120,20 +99,10 @@ void write_test(volatile int *buf, int buf_size, int loop_cnt, | |||
120 | } | 99 | } |
121 | } | 100 | } |
122 | #endif | 101 | #endif |
123 | delta = *rb->current_tick - last_tick; | ||
124 | delta = delta>0 ? delta : delta+1; | ||
125 | dMB = dMB_PER_SEC(loop_cnt, delta); | ||
126 | rb->screens[0]->putsf(0, line, "%s wr: %3d.%d MB/s (%3d ticks for %d MB)", | ||
127 | ramtype, dMB/10, dMB%10, delta, | ||
128 | (loop_cnt*BUF_SIZE*4)>>20); | ||
129 | } | 102 | } |
130 | 103 | ||
131 | void read_test(volatile int *buf, int buf_size, int loop_cnt, | 104 | static void read_test(volatile int *buf, int buf_size, int loop_cnt) |
132 | int line, char *ramtype) | ||
133 | { | 105 | { |
134 | int delta, dMB; | ||
135 | int last_tick = *rb->current_tick; | ||
136 | |||
137 | #if defined(CPU_ARM) | 106 | #if defined(CPU_ARM) |
138 | asm volatile ( | 107 | asm volatile ( |
139 | "mov r6, %[loops] \n" | 108 | "mov r6, %[loops] \n" |
@@ -142,8 +111,8 @@ void read_test(volatile int *buf, int buf_size, int loop_cnt, | |||
142 | "mov r5, %[size] \n" | 111 | "mov r5, %[size] \n" |
143 | ".inner_loop_write: \n" | 112 | ".inner_loop_write: \n" |
144 | "ldmia r4!, {r0-r3} \n" | 113 | "ldmia r4!, {r0-r3} \n" |
145 | "ldmia r4!, {r0-r3} \n" | ||
146 | "subs r5, r5, #8 \n" | 114 | "subs r5, r5, #8 \n" |
115 | "ldmia r4!, {r0-r3} \n" | ||
147 | "bgt .inner_loop_write \n" | 116 | "bgt .inner_loop_write \n" |
148 | "subs r6, r6, #1 \n" | 117 | "subs r6, r6, #1 \n" |
149 | "bgt .outer_loop_write \n" | 118 | "bgt .outer_loop_write \n" |
@@ -152,10 +121,10 @@ void read_test(volatile int *buf, int buf_size, int loop_cnt, | |||
152 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory", "cc" | 121 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory", "cc" |
153 | ); | 122 | ); |
154 | #else | 123 | #else |
155 | int i, j, x; | 124 | int x; |
156 | for(i = 0; i < loop_cnt; i++) | 125 | for(int i = 0; i < loop_cnt; i++) |
157 | { | 126 | { |
158 | for(j = 0; j < buf_size; j+=4) | 127 | for(int j = 0; j < buf_size; j+=4) |
159 | { | 128 | { |
160 | x = buf[j ]; | 129 | x = buf[j ]; |
161 | x = buf[j+2]; | 130 | x = buf[j+2]; |
@@ -164,14 +133,56 @@ void read_test(volatile int *buf, int buf_size, int loop_cnt, | |||
164 | } | 133 | } |
165 | } | 134 | } |
166 | #endif | 135 | #endif |
136 | } | ||
137 | |||
138 | enum test_type { | ||
139 | READ, | ||
140 | WRITE, | ||
141 | MEMSET, | ||
142 | MEMCPY, | ||
143 | }; | ||
144 | |||
145 | static const char tests[][3] = { | ||
146 | [READ] = "rd", | ||
147 | [WRITE] = "wr", | ||
148 | [MEMSET] = "ms", | ||
149 | [MEMCPY] = "mc", | ||
150 | }; | ||
151 | |||
152 | static int line; | ||
153 | #define TEST_MEM_PRINTF(...) rb->screens[0]->putsf(0, line++, __VA_ARGS__) | ||
154 | |||
155 | static int test(volatile int *buf, int buf_size, int loop_cnt, | ||
156 | char *ramtype, enum test_type type) | ||
157 | { | ||
158 | int delta, dMB; | ||
159 | int last_tick = *rb->current_tick; | ||
160 | int ret = 0; | ||
161 | |||
162 | switch(type) | ||
163 | { | ||
164 | case READ: read_test(buf, buf_size, loop_cnt); break; | ||
165 | case WRITE: write_test(buf, buf_size, loop_cnt); break; | ||
166 | case MEMSET: memset_test(buf, buf_size, loop_cnt); break; | ||
167 | case MEMCPY: memcpy_test(buf, buf_size, loop_cnt); break; | ||
168 | } | ||
169 | |||
167 | delta = *rb->current_tick - last_tick; | 170 | delta = *rb->current_tick - last_tick; |
171 | |||
172 | if (delta <= 10) | ||
173 | { | ||
174 | TEST_MEM_PRINTF("DELTA TOO LOW, RESULT INACCURATE"); | ||
175 | ret = 1; | ||
176 | } | ||
177 | |||
168 | delta = delta>0 ? delta : delta+1; | 178 | delta = delta>0 ? delta : delta+1; |
169 | dMB = dMB_PER_SEC(loop_cnt, delta); | 179 | dMB = dMB_PER_SEC(buf_size, loop_cnt, delta); |
170 | rb->screens[0]->putsf(0, line, "%s rd: %3d.%d MB/s (%3d ticks for %d MB)", | 180 | TEST_MEM_PRINTF("%s %s: %3d.%d MB/s (%3d ticks for %d MB)", |
171 | ramtype, dMB/10, dMB%10, delta, | 181 | ramtype, tests[type], dMB/10, dMB%10, delta, |
172 | (loop_cnt*BUF_SIZE*4)>>20); | 182 | (loop_cnt*buf_size*sizeof(buf[0]))>>20); |
173 | } | ||
174 | 183 | ||
184 | return ret; | ||
185 | } | ||
175 | 186 | ||
176 | enum plugin_status plugin_start(const void* parameter) | 187 | enum plugin_status plugin_start(const void* parameter) |
177 | { | 188 | { |
@@ -185,29 +196,33 @@ enum plugin_status plugin_start(const void* parameter) | |||
185 | #endif | 196 | #endif |
186 | 197 | ||
187 | rb->screens[0]->clear_display(); | 198 | rb->screens[0]->clear_display(); |
188 | rb->screens[0]->putsf(0, 0, "patience, may take some seconds..."); | 199 | TEST_MEM_PRINTF("patience, may take some seconds..."); |
189 | rb->screens[0]->update(); | 200 | rb->screens[0]->update(); |
190 | 201 | ||
191 | while (!done) | 202 | while (!done) |
192 | { | 203 | { |
193 | int line = 0; | 204 | line = 0; |
194 | 205 | int ret; | |
195 | rb->screens[0]->clear_display(); | 206 | rb->screens[0]->clear_display(); |
196 | rb->screens[0]->putsf(0, line++, "%s", boost?"boosted":"unboosted"); | ||
197 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | 207 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) |
198 | rb->screens[0]->putsf(0, line++, "clock: %d Hz", *rb->cpu_frequency); | 208 | TEST_MEM_PRINTF("%s", boost?"boosted":"unboosted"); |
209 | TEST_MEM_PRINTF("clock: %d Hz", *rb->cpu_frequency); | ||
199 | #endif | 210 | #endif |
200 | rb->screens[0]->putsf(0, line++, "loop#: %d", ++count); | 211 | TEST_MEM_PRINTF("loop#: %d", ++count); |
201 | 212 | ||
202 | read_test (buf_dram, BUF_SIZE, LOOP_REPEAT_DRAM, line++, "DRAM"); | 213 | ret = 0; |
203 | write_test (buf_dram, BUF_SIZE, LOOP_REPEAT_DRAM, line++, "DRAM"); | 214 | ret |= test(buf_dram, BUF_SIZE, loop_repeat_dram, "DRAM", READ); |
204 | memset_test(buf_dram, BUF_SIZE, LOOP_REPEAT_DRAM, line++, "DRAM"); | 215 | ret |= test(buf_dram, BUF_SIZE, loop_repeat_dram, "DRAM", WRITE); |
205 | memcpy_test(buf_dram, BUF_SIZE, LOOP_REPEAT_DRAM, line++, "DRAM"); | 216 | ret |= test(buf_dram, BUF_SIZE, loop_repeat_dram, "DRAM", MEMSET); |
217 | ret |= test(buf_dram, BUF_SIZE, loop_repeat_dram, "DRAM", MEMCPY); | ||
218 | if (ret != 0) loop_repeat_dram += LOOP_REPEAT_DRAM; | ||
206 | #if defined(PLUGIN_USE_IRAM) | 219 | #if defined(PLUGIN_USE_IRAM) |
207 | read_test (buf_iram, BUF_SIZE, LOOP_REPEAT_IRAM, line++, "IRAM"); | 220 | ret = 0; |
208 | write_test (buf_iram, BUF_SIZE, LOOP_REPEAT_IRAM, line++, "IRAM"); | 221 | ret |= test(buf_iram, BUF_SIZE, loop_repeat_iram, "IRAM", READ); |
209 | memset_test(buf_iram, BUF_SIZE, LOOP_REPEAT_IRAM, line++, "IRAM"); | 222 | ret |= test(buf_iram, BUF_SIZE, loop_repeat_iram, "IRAM", WRITE); |
210 | memcpy_test(buf_iram, BUF_SIZE, LOOP_REPEAT_DRAM, line++, "IRAM"); | 223 | ret |= test(buf_iram, BUF_SIZE, loop_repeat_iram, "IRAM", MEMSET); |
224 | ret |= test(buf_iram, BUF_SIZE, loop_repeat_iram, "IRAM", MEMCPY); | ||
225 | if (ret != 0) loop_repeat_iram += LOOP_REPEAT_IRAM; | ||
211 | #endif | 226 | #endif |
212 | 227 | ||
213 | rb->screens[0]->update(); | 228 | rb->screens[0]->update(); |