1/* FRV simulator memory option handling.
2   Copyright (C) 1999, 2000, 2007 Free Software Foundation, Inc.
3   Contributed by Red Hat.
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20#define WANT_CPU frvbf
21#define WANT_CPU_FRVBF
22
23#include "sim-main.h"
24#include "sim-assert.h"
25#include "sim-options.h"
26
27#ifdef HAVE_STRING_H
28#include <string.h>
29#else
30#ifdef HAVE_STRINGS_H
31#include <strings.h>
32#endif
33#endif
34#ifdef HAVE_STDLIB_H
35#include <stdlib.h>
36#endif
37
38/* FRV specific command line options. */
39
40enum {
41  OPTION_FRV_DATA_CACHE = OPTION_START,
42  OPTION_FRV_INSN_CACHE,
43  OPTION_FRV_PROFILE_CACHE,
44  OPTION_FRV_PROFILE_PARALLEL,
45  OPTION_FRV_TIMER,
46  OPTION_FRV_MEMORY_LATENCY
47};
48
49static DECLARE_OPTION_HANDLER (frv_option_handler);
50
51const OPTION frv_options[] =
52{
53  { {"profile", optional_argument, NULL, 'p'},
54      'p', "on|off", "Perform profiling",
55      frv_option_handler },
56  { {"data-cache", optional_argument, NULL, OPTION_FRV_DATA_CACHE },
57      '\0', "WAYS[,SETS[,LINESIZE]]", "Enable data cache",
58      frv_option_handler },
59  { {"insn-cache", optional_argument, NULL, OPTION_FRV_INSN_CACHE },
60      '\0', "WAYS[,SETS[,LINESIZE]]", "Enable instruction cache",
61      frv_option_handler },
62  { {"profile-cache", optional_argument, NULL, OPTION_FRV_PROFILE_CACHE },
63      '\0', "on|off", "Profile caches",
64      frv_option_handler },
65  { {"profile-parallel", optional_argument, NULL, OPTION_FRV_PROFILE_PARALLEL },
66      '\0', "on|off", "Profile parallelism",
67      frv_option_handler },
68  { {"timer", required_argument, NULL, OPTION_FRV_TIMER },
69      '\0', "CYCLES,INTERRUPT", "Set Interrupt Timer",
70      frv_option_handler },
71  { {"memory-latency", required_argument, NULL, OPTION_FRV_MEMORY_LATENCY },
72      '\0', "CYCLES", "Set Latency of memory",
73      frv_option_handler },
74  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
75};
76
77static char *
78parse_size (char *chp, address_word *nr_bytes)
79{
80  /* <nr_bytes> */
81  *nr_bytes = strtoul (chp, &chp, 0);
82  return chp;
83}
84
85static address_word
86check_pow2 (address_word value, char *argname, char *optname, SIM_DESC sd)
87{
88  if ((value & (value - 1)) != 0)
89    {
90      sim_io_eprintf (sd, "%s argument to %s must be a power of 2\n",
91		      argname, optname);
92      return 0; /* will enable default value.  */
93    }
94
95  return value;
96}
97
98static void
99parse_cache_option (SIM_DESC sd, char *arg, char *cache_name, int is_data_cache)
100{
101  int i;
102  address_word ways = 0, sets = 0, linesize = 0;
103  if (arg != NULL)
104    {
105      char *chp = arg;
106      /* parse the arguments */
107      chp = parse_size (chp, &ways);
108      ways = check_pow2 (ways, "WAYS", cache_name, sd);
109      if (*chp == ',')
110	{
111	  chp = parse_size (chp + 1, &sets);
112	  sets = check_pow2 (sets, "SETS", cache_name, sd);
113	  if (*chp == ',')
114	    {
115	      chp = parse_size (chp + 1, &linesize);
116	      linesize = check_pow2 (linesize, "LINESIZE", cache_name, sd);
117	    }
118	}
119    }
120  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
121    {
122      SIM_CPU *current_cpu = STATE_CPU (sd, i);
123      FRV_CACHE *cache = is_data_cache ? CPU_DATA_CACHE (current_cpu)
124	                               : CPU_INSN_CACHE (current_cpu);
125      cache->ways = ways;
126      cache->sets = sets;
127      cache->line_size = linesize;
128      frv_cache_init (current_cpu, cache);
129    }
130}
131
132static SIM_RC
133frv_option_handler (SIM_DESC sd, sim_cpu *current_cpu, int opt,
134		    char *arg, int is_command)
135{
136  switch (opt)
137    {
138    case 'p' :
139      if (! WITH_PROFILE)
140	sim_io_eprintf (sd, "Profiling not compiled in, `-p' ignored\n");
141      else
142	{
143	  unsigned mask = PROFILE_USEFUL_MASK;
144	  if (WITH_PROFILE_CACHE_P)
145	    mask |= (1 << PROFILE_CACHE_IDX);
146	  if (WITH_PROFILE_PARALLEL_P)
147	    mask |= (1 << PROFILE_PARALLEL_IDX);
148	  return set_profile_option_mask (sd, "profile", mask, arg);
149	}
150      break;
151
152    case OPTION_FRV_DATA_CACHE:
153      parse_cache_option (sd, arg, "data_cache", 1/*is_data_cache*/);
154      return SIM_RC_OK;
155
156    case OPTION_FRV_INSN_CACHE:
157      parse_cache_option (sd, arg, "insn_cache", 0/*is_data_cache*/);
158      return SIM_RC_OK;
159
160    case OPTION_FRV_PROFILE_CACHE:
161      if (WITH_PROFILE_CACHE_P)
162	return sim_profile_set_option (sd, "-cache", PROFILE_CACHE_IDX, arg);
163      else
164	sim_io_eprintf (sd, "Cache profiling not compiled in, `--profile-cache' ignored\n");
165      break;
166
167    case OPTION_FRV_PROFILE_PARALLEL:
168      if (WITH_PROFILE_PARALLEL_P)
169	{
170	  unsigned mask
171	    = (1 << PROFILE_MODEL_IDX) | (1 << PROFILE_PARALLEL_IDX);
172	  return set_profile_option_mask (sd, "-parallel", mask, arg);
173	}
174      else
175	sim_io_eprintf (sd, "Parallel profiling not compiled in, `--profile-parallel' ignored\n");
176      break;
177
178    case OPTION_FRV_TIMER:
179      {
180	char *chp = arg;
181	address_word cycles, interrupt;
182	chp = parse_size (chp, &cycles);
183	if (chp == arg)
184	  {
185	    sim_io_eprintf (sd, "Cycle count required for --timer\n");
186	    return SIM_RC_FAIL;
187	  }
188	if (*chp != ',')
189	  {
190	    sim_io_eprintf (sd, "Interrupt number required for --timer\n");
191	    return SIM_RC_FAIL;
192	  }
193	chp = parse_size (chp + 1, &interrupt);
194	if (interrupt < 1 || interrupt > 15)
195	  {
196	    sim_io_eprintf (sd, "Interrupt number for --timer must be greater than 0 and less that 16\n");
197	    return SIM_RC_FAIL;
198	  }
199	frv_interrupt_state.timer.enabled = 1;
200	frv_interrupt_state.timer.value = cycles;
201	frv_interrupt_state.timer.current = 0;
202	frv_interrupt_state.timer.interrupt =
203	  FRV_INTERRUPT_LEVEL_1 + interrupt - 1;
204      }
205      return SIM_RC_OK;
206
207    case OPTION_FRV_MEMORY_LATENCY:
208      {
209	int i;
210	char *chp = arg;
211	address_word cycles;
212	chp = parse_size (chp, &cycles);
213	if (chp == arg)
214	  {
215	    sim_io_eprintf (sd, "Cycle count required for --memory-latency\n");
216	    return SIM_RC_FAIL;
217	  }
218	for (i = 0; i < MAX_NR_PROCESSORS; ++i)
219	  {
220	    SIM_CPU *current_cpu = STATE_CPU (sd, i);
221	    FRV_CACHE *insn_cache = CPU_INSN_CACHE (current_cpu);
222	    FRV_CACHE *data_cache = CPU_DATA_CACHE (current_cpu);
223	    insn_cache->memory_latency = cycles;
224	    data_cache->memory_latency = cycles;
225	  }
226      }
227      return SIM_RC_OK;
228
229    default:
230      sim_io_eprintf (sd, "Unknown FRV option %d\n", opt);
231      return SIM_RC_FAIL;
232
233    }
234
235  return SIM_RC_FAIL;
236}
237