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