1 | /* |
---|
2 | File : core_portme.c |
---|
3 | */ |
---|
4 | /* |
---|
5 | Author : Shay Gal-On, EEMBC |
---|
6 | Legal : TODO! |
---|
7 | */ |
---|
8 | #include "coremark.h" |
---|
9 | |
---|
10 | #include <stdlib.h> |
---|
11 | #include <malloc.h> |
---|
12 | |
---|
13 | #if VALIDATION_RUN |
---|
14 | volatile ee_s32 seed1_volatile=0x3415; |
---|
15 | volatile ee_s32 seed2_volatile=0x3415; |
---|
16 | volatile ee_s32 seed3_volatile=0x66; |
---|
17 | #endif |
---|
18 | |
---|
19 | #if PERFORMANCE_RUN |
---|
20 | volatile ee_s32 seed1_volatile=0x0; |
---|
21 | volatile ee_s32 seed2_volatile=0x0; |
---|
22 | volatile ee_s32 seed3_volatile=0x66; |
---|
23 | #endif |
---|
24 | |
---|
25 | #if PROFILE_RUN |
---|
26 | volatile ee_s32 seed1_volatile=0x8; |
---|
27 | volatile ee_s32 seed2_volatile=0x8; |
---|
28 | volatile ee_s32 seed3_volatile=0x8; |
---|
29 | #endif |
---|
30 | |
---|
31 | /* Define : seed4_volatile |
---|
32 | It defines the number of iterations. |
---|
33 | |
---|
34 | When set to 0, the number of iterations is automatically computed |
---|
35 | during the benchmark's execution |
---|
36 | */ |
---|
37 | volatile ee_s32 seed4_volatile=ITERATIONS; |
---|
38 | |
---|
39 | |
---|
40 | /* Define : seed5_volatile |
---|
41 | It defines which algorithms are executed |
---|
42 | |
---|
43 | When set to 0, all algorithms are executed (matrix, list_join, state) |
---|
44 | */ |
---|
45 | volatile ee_s32 seed5_volatile=0; |
---|
46 | |
---|
47 | |
---|
48 | /* Porting : Timing functions |
---|
49 | How to capture time and convert to seconds must be ported to whatever is supported by the platform. |
---|
50 | |
---|
51 | Define : TIMER_RES_DIVIDER |
---|
52 | Divider to trade off timer resolution and total time that can be measured. |
---|
53 | |
---|
54 | Use lower values to increase resolution, but make sure that overflow does not occur. |
---|
55 | If there are issues with the return value overflowing, increase this value. |
---|
56 | */ |
---|
57 | #define TIMER_RES_DIVIDER 1 |
---|
58 | #define NSECS_PER_SEC 833000000 /* 833 MHz */ |
---|
59 | #define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER) |
---|
60 | #define GETMYTIME(_t) (*_t=giet_proctime()) |
---|
61 | |
---|
62 | |
---|
63 | /* global time variables.*/ |
---|
64 | static CORE_TICKS start_time_val, stop_time_val; |
---|
65 | |
---|
66 | |
---|
67 | /* Function : start_time |
---|
68 | This function will be called right before starting the timed portion of the benchmark. |
---|
69 | |
---|
70 | Implementation may be capturing a system timer (as implemented in the example code) |
---|
71 | or zeroing some system parameters - e.g. setting the cpu clocks cycles to 0. |
---|
72 | */ |
---|
73 | void start_time(void) { |
---|
74 | GETMYTIME(&start_time_val ); |
---|
75 | } |
---|
76 | |
---|
77 | |
---|
78 | /* Function : stop_time |
---|
79 | This function will be called right after ending the timed portion of the benchmark. |
---|
80 | |
---|
81 | Implementation may be capturing a system timer (as implemented in the example code) |
---|
82 | or other system parameters - e.g. reading the current value of cpu cycles counter. |
---|
83 | */ |
---|
84 | void stop_time(void) { |
---|
85 | GETMYTIME(&stop_time_val ); |
---|
86 | } |
---|
87 | |
---|
88 | |
---|
89 | /* Function : get_time |
---|
90 | Return an abstract "ticks" number that signifies time on the system. |
---|
91 | |
---|
92 | Actual value returned may be cpu cycles, milliseconds or any other value, |
---|
93 | as long as it can be converted to seconds by <time_in_secs>. |
---|
94 | This methodology is taken to accomodate any hardware or simulated platform. |
---|
95 | The sample implementation returns millisecs by default, |
---|
96 | and the resolution is controlled by <TIMER_RES_DIVIDER> |
---|
97 | */ |
---|
98 | CORE_TICKS get_time(void) { |
---|
99 | CORE_TICKS elapsed=(CORE_TICKS)(stop_time_val - start_time_val); |
---|
100 | return elapsed; |
---|
101 | } |
---|
102 | |
---|
103 | |
---|
104 | /* Function : time_in_secs |
---|
105 | Convert the value returned by get_time to seconds. |
---|
106 | |
---|
107 | The <secs_ret> type is used to accomodate systems with no support for floating point. |
---|
108 | Default implementation implemented by the EE_TICKS_PER_SEC macro above. |
---|
109 | */ |
---|
110 | secs_ret time_in_secs(CORE_TICKS ticks) { |
---|
111 | secs_ret retval=((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; |
---|
112 | return retval; |
---|
113 | } |
---|
114 | |
---|
115 | ee_u32 default_num_contexts=MULTITHREAD; |
---|
116 | |
---|
117 | |
---|
118 | /* Function : portable_init |
---|
119 | Target specific initialization code |
---|
120 | Test for some common mistakes. |
---|
121 | */ |
---|
122 | void portable_init(core_portable *p, int *argc, char *argv[]) |
---|
123 | { |
---|
124 | if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) { |
---|
125 | ee_printf("ERROR! Please define ee_ptr_int to a type that holds a pointer!\n"); |
---|
126 | } |
---|
127 | if (sizeof(ee_u32) != 4) { |
---|
128 | ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); |
---|
129 | } |
---|
130 | |
---|
131 | // allocate a shared TTY |
---|
132 | giet_tty_alloc(1); |
---|
133 | |
---|
134 | #if MULTITHREAD>1 |
---|
135 | unsigned int x_size, y_size, nprocs; |
---|
136 | giet_procs_number( &x_size, &y_size, &nprocs ); |
---|
137 | |
---|
138 | // initialize distributed heaps |
---|
139 | int x, y; |
---|
140 | for (x=0; x < x_size; ++x) { |
---|
141 | for (y=0; y < y_size; ++y) { |
---|
142 | heap_init(x, y); |
---|
143 | } |
---|
144 | } |
---|
145 | #else |
---|
146 | // initialize local heap |
---|
147 | unsigned int lx, ly, lp; |
---|
148 | giet_proc_xyp(&lx, &ly, &lp); |
---|
149 | heap_init(lx, ly); |
---|
150 | #endif |
---|
151 | |
---|
152 | p->portable_id=1; |
---|
153 | } |
---|
154 | |
---|
155 | |
---|
156 | /* Function : portable_fini |
---|
157 | Target specific final code |
---|
158 | */ |
---|
159 | void portable_fini(core_portable *p) |
---|
160 | { |
---|
161 | core_results *res = (core_results*)((char*)p - |
---|
162 | (sizeof(core_results) - sizeof(core_portable))); |
---|
163 | |
---|
164 | int i; |
---|
165 | for (i=0 ; i<default_num_contexts; i++) { |
---|
166 | const CORE_TICKS total_time = res[i].port.stop_time - res[i].port.start_time; |
---|
167 | printf("thread %d: total ticks = %d\n", i, total_time); |
---|
168 | } |
---|
169 | |
---|
170 | p->portable_id=0; |
---|
171 | } |
---|
172 | |
---|
173 | |
---|
174 | /* Function : __iterate |
---|
175 | Target specific wrapper for the iterate function, which allows to add |
---|
176 | the iterate function in the constructor list |
---|
177 | |
---|
178 | This is the entry function for the secondary threads |
---|
179 | */ |
---|
180 | __attribute__ ((constructor)) |
---|
181 | void *__iterate(void *pres) { |
---|
182 | core_results *res = (core_results*)pres; |
---|
183 | GETMYTIME(&(res->port.start_time)); |
---|
184 | iterate(pres); |
---|
185 | GETMYTIME(&(res->port.stop_time)); |
---|
186 | giet_pthread_exit(NULL); |
---|
187 | return NULL; |
---|
188 | } |
---|
189 | |
---|
190 | |
---|
191 | /* Function : __main |
---|
192 | Target specific wrapper for the main function, which allows to add |
---|
193 | the main function in the constructor list. |
---|
194 | |
---|
195 | This is the entry function for the main thread |
---|
196 | */ |
---|
197 | extern MAIN_RETURN_TYPE main(void); |
---|
198 | __attribute__ ((constructor)) |
---|
199 | void __main() { |
---|
200 | main(); |
---|
201 | giet_pthread_exit("Coremark execution completed"); |
---|
202 | } |
---|
203 | |
---|
204 | |
---|
205 | /* Function: portable_malloc |
---|
206 | Provide malloc() functionality in a platform specific way. |
---|
207 | */ |
---|
208 | void *portable_malloc(ee_size_t size) { |
---|
209 | return malloc(size); |
---|
210 | } |
---|
211 | |
---|
212 | |
---|
213 | /* Function: portable_free |
---|
214 | Provide free() functionality in a platform specific way. |
---|
215 | */ |
---|
216 | void portable_free(void *p) { |
---|
217 | free(p); |
---|
218 | } |
---|
219 | |
---|
220 | |
---|
221 | /* Function: core_start_parallel |
---|
222 | Start benchmarking in a parallel context. |
---|
223 | */ |
---|
224 | ee_u8 core_start_parallel(core_results *res) { |
---|
225 | return (ee_u8)giet_pthread_create(&(res->port.thread),NULL,__iterate,(void*)res); |
---|
226 | } |
---|
227 | |
---|
228 | |
---|
229 | /* Function: core_stop_parallel |
---|
230 | Stop a parallel context execution of coremark, and gather the results. |
---|
231 | */ |
---|
232 | ee_u8 core_stop_parallel(core_results *res) { |
---|
233 | return (ee_u8)giet_pthread_join(res->port.thread, NULL); |
---|
234 | } |
---|