Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / procs / sunsparc / debug / tools / coverage_dump.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: coverage_dump.c
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23/*
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27#pragma ident "@(#)coverage_dump.c 1.6 06/10/25 SMI"
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <assert.h>
35#include <string.h>
36#include <strings.h>
37#include <fcntl.h>
38
39#include "basics.h"
40#include "fatal.h"
41#include "coverage.h"
42
43#if 1
44#define DBGP(s) do { s } while (0)
45#endif
46
47void
48usage(void)
49{
50 printf("\nUsage: coverage_dump [- a] [-z] [-c num_samples] "\
51 "[-r] [-v] [-t] filename" \
52 "\n [-a | --all]" \
53 "\n - dump all samples (zero and non-zero)" \
54 "\n [-z | --zero]" \
55 "\n - dump only zero samples (%%pc never hit)" \
56 "\n [-c | --count num_of_samples]" \
57 "\n - dump first num_of_samples %%pc samples" \
58 "\n - if this option is not given, all non-zero "\
59 "samples are dumped " \
60 "\n [-r | --ref]" \
61 "\n - don't increment the ref count for each "\
62 "access to a %%pc "\
63 "\n instead print 0x1 (if it was ever executed) "\
64 "\n or a 0x0 (if it was never executed) "\
65 "\n [-v | --verbose]" \
66 "\n - decode and display the raw instns" \
67 "\n by default, only the raw instn gets dumped" \
68 "\n [-t | --titles]" \
69 "\n - print titles and footer " \
70 "\n " \
71 "\n filename" \
72 "\n The name of file with legion coverage data" \
73 "\n " \
74 "\n When run with no options, dump all non-zero samples" \
75 "\n " \
76 "\n This tool is meant to work with the debug_hook feature" \
77 "\n for gathering coverage data. You need to" \
78 "\n specify a range of %%pc addresses in the conf file " \
79 "\n under the cpu directive as follows:" \
80 "\n " \
81 "\n debug_hook coverage 0x100000 0x800000;" \
82 "\n " \
83 "\n");
84}
85
86bool_t
87streq(char *a, char *b)
88{
89 return (strcmp(a, b) == 0);
90}
91
92 /*
93 * Attach to shared memory created by legion and
94 * dump out coverage statistics from the running
95 * system.
96 */
97int
98main(int argc, char ** argv)
99{
100 uint64_t buf_size;
101 uint64_t dump_count = 0;
102 uint64_t sample_count;
103 uint64_t low_pc = 0;
104 uint64_t high_pc = 0;
105 uint64_t i;
106 bool_t dump_all_samples = false;
107 bool_t dump_zero_samples = false;
108 bool_t verbose = false;
109 bool_t titles = false;
110 bool_t ref_only = false;
111 char instn_buf[160];
112 bool_t print_it = false;
113 char filename[256];
114 int fd;
115 struct stat sb;
116 uint64_t num_of_pcs = 0;
117 coverage_info_t coverage_buf;
118
119
120
121 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
122 char *p;
123
124 p = &(argv[i][1]);
125
126 if (streq(p, "a") || streq(p, "-all")) {
127 if (dump_zero_samples) {
128 printf("\nERROR: Cannot use both -a and -z");
129 usage();
130 exit(1);
131 }
132 dump_all_samples = true;
133 } else
134 if (streq(p, "z") || streq(p, "-zero")) {
135 if (dump_all_samples) {
136 printf("\nERROR: Cannot use both -a and -z");
137 usage();
138 exit(1);
139 }
140 dump_zero_samples = true;
141 } else
142 if (streq(p, "c") || streq(p, "-count")) {
143 if (++i >= argc) {
144 usage();
145 exit(1);
146 }
147 dump_count = atol(argv[i]);
148 if (dump_count == 0) {
149 printf("\nERROR: Invalid value for count");
150 usage();
151 exit(1);
152 }
153 } else
154 if (streq(p, "r") || streq(p, "-ref")) {
155 ref_only = true;
156 } else
157 if (streq(p, "v") || streq(p, "-verbose")) {
158 verbose = true;
159 } else
160 if (streq(p, "t") || streq(p, "-titles")) {
161 titles = true;
162 } else {
163 printf("\nERROR: Illegal option %s", p);
164 usage();
165 exit(1);
166 }
167 }
168
169 /*
170 * Assume any non option provided is the name of the coverage
171 * data file.
172 */
173 if (i == (argc - 1)) {
174 strcpy(filename, argv[i]);
175 } else {
176 printf("\nERROR: no filename specified");
177 usage();
178 exit(1);
179 }
180
181
182 /*
183 * Open the dump_file and get it's size.
184 *
185 * In order to figure out how many samples are in this file
186 * we divide the file size by the size of this struct.
187 * We can then then either dump them all, or dump just the first n
188 * if the -c flag is specified.
189 */
190 if (stat(filename, &sb) == -1)
191 fatal("Error: dump_file %s does not exist.", filename);
192
193 sample_count = (sb.st_size / (sizeof (coverage_info_t)));
194
195 if ((fd = open(filename, O_RDONLY)) == -1)
196 fatal("Could not open dump_file %s\n", filename);
197
198 /*
199 * Depending on whether a specific number of samples was
200 * given at the command line or not, we either dump them
201 * all or just the first n samples.
202 * The -a flag determines whether we print the zero samples.
203 * The -z flag determines whether we only print the zero samples.
204 */
205 if (dump_count != 0) {
206 num_of_pcs = dump_count; /* value from command line */
207 } else {
208 num_of_pcs = sample_count;
209 }
210
211 if (titles) {
212 printf("\nOpened data file : [%s] ", filename);
213 printf("\nSize of file in bytes : [0x%llx] ", sb.st_size);
214 printf("\nNumber of %%pc samples : [0x%llx] ", sample_count);
215 printf("\nIndx:%%pc:Ref_Cnt:Raw_Instn Decoded_Inst\n");
216 }
217
218 for (i = 0; i < num_of_pcs; i++) {
219
220 /* Read from the file */
221 if (read(fd, &coverage_buf, sizeof (coverage_info_t)) !=
222 sizeof (coverage_info_t)) {
223 perror("read");
224 fatal("Error reading from file %s\n", filename);
225 }
226
227 /* Gather stats for the end */
228 if (coverage_buf.count != 0) {
229 /* save the last non-zero count %pc */
230 high_pc = coverage_buf.pc;
231 if (low_pc == 0) {
232 /* save the first non-zero count %pc */
233 low_pc = coverage_buf.pc;
234 }
235 }
236
237 /* Figure out whether to print this sample or not */
238 print_it = false;
239
240 if (dump_all_samples) {
241 print_it = true;
242 } else if (dump_zero_samples) {
243 if (coverage_buf.count == 0)
244 print_it = true;
245 } else if (coverage_buf.count != 0) {
246 print_it = true;
247 }
248
249 if (print_it) {
250
251 if (ref_only) {
252 if (coverage_buf.count > 0x1)
253 coverage_buf.count = 0x1; /* reset to 0x1 */
254 }
255
256 printf("0x%llx:0x%llx:0x%x:0x%08x",
257 i, coverage_buf.pc, coverage_buf.count,
258 coverage_buf.rawi);
259
260 if (verbose) {
261 if (coverage_buf.count != 0) {
262 sparcv9_idis(instn_buf, sizeof (instn_buf),
263 coverage_buf.rawi, coverage_buf.pc);
264 } else {
265 sprintf(instn_buf, ":N/A", "%s");
266 }
267 printf(":%s", instn_buf);
268 }
269 printf("\n");
270 }
271
272 }
273
274 if (titles) {
275 printf("\nLoweset/Highest %%pc : [0x%llx] [0x%llx]\n",
276 low_pc, high_pc);
277 }
278
279 close(fd);
280
281 return (0);
282}