mon.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /* This file is part of the program psim.
  2. Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #ifndef _MON_C_
  15. #define _MON_C_
  16. #include "defs.h"
  17. #include <stdio.h>
  18. #include <string.h>
  19. #ifdef HAVE_UNISTD_H
  20. #include <unistd.h>
  21. #endif
  22. #include <stdlib.h>
  23. #ifdef HAVE_SYS_TYPES_H
  24. #include <sys/types.h>
  25. #endif
  26. #include <time.h>
  27. #include <sys/time.h>
  28. #ifdef HAVE_SYS_RESOURCE_H
  29. #include <sys/resource.h>
  30. int getrusage();
  31. #endif
  32. #include "basics.h"
  33. #include "cpu.h"
  34. #include "mon.h"
  35. #define MAX_BYTE_READWRITE 9
  36. #define MAX_SHIFT_READWRITE 3
  37. struct _cpu_mon {
  38. count_type issue_count[nr_itable_entries];
  39. count_type read_count;
  40. count_type read_byte_count[MAX_BYTE_READWRITE];
  41. count_type write_count;
  42. count_type write_byte_count[MAX_BYTE_READWRITE];
  43. count_type unaligned_read_count;
  44. count_type unaligned_write_count;
  45. count_type event_count[nr_mon_events];
  46. };
  47. struct _mon {
  48. int nr_cpus;
  49. cpu_mon cpu_monitor[MAX_NR_PROCESSORS];
  50. };
  51. INLINE_MON\
  52. (mon *)
  53. mon_create(void)
  54. {
  55. mon *monitor = ZALLOC(mon);
  56. return monitor;
  57. }
  58. INLINE_MON\
  59. (cpu_mon *)
  60. mon_cpu(mon *monitor,
  61. int cpu_nr)
  62. {
  63. if (cpu_nr < 0 || cpu_nr >= MAX_NR_PROCESSORS)
  64. error("mon_cpu() - invalid cpu number\n");
  65. return &monitor->cpu_monitor[cpu_nr];
  66. }
  67. INLINE_MON\
  68. (void)
  69. mon_init(mon *monitor,
  70. int nr_cpus)
  71. {
  72. memset(monitor, 0, sizeof(*monitor));
  73. monitor->nr_cpus = nr_cpus;
  74. }
  75. INLINE_MON\
  76. (void)
  77. mon_issue(itable_index index,
  78. cpu *processor,
  79. unsigned_word cia)
  80. {
  81. cpu_mon *monitor = cpu_monitor(processor);
  82. ASSERT(index <= nr_itable_entries);
  83. monitor->issue_count[index] += 1;
  84. }
  85. INLINE_MON\
  86. (void)
  87. mon_read(unsigned_word ea,
  88. unsigned_word ra,
  89. unsigned nr_bytes,
  90. cpu *processor,
  91. unsigned_word cia)
  92. {
  93. cpu_mon *monitor = cpu_monitor(processor);
  94. monitor->read_count += 1;
  95. monitor->read_byte_count[nr_bytes] += 1;
  96. if ((nr_bytes - 1) & ea)
  97. monitor->unaligned_read_count += 1;
  98. }
  99. INLINE_MON\
  100. (void)
  101. mon_write(unsigned_word ea,
  102. unsigned_word ra,
  103. unsigned nr_bytes,
  104. cpu *processor,
  105. unsigned_word cia)
  106. {
  107. cpu_mon *monitor = cpu_monitor(processor);
  108. monitor->write_count += 1;
  109. monitor->write_byte_count[nr_bytes] += 1;
  110. if ((nr_bytes - 1) & ea)
  111. monitor->unaligned_write_count += 1;
  112. }
  113. INLINE_MON\
  114. (void)
  115. mon_event(mon_events event,
  116. cpu *processor,
  117. unsigned_word cia)
  118. {
  119. cpu_mon *monitor = cpu_monitor(processor);
  120. ASSERT(event < nr_mon_events);
  121. monitor->event_count[event] += 1;
  122. }
  123. INLINE_MON\
  124. (unsigned)
  125. mon_get_number_of_insns(mon *monitor,
  126. int cpu_nr)
  127. {
  128. itable_index index;
  129. unsigned total_insns = 0;
  130. ASSERT(cpu_nr >= 0 && cpu_nr < monitor->nr_cpus);
  131. for (index = 0; index < nr_itable_entries; index++)
  132. total_insns += monitor->cpu_monitor[cpu_nr].issue_count[index];
  133. return total_insns;
  134. }
  135. STATIC_INLINE_MON\
  136. (int)
  137. mon_sort_instruction_names(const void *ptr_a, const void *ptr_b)
  138. {
  139. itable_index a = *(const itable_index *)ptr_a;
  140. itable_index b = *(const itable_index *)ptr_b;
  141. return strcmp (itable[a].name, itable[b].name);
  142. }
  143. STATIC_INLINE_MON\
  144. (char *)
  145. mon_add_commas(char *buf,
  146. int sizeof_buf,
  147. count_type value)
  148. {
  149. int comma = 3;
  150. char *endbuf = buf + sizeof_buf - 1;
  151. *--endbuf = '\0';
  152. do {
  153. if (comma-- == 0)
  154. {
  155. *--endbuf = ',';
  156. comma = 2;
  157. }
  158. *--endbuf = (value % 10) + '0';
  159. } while ((value /= 10) != 0);
  160. ASSERT(endbuf >= buf);
  161. return endbuf;
  162. }
  163. INLINE_MON\
  164. (void)
  165. mon_print_info(psim *system,
  166. mon *monitor,
  167. int verbose)
  168. {
  169. char buffer[20];
  170. char buffer1[20];
  171. char buffer2[20];
  172. char buffer4[20];
  173. char buffer8[20];
  174. int cpu_nr;
  175. int len_cpu;
  176. int len_num = 0;
  177. int len_sub_num[MAX_BYTE_READWRITE];
  178. int len;
  179. int i;
  180. long total_insns = 0;
  181. long cpu_insns_second = 0;
  182. long total_sim_cycles = 0;
  183. long sim_cycles_second = 0;
  184. double cpu_time = 0.0;
  185. for (i = 0; i < MAX_BYTE_READWRITE; i++)
  186. len_sub_num[i] = 0;
  187. for (cpu_nr = 0; cpu_nr < monitor->nr_cpus; cpu_nr++) {
  188. count_type num_insns = mon_get_number_of_insns(monitor, cpu_nr);
  189. total_insns += num_insns;
  190. len = strlen (mon_add_commas(buffer, sizeof(buffer), num_insns));
  191. if (len_num < len)
  192. len_num = len;
  193. for (i = 0; i <= MAX_SHIFT_READWRITE; i++) {
  194. int size = 1<<i;
  195. len = strlen (mon_add_commas(buffer, sizeof(buffer),
  196. monitor->cpu_monitor[cpu_nr].read_byte_count[size]));
  197. if (len_sub_num[size] < len)
  198. len_sub_num[size] = len;
  199. len = strlen (mon_add_commas(buffer, sizeof(buffer),
  200. monitor->cpu_monitor[cpu_nr].write_byte_count[size]));
  201. if (len_sub_num[size] < len)
  202. len_sub_num[size] = len;
  203. }
  204. }
  205. sprintf (buffer, "%d", (int)monitor->nr_cpus + 1);
  206. len_cpu = strlen (buffer);
  207. #ifdef HAVE_GETRUSAGE
  208. {
  209. struct rusage mytime;
  210. if (getrusage (RUSAGE_SELF, &mytime) == 0
  211. && (mytime.ru_utime.tv_sec > 0 || mytime.ru_utime.tv_usec > 0)) {
  212. cpu_time = (double)mytime.ru_utime.tv_sec + (((double)mytime.ru_utime.tv_usec) / 1000000.0);
  213. }
  214. }
  215. if (WITH_EVENTS)
  216. total_sim_cycles = event_queue_time(psim_event_queue(system)) - 1;
  217. if (cpu_time > 0) {
  218. if (total_insns > 0)
  219. cpu_insns_second = (long)(((double)total_insns / cpu_time) + 0.5);
  220. if (total_sim_cycles) {
  221. sim_cycles_second = (long)(((double)total_sim_cycles / cpu_time) + 0.5);
  222. }
  223. }
  224. #endif
  225. for (cpu_nr = 0; cpu_nr < monitor->nr_cpus; cpu_nr++) {
  226. if (verbose > 1) {
  227. itable_index sort_insns[nr_itable_entries];
  228. int nr_sort_insns = 0;
  229. itable_index index;
  230. int index2;
  231. if (cpu_nr)
  232. printf_filtered ("\n");
  233. for (index = 0; index < nr_itable_entries; index++) {
  234. if (monitor->cpu_monitor[cpu_nr].issue_count[index]) {
  235. sort_insns[nr_sort_insns++] = index;
  236. }
  237. }
  238. qsort((void *)sort_insns, nr_sort_insns, sizeof(sort_insns[0]), mon_sort_instruction_names);
  239. for (index2 = 0; index2 < nr_sort_insns; index2++) {
  240. index = sort_insns[index2];
  241. printf_filtered("CPU #%*d executed %*s %s instruction%s.\n",
  242. len_cpu, cpu_nr+1,
  243. len_num, mon_add_commas(buffer,
  244. sizeof(buffer),
  245. monitor->cpu_monitor[cpu_nr].issue_count[index]),
  246. itable[index].name,
  247. (monitor->cpu_monitor[cpu_nr].issue_count[index] == 1) ? "" : "s");
  248. }
  249. printf_filtered ("\n");
  250. }
  251. if (CURRENT_MODEL_ISSUE > 0)
  252. {
  253. model_data *model_ptr = cpu_model(psim_cpu(system, cpu_nr));
  254. model_print *ptr = model_mon_info(model_ptr);
  255. model_print *orig_ptr = ptr;
  256. while (ptr) {
  257. if (ptr->count)
  258. printf_filtered("CPU #%*d executed %*s %s%s.\n",
  259. len_cpu, cpu_nr+1,
  260. len_num, mon_add_commas(buffer,
  261. sizeof(buffer),
  262. ptr->count),
  263. ptr->name,
  264. ((ptr->count == 1)
  265. ? ptr->suffix_singular
  266. : ptr->suffix_plural));
  267. ptr = ptr->next;
  268. }
  269. model_mon_info_free(model_ptr, orig_ptr);
  270. }
  271. if (monitor->cpu_monitor[cpu_nr].read_count)
  272. printf_filtered ("CPU #%*d executed %*s read%s (%*s 1-byte, %*s 2-byte, %*s 4-byte, %*s 8-byte).\n",
  273. len_cpu, cpu_nr+1,
  274. len_num, mon_add_commas(buffer,
  275. sizeof(buffer),
  276. monitor->cpu_monitor[cpu_nr].read_count),
  277. (monitor->cpu_monitor[cpu_nr].read_count == 1) ? "" : "s",
  278. len_sub_num[1], mon_add_commas(buffer1,
  279. sizeof(buffer1),
  280. monitor->cpu_monitor[cpu_nr].read_byte_count[1]),
  281. len_sub_num[2], mon_add_commas(buffer2,
  282. sizeof(buffer2),
  283. monitor->cpu_monitor[cpu_nr].read_byte_count[2]),
  284. len_sub_num[4], mon_add_commas(buffer4,
  285. sizeof(buffer4),
  286. monitor->cpu_monitor[cpu_nr].read_byte_count[4]),
  287. len_sub_num[8], mon_add_commas(buffer8,
  288. sizeof(buffer8),
  289. monitor->cpu_monitor[cpu_nr].read_byte_count[8]));
  290. if (monitor->cpu_monitor[cpu_nr].write_count)
  291. printf_filtered ("CPU #%*d executed %*s write%s (%*s 1-byte, %*s 2-byte, %*s 4-byte, %*s 8-byte).\n",
  292. len_cpu, cpu_nr+1,
  293. len_num, mon_add_commas(buffer,
  294. sizeof(buffer),
  295. monitor->cpu_monitor[cpu_nr].write_count),
  296. (monitor->cpu_monitor[cpu_nr].write_count == 1) ? "" : "s",
  297. len_sub_num[1], mon_add_commas(buffer1,
  298. sizeof(buffer1),
  299. monitor->cpu_monitor[cpu_nr].write_byte_count[1]),
  300. len_sub_num[2], mon_add_commas(buffer2,
  301. sizeof(buffer2),
  302. monitor->cpu_monitor[cpu_nr].write_byte_count[2]),
  303. len_sub_num[4], mon_add_commas(buffer4,
  304. sizeof(buffer4),
  305. monitor->cpu_monitor[cpu_nr].write_byte_count[4]),
  306. len_sub_num[8], mon_add_commas(buffer8,
  307. sizeof(buffer8),
  308. monitor->cpu_monitor[cpu_nr].write_byte_count[8]));
  309. if (monitor->cpu_monitor[cpu_nr].unaligned_read_count)
  310. printf_filtered ("CPU #%*d executed %*s unaligned read%s.\n",
  311. len_cpu, cpu_nr+1,
  312. len_num, mon_add_commas(buffer,
  313. sizeof(buffer),
  314. monitor->cpu_monitor[cpu_nr].unaligned_read_count),
  315. (monitor->cpu_monitor[cpu_nr].unaligned_read_count == 1) ? "" : "s");
  316. if (monitor->cpu_monitor[cpu_nr].unaligned_write_count)
  317. printf_filtered ("CPU #%*d executed %*s unaligned write%s.\n",
  318. len_cpu, cpu_nr+1,
  319. len_num, mon_add_commas(buffer,
  320. sizeof(buffer),
  321. monitor->cpu_monitor[cpu_nr].unaligned_write_count),
  322. (monitor->cpu_monitor[cpu_nr].unaligned_write_count == 1) ? "" : "s");
  323. if (monitor->cpu_monitor[cpu_nr].event_count[mon_event_icache_miss])
  324. printf_filtered ("CPU #%*d executed %*s icache miss%s.\n",
  325. len_cpu, cpu_nr+1,
  326. len_num, mon_add_commas(buffer,
  327. sizeof(buffer),
  328. monitor->cpu_monitor[cpu_nr].event_count[mon_event_icache_miss]),
  329. (monitor->cpu_monitor[cpu_nr].event_count[mon_event_icache_miss] == 1) ? "" : "es");
  330. {
  331. long nr_insns = mon_get_number_of_insns(monitor, cpu_nr);
  332. if (nr_insns > 0)
  333. printf_filtered("CPU #%*d executed %*s instructions in total.\n",
  334. len_cpu, cpu_nr+1,
  335. len_num, mon_add_commas(buffer,
  336. sizeof(buffer),
  337. nr_insns));
  338. }
  339. }
  340. if (total_insns > 0) {
  341. if (monitor->nr_cpus > 1)
  342. printf_filtered("\nAll CPUs executed %s instructions in total.\n",
  343. mon_add_commas(buffer, sizeof(buffer), total_insns));
  344. }
  345. else if (total_sim_cycles > 0) {
  346. printf_filtered("\nSimulator performed %s simulation cycles.\n",
  347. mon_add_commas(buffer, sizeof(buffer), total_sim_cycles));
  348. }
  349. if (cpu_insns_second)
  350. printf_filtered ("%sSimulator speed was %s instructions/second.\n",
  351. (monitor->nr_cpus > 1) ? "" : "\n",
  352. mon_add_commas(buffer, sizeof(buffer), cpu_insns_second));
  353. else if (sim_cycles_second)
  354. printf_filtered ("Simulator speed was %s simulation cycles/second\n",
  355. mon_add_commas(buffer, sizeof(buffer), sim_cycles_second));
  356. else if (cpu_time > 0.0)
  357. printf_filtered ("%sSimulator executed for %.2f seconds\n",
  358. (monitor->nr_cpus > 1) ? "" : "\n", cpu_time);
  359. }
  360. #endif /* _MON_C_ */