Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / procs / sunsparc / debug / coverage.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: coverage.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.c 1.5 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/mman.h>
34#include <assert.h>
35#include <string.h>
36#include <strings.h>
37#include <fcntl.h>
38#include <sys/stat.h>
39#include <thread.h>
40#include <synch.h>
41
42#include "ss_common.h"
43#include "niagara.h"
44#include "coverage.h"
45
46#if 1
47#define DBGP(s) do { s; } while (0)
48#endif
49
50void dbg_coverage(simcpu_t *sp, uint32_t rawi);
51void dbg_coverage_parse(void);
52void dbg_coverage_dump(void);
53
54/* start/end for pc,instn coverage analysis */
55uint32_t coverage_mode;
56uint64_t start_pc = 0x0;
57uint64_t end_pc = 0x0;
58bool_t decode_instn = false;
59void *coverage_data_filep;
60
61coverage_info_t *coverage_bufp;
62
63 /*
64 * This will be called while parsing the conf file
65 * to allow this hook to parse specific options from
66 * the conf file.
67 *
68 * Format of coverage directive is:
69 * debug_hook [coverage] [start] [end];
70 *
71 * [coverage] - we've already parsed this. That's how we got here.
72 * [data_file] - name of the file to mmap (will contain coverage data)
73 * [start]
74 * [end] - only trace when %pc is within [start]-[end] range
75 *
76 * All samples for %pc within the range supplied will be stored
77 * in a data file (using the name provided in the directive). The
78 * results of the coverage run can be viewed by running the
79 * coverage_dump tool (in the build directory) at any time during
80 * or after the run.
81 * NOTE: this feature will not overwrite the data_file
82 */
83void
84dbg_coverage_parse(void)
85{
86 lexer_tok_t tok;
87 uint64_t num_of_pcs;
88 int shmflg;
89 uint64_t buf_size;
90 char data_file[256];
91 struct stat sb;
92 mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
93 int fd;
94
95
96 DBGP(printf("\nInside dbg_coverage_parse()"));
97
98 /* Parse data_file to mmap in */
99 tok = lex_get_token();
100 strcpy(data_file, lex.strp);
101
102
103 lex_get(T_Number); /* start pc */
104 start_pc = lex.val;
105 lex_get(T_Number); /* end pc */
106 end_pc = lex.val;
107
108 if (end_pc < start_pc)
109 lex_fatal("end_pc needs to be larger than start_pc in conf file");
110
111 num_of_pcs = ((end_pc - start_pc) / 4) + 1;
112 buf_size = ((sizeof (coverage_info_t)) * num_of_pcs);
113
114 DBGP(printf("\ncoverage: start_pc=0x%llx, end_pc=0x%llx "\
115 "num_of_pcs=0x%llx, buf_size=0x%llx",
116 start_pc, end_pc, num_of_pcs, buf_size));
117
118 /*
119 * Setup mmap file.
120 *
121 * Create the empty data_file of size buf_size
122 * Then mmap it into memory.
123 */
124
125 /* Make sure file does not exist */
126 if (stat(data_file, &sb) == 0)
127 lex_fatal("coverage: file %s already exists. Check conf file ",
128 data_file);
129
130 /* Create a new file */
131 if ((fd = open(data_file, O_RDWR | O_CREAT | O_TRUNC, mode)) == -1)
132 fatal("Could not create data_file %s\n", data_file);
133
134 /* Set the size of the file by seeking to the end and write NULL */
135 if (lseek(fd, (off_t)buf_size-1, SEEK_SET) < 0)
136 fatal("Could not create data_file of size [0x%llx]", buf_size);
137
138 if (write(fd, "", 1) != 1)
139 fatal("Could not write to data_file of size [0x%llx]", buf_size);
140
141 /* mmap file file */
142 coverage_data_filep = mmap(NULL, buf_size, PROT_READ | PROT_WRITE,
143 MAP_SHARED, fd, 0);
144 if (coverage_data_filep == MAP_FAILED)
145 fatal("Failed to mmap %s\n", data_file);
146
147 coverage_bufp = coverage_data_filep;
148
149 /*
150 * return to parse_debug_hook() which will take care of
151 * parsing the last semi colon.
152 */
153}
154
155
156 /*
157 * This function will get called before each instruction
158 * gets executed in execloop(). We use the coverage_dump tool
159 * in legion to read the datafile.
160 */
161void
162dbg_coverage(simcpu_t *sp, uint32_t rawi)
163{
164 extern uint32_t sim_atomic_add_32_nv(uint32_t *target, int32_t delta);
165 int idx = 0;
166 sparcv9_cpu_t *v9p = (sparcv9_cpu_t *)(sp->specificp);
167
168 /*
169 * Only store data when %pc is in Hypervisor and it is in range
170 * XXX FIXME: we could parse the state from the config file.
171 */
172 if ((v9p->state != V9_HyperPriv) ||
173 (sp->pc <= start_pc) || (sp->pc >= end_pc)) {
174 return;
175 }
176
177 idx = ((sp->pc - start_pc) / 4);
178
179 /* Increment counter and copy instn into buffer once */
180 if (sim_atomic_add_32_nv(&(coverage_bufp[idx].count), 1) == 1) {
181 coverage_bufp[idx].pc = sp->pc;
182 coverage_bufp[idx].rawi = rawi;
183 }
184}
185
186void
187dbg_coverage_dump(void)
188{
189 printf("\ndbg_coverage_dump: caled with start=0x%llx, end=0x%llx",
190 start_pc, end_pc);
191 printf("\nuse legion's coverage_dump tool to read the data file");
192}