Commit | Line | Data |
---|---|---|
b9c8cd10 DE |
1 | /* Simulator cache routines for CGEN simulators (and maybe others). |
2 | Copyright (C) 1996, 1997 Free Software Foundation, Inc. | |
3 | Contributed by Cygnus Support. | |
4 | ||
5 | This file is part of GDB, the GNU debugger. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License along | |
18 | with this program; if not, write to the Free Software Foundation, Inc., | |
19 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #define SCACHE_P | |
22 | #define SCACHE_DEFINE_INLINE | |
23 | ||
24 | #include "sim-main.h" | |
25 | #include "libiberty.h" | |
26 | #include "cgen-scache.h" | |
27 | #include "sim-options.h" | |
28 | #include "sim-io.h" | |
29 | ||
30 | /* Unused address. */ | |
31 | #define UNUSED_ADDR 0xffffffff | |
32 | ||
33 | static MODULE_INIT_FN scache_init; | |
34 | static MODULE_UNINSTALL_FN scache_uninstall; | |
35 | ||
36 | static DECLARE_OPTION_HANDLER (scache_option_handler); | |
37 | ||
38 | #define OPTION_PROFILE_SCACHE (OPTION_START + 0) | |
39 | ||
40 | static const OPTION scache_options[] = { | |
41 | { {"scache-size", optional_argument, NULL, 'c'}, | |
42 | 'c', "[SIZE]", "Specify size of simulator execution cache", | |
43 | scache_option_handler }, | |
44 | { {"profile-scache", no_argument, NULL, OPTION_PROFILE_SCACHE}, | |
45 | '\0', NULL, "Perform simulator execution cache profiling", | |
46 | scache_option_handler }, | |
47 | { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } | |
48 | }; | |
49 | ||
50 | static SIM_RC | |
51 | scache_option_handler (sd, opt, arg) | |
52 | SIM_DESC sd; | |
53 | int opt; | |
54 | char *arg; | |
55 | { | |
56 | int n; | |
57 | ||
58 | switch (opt) | |
59 | { | |
60 | case 'c' : | |
61 | if (WITH_SCACHE) | |
62 | { | |
63 | if (arg != NULL) | |
64 | { | |
65 | int n = strtol (arg, NULL, 0); | |
66 | /* The m32r port assumes a cache size of at least 2 so it | |
67 | can decode both 16 bit insns. */ | |
68 | if (n < 2) | |
69 | { | |
70 | sim_io_eprintf (sd, "invalid scache size `%d'", n); | |
71 | return SIM_RC_FAIL; | |
72 | } | |
73 | /* Ensure it's a multiple of 2. */ | |
74 | if ((n & (n - 1)) != 0) | |
75 | { | |
76 | sim_io_eprintf (sd, "scache size `%d' not a multiple of 2\n", n); | |
77 | { | |
78 | /* round up to nearest multiple of 2 */ | |
79 | int i; | |
80 | for (i = 1; i < n; i <<= 1) | |
81 | continue; | |
82 | n = i; | |
83 | ||
84 | } | |
85 | sim_io_eprintf (sd, "rounding scache size up to %d\n", n); | |
86 | } | |
87 | STATE_SCACHE_SIZE (sd) = n; | |
88 | } | |
89 | else | |
90 | STATE_SCACHE_SIZE (sd) = SCACHE_DEFAULT_CACHE_SIZE; | |
91 | } | |
92 | else | |
93 | sim_io_eprintf (sd, "Simulator execution cache not enabled, `--scache-size' ignored\n"); | |
94 | break; | |
95 | ||
96 | case OPTION_PROFILE_SCACHE : | |
97 | if (WITH_SCACHE && WITH_PROFILE_SCACHE_P) | |
98 | for (n = 0; n < MAX_NR_PROCESSORS; ++n) | |
99 | CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_SCACHE_IDX] = 1; | |
100 | else | |
101 | sim_io_eprintf (sd, "Simulator cache profiling not compiled in, `--profile-scache' ignored\n"); | |
102 | break; | |
103 | ||
104 | } | |
105 | ||
106 | return SIM_RC_OK; | |
107 | } | |
108 | ||
109 | SIM_RC | |
110 | scache_install (SIM_DESC sd) | |
111 | { | |
112 | sim_add_option_table (sd, scache_options); | |
113 | sim_module_add_init_fn (sd, scache_init); | |
114 | sim_module_add_uninstall_fn (sd, scache_uninstall); | |
115 | ||
116 | /* This is the default, it may be overridden on the command line. */ | |
117 | STATE_SCACHE_SIZE (sd) = WITH_SCACHE; | |
118 | ||
119 | return SIM_RC_OK; | |
120 | } | |
121 | ||
122 | static SIM_RC | |
123 | scache_init (SIM_DESC sd) | |
124 | { | |
125 | int c; | |
126 | ||
127 | for (c = 0; c < MAX_NR_PROCESSORS; ++c) | |
128 | { | |
129 | SIM_CPU *cpu = STATE_CPU (sd, c); | |
130 | ||
131 | CPU_SCACHE_SIZE (cpu) = STATE_SCACHE_SIZE (sd); | |
132 | CPU_SCACHE_CACHE (cpu) = (SCACHE *) | |
133 | xmalloc (CPU_SCACHE_SIZE (cpu) * sizeof (SCACHE)); | |
134 | } | |
135 | ||
136 | scache_flush (sd); | |
137 | ||
138 | return SIM_RC_OK; | |
139 | } | |
140 | ||
141 | static void | |
142 | scache_uninstall (SIM_DESC sd) | |
143 | { | |
144 | int c; | |
145 | ||
146 | for (c = 0; c < MAX_NR_PROCESSORS; ++c) | |
147 | { | |
148 | SIM_CPU *cpu = STATE_CPU (sd, c); | |
149 | ||
150 | if (CPU_SCACHE_CACHE (cpu) != NULL) | |
151 | free (CPU_SCACHE_CACHE (cpu)); | |
152 | } | |
153 | } | |
154 | ||
155 | void | |
156 | scache_flush (SIM_DESC sd) | |
157 | { | |
158 | int i,c; | |
159 | SCACHE *sc; | |
160 | ||
161 | for (c = 0; c < MAX_NR_PROCESSORS; ++c) | |
162 | { | |
163 | SIM_CPU *cpu = STATE_CPU (sd, c); | |
164 | ||
165 | /* Technically, this may not be necessary, but it helps debugging. */ | |
166 | memset (CPU_SCACHE_CACHE (cpu), 0, | |
167 | CPU_SCACHE_SIZE (cpu) * sizeof (SCACHE)); | |
168 | ||
169 | for (i = 0, sc = CPU_SCACHE_CACHE (cpu); i < CPU_SCACHE_SIZE (cpu); | |
170 | ++i, ++sc) | |
171 | { | |
172 | sc->argbuf.addr = UNUSED_ADDR; | |
173 | } | |
174 | } | |
175 | } | |
176 | ||
c967f187 DE |
177 | /* Print cache access statics for CPU. */ |
178 | ||
b9c8cd10 | 179 | void |
c967f187 | 180 | scache_print_profile (SIM_CPU *cpu, int verbose) |
b9c8cd10 | 181 | { |
c967f187 | 182 | SIM_DESC sd = CPU_STATE (cpu); |
b9c8cd10 DE |
183 | unsigned long hits = CPU_SCACHE_HITS (cpu); |
184 | unsigned long misses = CPU_SCACHE_MISSES (cpu); | |
2317a499 | 185 | char buf[20]; |
b9c8cd10 DE |
186 | |
187 | sim_io_printf (sd, "Simulator Cache Statistics\n\n"); | |
188 | ||
c967f187 | 189 | /* One could use PROFILE_LABEL_WIDTH here. I chose not to. */ |
2317a499 DE |
190 | sim_io_printf (sd, " Cache size: %d\n", |
191 | sim_add_commas (buf, sizeof (buf), CPU_SCACHE_SIZE (cpu))); | |
192 | sim_io_printf (sd, " Hits: %s\n", | |
193 | sim_add_commas (buf, sizeof (buf), hits)); | |
194 | sim_io_printf (sd, " Misses: %s\n", | |
195 | sim_add_commas (buf, sizeof (buf), misses)); | |
b9c8cd10 | 196 | if (hits + misses != 0) |
c967f187 | 197 | sim_io_printf (sd, " Hit rate: %.2f%%\n", |
b9c8cd10 DE |
198 | ((double) hits / ((double) hits + (double) misses)) * 100); |
199 | sim_io_printf (sd, "\n"); | |
200 | } |