1 /* This file is part of the program psim.
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
45 #ifdef HAVE_SYS_TYPES_H
46 #include <sys/types.h>
53 #ifdef HAVE_SYS_TIMES_H
54 #include <sys/times.h>
57 #ifdef HAVE_SYS_TIME_H
61 #ifdef HAVE_SYS_RESOURCE_H
62 #include <sys/resource.h>
66 #define MAX_BYTE_READWRITE 9
67 #define MAX_SHIFT_READWRITE 3
70 count_type issue_count
[nr_itable_entries
];
71 count_type read_count
;
72 count_type read_byte_count
[MAX_BYTE_READWRITE
];
73 count_type write_count
;
74 count_type write_byte_count
[MAX_BYTE_READWRITE
];
75 count_type unaligned_read_count
;
76 count_type unaligned_write_count
;
77 count_type event_count
[nr_mon_events
];
82 cpu_mon cpu_monitor
[MAX_NR_PROCESSORS
];
90 mon
*monitor
= ZALLOC(mon
);
100 if (cpu_nr
< 0 || cpu_nr
>= MAX_NR_PROCESSORS
)
101 error("mon_cpu() - invalid cpu number\n");
102 return &monitor
->cpu_monitor
[cpu_nr
];
108 mon_init(mon
*monitor
,
111 memset(monitor
, 0, sizeof(*monitor
));
112 monitor
->nr_cpus
= nr_cpus
;
118 mon_issue(itable_index index
,
122 cpu_mon
*monitor
= cpu_monitor(processor
);
123 ASSERT(index
<= nr_itable_entries
);
124 monitor
->issue_count
[index
] += 1;
130 mon_read(unsigned_word ea
,
136 cpu_mon
*monitor
= cpu_monitor(processor
);
137 monitor
->read_count
+= 1;
138 monitor
->read_byte_count
[nr_bytes
] += 1;
139 if ((nr_bytes
- 1) & ea
)
140 monitor
->unaligned_read_count
+= 1;
146 mon_write(unsigned_word ea
,
152 cpu_mon
*monitor
= cpu_monitor(processor
);
153 monitor
->write_count
+= 1;
154 monitor
->write_byte_count
[nr_bytes
] += 1;
155 if ((nr_bytes
- 1) & ea
)
156 monitor
->unaligned_write_count
+= 1;
161 mon_event(mon_events event
,
165 cpu_mon
*monitor
= cpu_monitor(processor
);
166 ASSERT(event
< nr_mon_events
);
167 monitor
->event_count
[event
] += 1;
172 mon_get_number_of_insns(mon
*monitor
,
176 unsigned total_insns
= 0;
177 ASSERT(cpu_nr
>= 0 && cpu_nr
< monitor
->nr_cpus
);
178 for (index
= 0; index
< nr_itable_entries
; index
++)
179 total_insns
+= monitor
->cpu_monitor
[cpu_nr
].issue_count
[index
];
185 mon_sort_instruction_names(const void *ptr_a
, const void *ptr_b
)
187 itable_index a
= *(const itable_index
*)ptr_a
;
188 itable_index b
= *(const itable_index
*)ptr_b
;
190 return strcmp (itable
[a
].name
, itable
[b
].name
);
195 mon_add_commas(char *buf
,
200 char *endbuf
= buf
+ sizeof_buf
- 1;
210 *--endbuf
= (value
% 10) + '0';
211 } while ((value
/= 10) != 0);
213 ASSERT(endbuf
>= buf
);
220 mon_print_info(psim
*system
,
232 int len_sub_num
[MAX_BYTE_READWRITE
];
235 long total_insns
= 0;
236 long cpu_insns_second
= 0;
237 long total_sim_cycles
= 0;
238 long sim_cycles_second
= 0;
239 double cpu_time
= 0.0;
241 for (i
= 0; i
< MAX_BYTE_READWRITE
; i
++)
244 for (cpu_nr
= 0; cpu_nr
< monitor
->nr_cpus
; cpu_nr
++) {
245 count_type num_insns
= mon_get_number_of_insns(monitor
, cpu_nr
);
247 total_insns
+= num_insns
;
248 len
= strlen (mon_add_commas(buffer
, sizeof(buffer
), num_insns
));
252 for (i
= 0; i
<= MAX_SHIFT_READWRITE
; i
++) {
254 len
= strlen (mon_add_commas(buffer
, sizeof(buffer
),
255 monitor
->cpu_monitor
[cpu_nr
].read_byte_count
[size
]));
256 if (len_sub_num
[size
] < len
)
257 len_sub_num
[size
] = len
;
259 len
= strlen (mon_add_commas(buffer
, sizeof(buffer
),
260 monitor
->cpu_monitor
[cpu_nr
].write_byte_count
[size
]));
261 if (len_sub_num
[size
] < len
)
262 len_sub_num
[size
] = len
;
266 sprintf (buffer
, "%d", (int)monitor
->nr_cpus
+ 1);
267 len_cpu
= strlen (buffer
);
269 #ifdef HAVE_GETRUSAGE
271 struct rusage mytime
;
272 if (getrusage (RUSAGE_SELF
, &mytime
) == 0
273 && (mytime
.ru_utime
.tv_sec
> 0 || mytime
.ru_utime
.tv_usec
> 0)) {
275 cpu_time
= (double)mytime
.ru_utime
.tv_sec
+ (((double)mytime
.ru_utime
.tv_usec
) / 1000000.0);
279 total_sim_cycles
= event_queue_time(psim_event_queue(system
)) - 1;
282 cpu_insns_second
= (long)(((double)total_insns
/ cpu_time
) + 0.5);
283 if (total_sim_cycles
) {
284 sim_cycles_second
= (long)(((double)total_sim_cycles
/ cpu_time
) + 0.5);
289 for (cpu_nr
= 0; cpu_nr
< monitor
->nr_cpus
; cpu_nr
++) {
292 itable_index sort_insns
[nr_itable_entries
];
293 int nr_sort_insns
= 0;
298 printf_filtered ("\n");
300 for (index
= 0; index
< nr_itable_entries
; index
++) {
301 if (monitor
->cpu_monitor
[cpu_nr
].issue_count
[index
]) {
302 sort_insns
[nr_sort_insns
++] = index
;
306 qsort((void *)sort_insns
, nr_sort_insns
, sizeof(sort_insns
[0]), mon_sort_instruction_names
);
308 for (index2
= 0; index2
< nr_sort_insns
; index2
++) {
309 index
= sort_insns
[index2
];
310 printf_filtered("CPU #%*d executed %*s %s instruction%s.\n",
312 len_num
, mon_add_commas(buffer
,
314 monitor
->cpu_monitor
[cpu_nr
].issue_count
[index
]),
316 (monitor
->cpu_monitor
[cpu_nr
].issue_count
[index
] == 1) ? "" : "s");
319 printf_filtered ("\n");
322 if (CURRENT_MODEL_ISSUE
> 0)
324 model_data
*model_ptr
= cpu_model(psim_cpu(system
, cpu_nr
));
325 model_print
*ptr
= model_mon_info(model_ptr
);
326 model_print
*orig_ptr
= ptr
;
330 printf_filtered("CPU #%*d executed %*s %s%s.\n",
332 len_num
, mon_add_commas(buffer
,
337 ? ptr
->suffix_singular
338 : ptr
->suffix_plural
));
343 model_mon_info_free(model_ptr
, orig_ptr
);
346 if (monitor
->cpu_monitor
[cpu_nr
].read_count
)
347 printf_filtered ("CPU #%*d executed %*s read%s (%*s 1-byte, %*s 2-byte, %*s 4-byte, %*s 8-byte).\n",
349 len_num
, mon_add_commas(buffer
,
351 monitor
->cpu_monitor
[cpu_nr
].read_count
),
352 (monitor
->cpu_monitor
[cpu_nr
].read_count
== 1) ? "" : "s",
353 len_sub_num
[1], mon_add_commas(buffer1
,
355 monitor
->cpu_monitor
[cpu_nr
].read_byte_count
[1]),
356 len_sub_num
[2], mon_add_commas(buffer2
,
358 monitor
->cpu_monitor
[cpu_nr
].read_byte_count
[2]),
359 len_sub_num
[4], mon_add_commas(buffer4
,
361 monitor
->cpu_monitor
[cpu_nr
].read_byte_count
[4]),
362 len_sub_num
[8], mon_add_commas(buffer8
,
364 monitor
->cpu_monitor
[cpu_nr
].read_byte_count
[8]));
366 if (monitor
->cpu_monitor
[cpu_nr
].write_count
)
367 printf_filtered ("CPU #%*d executed %*s write%s (%*s 1-byte, %*s 2-byte, %*s 4-byte, %*s 8-byte).\n",
369 len_num
, mon_add_commas(buffer
,
371 monitor
->cpu_monitor
[cpu_nr
].write_count
),
372 (monitor
->cpu_monitor
[cpu_nr
].write_count
== 1) ? "" : "s",
373 len_sub_num
[1], mon_add_commas(buffer1
,
375 monitor
->cpu_monitor
[cpu_nr
].write_byte_count
[1]),
376 len_sub_num
[2], mon_add_commas(buffer2
,
378 monitor
->cpu_monitor
[cpu_nr
].write_byte_count
[2]),
379 len_sub_num
[4], mon_add_commas(buffer4
,
381 monitor
->cpu_monitor
[cpu_nr
].write_byte_count
[4]),
382 len_sub_num
[8], mon_add_commas(buffer8
,
384 monitor
->cpu_monitor
[cpu_nr
].write_byte_count
[8]));
386 if (monitor
->cpu_monitor
[cpu_nr
].unaligned_read_count
)
387 printf_filtered ("CPU #%*d executed %*s unaligned read%s.\n",
389 len_num
, mon_add_commas(buffer
,
391 monitor
->cpu_monitor
[cpu_nr
].unaligned_read_count
),
392 (monitor
->cpu_monitor
[cpu_nr
].unaligned_read_count
== 1) ? "" : "s");
394 if (monitor
->cpu_monitor
[cpu_nr
].unaligned_write_count
)
395 printf_filtered ("CPU #%*d executed %*s unaligned write%s.\n",
397 len_num
, mon_add_commas(buffer
,
399 monitor
->cpu_monitor
[cpu_nr
].unaligned_write_count
),
400 (monitor
->cpu_monitor
[cpu_nr
].unaligned_write_count
== 1) ? "" : "s");
402 if (monitor
->cpu_monitor
[cpu_nr
].event_count
[mon_event_icache_miss
])
403 printf_filtered ("CPU #%*d executed %*s icache miss%s.\n",
405 len_num
, mon_add_commas(buffer
,
407 monitor
->cpu_monitor
[cpu_nr
].event_count
[mon_event_icache_miss
]),
408 (monitor
->cpu_monitor
[cpu_nr
].event_count
[mon_event_icache_miss
] == 1) ? "" : "es");
411 long nr_insns
= mon_get_number_of_insns(monitor
, cpu_nr
);
413 printf_filtered("CPU #%*d executed %*s instructions in total.\n",
415 len_num
, mon_add_commas(buffer
,
421 if (total_insns
> 0) {
422 if (monitor
->nr_cpus
> 1)
423 printf_filtered("\nAll CPUs executed %s instructions in total.\n",
424 mon_add_commas(buffer
, sizeof(buffer
), total_insns
));
426 else if (total_sim_cycles
> 0) {
427 printf_filtered("\nSimulator performed %s simulation cycles.\n",
428 mon_add_commas(buffer
, sizeof(buffer
), total_sim_cycles
));
431 if (cpu_insns_second
)
432 printf_filtered ("%sSimulator speed was %s instructions/second.\n",
433 (monitor
->nr_cpus
> 1) ? "" : "\n",
434 mon_add_commas(buffer
, sizeof(buffer
), cpu_insns_second
));
435 else if (sim_cycles_second
)
436 printf_filtered ("Simulator speed was %s simulation cycles/second\n",
437 mon_add_commas(buffer
, sizeof(buffer
), sim_cycles_second
));
438 else if (cpu_time
> 0.0)
439 printf_filtered ("%sSimulator executed for %.2f seconds\n",
440 (monitor
->nr_cpus
> 1) ? "" : "\n", cpu_time
);