4 * License : GNU GPL v.2
5 * Description : PowerPC timestamping function
6 * Author : Martin Zidek
15 #include <timing_config.h>
17 #define TS_SIZE 4500000
19 #ifdef CONFIG_TIMING_IPOINT_ASM
20 typedef struct timestamp_str {
26 #ifdef CONFIG_TIMING_IPOINT_CLOCK_GETTIME
27 typedef struct timestamp_str {
33 clockid_t clk_id = -1;
34 timestamp_t ts[TS_SIZE];
35 timestamp_t *timestamp_ptr = ts;
36 timestamp_t *timestamp_buff_end = &ts[TS_SIZE];
37 bool timestamp_enabled = true;
40 struct timespec meas_start_ts;
42 void timing_statistics_asm(void);
43 void timing_output_trace_screen(void);
44 void timing_output_trace_file(void);
45 void timing_statistics_clock_gettime(void);
47 timestamp_t * timestamp_handle_overflow(void)
49 static bool first_overflow = true;
50 /* Here we can also implement atomic wrap-around and return
52 timestamp_enabled = false;
54 printf("timestamp overflow\n");
55 first_overflow = false;
61 void timing_ipoint_dummy(unsigned char id)
63 printf("timing: Instrumentation point type not set!\n");
66 #ifdef CONFIG_TIMING_IPOINT_ASM
67 void timing_ipoint_asm(unsigned char id)
69 timestamp_t *p, *pinc;
70 uint32_t tbu, tb, tbu2;
72 /* Store current TB */
80 : "=r" (tbu), "=r" (tb), "=r" (tbu2) /* Outputs */
82 : "cr0" ); /* CR0 changes */
89 : "=&b" (p), "=&b" (pinc), "=m" (timestamp_ptr)
90 : "n" (sizeof(timestamp_t)), "b" (×tamp_ptr)
93 if (p >= timestamp_buff_end) {
94 p = timestamp_handle_overflow();
105 #ifdef CONFIG_TIMING_IPOINT_CLOCK_GETTIME
106 void timing_ipoint_clock_gettime(unsigned char id)
108 timestamp_t *p, *pinc;
112 clock_gettime(clk_id, &(p->ts));
114 // timestamp_ptr = pinc;
115 if (p >= timestamp_buff_end) {
116 p = timestamp_handle_overflow();
127 void timing_init(int init_freq)
129 printf("Timing analysis turned on - initialising\n");
131 /*just for case no ipoint function configured during compile-time*/
132 timing_ipoint = timing_ipoint_dummy;
133 #ifdef CONFIG_TIMING_IPOINT_ASM
134 timing_ipoint = timing_ipoint_asm;
135 timing_statistics = timing_statistics_asm;
137 #ifdef CONFIG_TIMING_IPOINT_CLOCK_GETTIME
138 timing_ipoint = timing_ipoint_clock_gettime;
139 timing_statistics = timing_statistics_clock_gettime;
141 system("mount -t debugfs trace /debug");
142 system("echo sched_switch > /debug/tracing/current_tracer");
145 #ifdef CONFIG_CLOCK_RT
146 clk_id = CLOCK_REALTIME;
148 #ifdef CONFIG_CLOCK_MONOTONIC
149 clk_id = CLOCK_MONOTONIC;
151 #ifdef CONFIG_CLOCK_MONOTONIC_RAW
152 clk_id = CLOCK_MONOTONIC_RAW;
154 #ifdef CONFIG_CLOCK_PROCESS
155 clk_id = CLOCK_PROCESS_CPUTIME_ID;
157 #ifdef CONFIG_CLOCK_THREAD
158 clk_id = CLOCK_THREAD_CPUTIME_ID;
161 printf("timing: Clock source not set during compile time! Unable to perform timestamping!\n");
165 #ifdef CONFIG_TIMING_OUTPUT_SCREEN
166 timing_output_trace = timing_output_trace_screen;
168 #ifdef CONFIG_TIMING_OUTPUT_FILE
169 timing_output_trace = timing_output_trace_file;
171 printf("Timing library initialized!\n");
172 system("dmesg | grep tb_orig_stamp | sed 's#.*tb_orig_stamp\\=\\([0-9]*\\).*#\\1#' | tee tb_orig_stamp");
173 system("echo 1 > /debug/tracing/tracing_enabled");
174 clock_gettime(clk_id, &meas_start_ts);
179 system("echo 0 > /debug/tracing/tracing_enabled");
180 #ifdef CONFIG_TIMING_OUTPUT_FILE
181 system("cat /debug/tracing/trace | tee taskswitch.log");
183 system("echo nop > /debug/tracing/current_tracer");
186 #ifdef CONFIG_TIMING_IPOINT_ASM
187 void print_ts_asm(timestamp_t *ts)
189 printf("%d %llu\n", ts->id, (uint64_t)((uint64_t)ts->tbu << 32 | ts->tbl));
193 void timing_output_trace_screen(void)
195 timestamp_t *ts_iter;
197 printf("Timing analysis application trace\n");
199 if(timestamp_enabled)
200 while(ts_iter != (timestamp_ptr+1))
202 #ifdef CONFIG_TIMING_IPOINT_ASM
203 print_ts_asm(ts_iter);
209 printf("got %d timestamps over limit\n",cnt);
212 double timespec2sec(struct timespec *tspec)
216 result = tspec->tv_sec + (tspec->tv_nsec*0.000000001);
221 void timing_output_trace_file(void)
224 timestamp_t *ts_iter;
227 file = fopen(CONFIG_TIMING_OUTPUT_FILENAME, "w+");
229 perror("timing file open error");
232 fprintf(file, "Timing analysis application trace\n");
234 if(timestamp_enabled)
235 while(ts_iter != (timestamp_ptr+1))
237 #ifdef CONFIG_TIMING_IPOINT_ASM
238 fprintf(file, "%d %llu\n", ts_iter->id,
239 (uint64_t)((uint64_t)ts_iter->tbu << 32 | ts_iter->tbl));
241 #ifdef CONFIG_TIMING_IPOINT_CLOCK_GETTIME
242 fprintf(file, "%d %.6f\n", ts_iter->id, timespec2sec(&ts_iter->ts));
248 fprintf(file, "got %d timestamps over limit\n",cnt);
253 #ifdef CONFIG_TIMING_IPOINT_ASM
254 double sub_timestamps_us(timestamp_t *t1, timestamp_t *t2)
257 uint64_t t1_val, t2_val;
266 result = (double)(t2_val - t1_val)/freq;
272 void timing_statistics_asm(void)
274 timestamp_t *ts_iter;
277 printf("Timing Statistics\n");
278 printf("-----------------\n");
281 if(timestamp_enabled)
282 while(ts_iter != (timestamp_ptr+1))
285 printf("%3.2f\n", sub_timestamps_us(ts_iter-1, ts_iter));
291 printf("got %d timestamps over limit\n",cnt);
295 double sub_ts_us(struct timespec start, struct timespec end)
297 struct timespec temp;
300 if ((end.tv_nsec-start.tv_nsec)<0) {
301 temp.tv_sec = end.tv_sec-start.tv_sec-1;
302 temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
304 temp.tv_sec = end.tv_sec-start.tv_sec;
305 temp.tv_nsec = end.tv_nsec-start.tv_nsec;
308 ret = (temp.tv_sec * 1000000.0) + (temp.tv_nsec/1000.0);
313 #ifdef CONFIG_TIMING_IPOINT_CLOCK_GETTIME
314 void timing_statistics_clock_gettime(void)
316 timestamp_t *ts_iter;
319 printf("Highrest_Statistics\n");
322 if(timestamp_enabled)
323 while(ts_iter != (timestamp_ptr+1))
326 printf("%3.2f\n", sub_ts_us((ts_iter-1)->ts,(ts_iter)->ts));
332 printf("got %d timestamps over limit\n",cnt);