* Makefile.in (sim-options_h): Define.
[external/binutils.git] / sim / common / cgen-scache.c
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
177 /* Print cache access statics for CPU.  */
178
179 void
180 scache_print_profile (SIM_CPU *cpu, int verbose)
181 {
182   SIM_DESC sd = CPU_STATE (cpu);
183   unsigned long hits = CPU_SCACHE_HITS (cpu);
184   unsigned long misses = CPU_SCACHE_MISSES (cpu);
185
186   sim_io_printf (sd, "Simulator Cache Statistics\n\n");
187
188   /* One could use PROFILE_LABEL_WIDTH here.  I chose not to.  */
189   sim_io_printf (sd, "  Cache size: %d\n", CPU_SCACHE_SIZE (cpu));
190   sim_io_printf (sd, "  Hits:       %d\n", hits);
191   sim_io_printf (sd, "  Misses:     %d\n", misses);
192   if (hits + misses != 0)
193     sim_io_printf (sd, "  Hit rate:   %.2f%%\n",
194                    ((double) hits / ((double) hits + (double) misses)) * 100);
195   sim_io_printf (sd, "\n");
196 }