xref: /netbsd-src/external/gpl3/gdb/dist/sim/frv/options.c (revision 28bcf0b924ec476f57aeda79eff0c1a07cb62e5f)
14e98e3e1Schristos /* FRV simulator memory option handling.
2*28bcf0b9Schristos    Copyright (C) 1999-2024 Free Software Foundation, Inc.
34e98e3e1Schristos    Contributed by Red Hat.
44e98e3e1Schristos 
54e98e3e1Schristos This file is part of GDB, the GNU debugger.
64e98e3e1Schristos 
74e98e3e1Schristos This program is free software; you can redistribute it and/or modify
84e98e3e1Schristos it under the terms of the GNU General Public License as published by
94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or
104e98e3e1Schristos (at your option) any later version.
114e98e3e1Schristos 
124e98e3e1Schristos This program is distributed in the hope that it will be useful,
134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
154e98e3e1Schristos GNU General Public License for more details.
164e98e3e1Schristos 
174e98e3e1Schristos You should have received a copy of the GNU General Public License
184e98e3e1Schristos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
194e98e3e1Schristos 
204b169a6bSchristos /* This must come before any other includes.  */
214b169a6bSchristos #include "defs.h"
224b169a6bSchristos 
234e98e3e1Schristos #define WANT_CPU frvbf
244e98e3e1Schristos #define WANT_CPU_FRVBF
254e98e3e1Schristos 
264e98e3e1Schristos #include "sim-main.h"
274e98e3e1Schristos #include "sim-assert.h"
284e98e3e1Schristos #include "sim-options.h"
294e98e3e1Schristos 
304e98e3e1Schristos #include <string.h>
314e98e3e1Schristos #include <stdlib.h>
324e98e3e1Schristos 
334e98e3e1Schristos /* FRV specific command line options. */
344e98e3e1Schristos 
354e98e3e1Schristos enum {
364e98e3e1Schristos   OPTION_FRV_DATA_CACHE = OPTION_START,
374e98e3e1Schristos   OPTION_FRV_INSN_CACHE,
384e98e3e1Schristos   OPTION_FRV_PROFILE_CACHE,
394e98e3e1Schristos   OPTION_FRV_PROFILE_PARALLEL,
404e98e3e1Schristos   OPTION_FRV_TIMER,
414e98e3e1Schristos   OPTION_FRV_MEMORY_LATENCY
424e98e3e1Schristos };
434e98e3e1Schristos 
444e98e3e1Schristos static DECLARE_OPTION_HANDLER (frv_option_handler);
454e98e3e1Schristos 
464e98e3e1Schristos const OPTION frv_options[] =
474e98e3e1Schristos {
484e98e3e1Schristos   { {"profile", optional_argument, NULL, 'p'},
494e98e3e1Schristos       'p', "on|off", "Perform profiling",
504e98e3e1Schristos       frv_option_handler },
514e98e3e1Schristos   { {"data-cache", optional_argument, NULL, OPTION_FRV_DATA_CACHE },
524e98e3e1Schristos       '\0', "WAYS[,SETS[,LINESIZE]]", "Enable data cache",
534e98e3e1Schristos       frv_option_handler },
544e98e3e1Schristos   { {"insn-cache", optional_argument, NULL, OPTION_FRV_INSN_CACHE },
554e98e3e1Schristos       '\0', "WAYS[,SETS[,LINESIZE]]", "Enable instruction cache",
564e98e3e1Schristos       frv_option_handler },
574e98e3e1Schristos   { {"profile-cache", optional_argument, NULL, OPTION_FRV_PROFILE_CACHE },
584e98e3e1Schristos       '\0', "on|off", "Profile caches",
594e98e3e1Schristos       frv_option_handler },
604e98e3e1Schristos   { {"profile-parallel", optional_argument, NULL, OPTION_FRV_PROFILE_PARALLEL },
614e98e3e1Schristos       '\0', "on|off", "Profile parallelism",
624e98e3e1Schristos       frv_option_handler },
634e98e3e1Schristos   { {"timer", required_argument, NULL, OPTION_FRV_TIMER },
644e98e3e1Schristos       '\0', "CYCLES,INTERRUPT", "Set Interrupt Timer",
654e98e3e1Schristos       frv_option_handler },
664e98e3e1Schristos   { {"memory-latency", required_argument, NULL, OPTION_FRV_MEMORY_LATENCY },
674e98e3e1Schristos       '\0', "CYCLES", "Set Latency of memory",
684e98e3e1Schristos       frv_option_handler },
694e98e3e1Schristos   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
704e98e3e1Schristos };
714e98e3e1Schristos 
724e98e3e1Schristos static char *
734e98e3e1Schristos parse_size (char *chp, address_word *nr_bytes)
744e98e3e1Schristos {
754e98e3e1Schristos   /* <nr_bytes> */
764e98e3e1Schristos   *nr_bytes = strtoul (chp, &chp, 0);
774e98e3e1Schristos   return chp;
784e98e3e1Schristos }
794e98e3e1Schristos 
804e98e3e1Schristos static address_word
814e98e3e1Schristos check_pow2 (address_word value, char *argname, char *optname, SIM_DESC sd)
824e98e3e1Schristos {
834e98e3e1Schristos   if ((value & (value - 1)) != 0)
844e98e3e1Schristos     {
854e98e3e1Schristos       sim_io_eprintf (sd, "%s argument to %s must be a power of 2\n",
864e98e3e1Schristos 		      argname, optname);
874e98e3e1Schristos       return 0; /* will enable default value.  */
884e98e3e1Schristos     }
894e98e3e1Schristos 
904e98e3e1Schristos   return value;
914e98e3e1Schristos }
924e98e3e1Schristos 
934e98e3e1Schristos static void
944e98e3e1Schristos parse_cache_option (SIM_DESC sd, char *arg, char *cache_name, int is_data_cache)
954e98e3e1Schristos {
964e98e3e1Schristos   int i;
974e98e3e1Schristos   address_word ways = 0, sets = 0, linesize = 0;
984e98e3e1Schristos   if (arg != NULL)
994e98e3e1Schristos     {
1004e98e3e1Schristos       char *chp = arg;
1014e98e3e1Schristos       /* parse the arguments */
1024e98e3e1Schristos       chp = parse_size (chp, &ways);
1034e98e3e1Schristos       ways = check_pow2 (ways, "WAYS", cache_name, sd);
1044e98e3e1Schristos       if (*chp == ',')
1054e98e3e1Schristos 	{
1064e98e3e1Schristos 	  chp = parse_size (chp + 1, &sets);
1074e98e3e1Schristos 	  sets = check_pow2 (sets, "SETS", cache_name, sd);
1084e98e3e1Schristos 	  if (*chp == ',')
1094e98e3e1Schristos 	    {
1104e98e3e1Schristos 	      chp = parse_size (chp + 1, &linesize);
1114e98e3e1Schristos 	      linesize = check_pow2 (linesize, "LINESIZE", cache_name, sd);
1124e98e3e1Schristos 	    }
1134e98e3e1Schristos 	}
1144e98e3e1Schristos     }
1154e98e3e1Schristos   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1164e98e3e1Schristos     {
1174e98e3e1Schristos       SIM_CPU *current_cpu = STATE_CPU (sd, i);
1184e98e3e1Schristos       FRV_CACHE *cache = is_data_cache ? CPU_DATA_CACHE (current_cpu)
1194e98e3e1Schristos 	                               : CPU_INSN_CACHE (current_cpu);
1204e98e3e1Schristos       cache->ways = ways;
1214e98e3e1Schristos       cache->sets = sets;
1224e98e3e1Schristos       cache->line_size = linesize;
1234e98e3e1Schristos       frv_cache_init (current_cpu, cache);
1244e98e3e1Schristos     }
1254e98e3e1Schristos }
1264e98e3e1Schristos 
1274e98e3e1Schristos static SIM_RC
1284e98e3e1Schristos frv_option_handler (SIM_DESC sd, sim_cpu *current_cpu, int opt,
1294e98e3e1Schristos 		    char *arg, int is_command)
1304e98e3e1Schristos {
1314e98e3e1Schristos   switch (opt)
1324e98e3e1Schristos     {
1334e98e3e1Schristos     case 'p' :
1344e98e3e1Schristos       if (! WITH_PROFILE)
1354e98e3e1Schristos 	sim_io_eprintf (sd, "Profiling not compiled in, `-p' ignored\n");
1364e98e3e1Schristos       else
1374e98e3e1Schristos 	{
1384e98e3e1Schristos 	  unsigned mask = PROFILE_USEFUL_MASK;
1394e98e3e1Schristos 	  if (WITH_PROFILE_CACHE_P)
1404e98e3e1Schristos 	    mask |= (1 << PROFILE_CACHE_IDX);
1414e98e3e1Schristos 	  if (WITH_PROFILE_PARALLEL_P)
1424e98e3e1Schristos 	    mask |= (1 << PROFILE_PARALLEL_IDX);
1434e98e3e1Schristos 	  return set_profile_option_mask (sd, "profile", mask, arg);
1444e98e3e1Schristos 	}
1454e98e3e1Schristos       break;
1464e98e3e1Schristos 
1474e98e3e1Schristos     case OPTION_FRV_DATA_CACHE:
1484e98e3e1Schristos       parse_cache_option (sd, arg, "data_cache", 1/*is_data_cache*/);
1494e98e3e1Schristos       return SIM_RC_OK;
1504e98e3e1Schristos 
1514e98e3e1Schristos     case OPTION_FRV_INSN_CACHE:
1524e98e3e1Schristos       parse_cache_option (sd, arg, "insn_cache", 0/*is_data_cache*/);
1534e98e3e1Schristos       return SIM_RC_OK;
1544e98e3e1Schristos 
1554e98e3e1Schristos     case OPTION_FRV_PROFILE_CACHE:
1564e98e3e1Schristos       if (WITH_PROFILE_CACHE_P)
1574e98e3e1Schristos 	return sim_profile_set_option (sd, "-cache", PROFILE_CACHE_IDX, arg);
1584e98e3e1Schristos       else
1594e98e3e1Schristos 	sim_io_eprintf (sd, "Cache profiling not compiled in, `--profile-cache' ignored\n");
1604e98e3e1Schristos       break;
1614e98e3e1Schristos 
1624e98e3e1Schristos     case OPTION_FRV_PROFILE_PARALLEL:
1634e98e3e1Schristos       if (WITH_PROFILE_PARALLEL_P)
1644e98e3e1Schristos 	{
1654e98e3e1Schristos 	  unsigned mask
1664e98e3e1Schristos 	    = (1 << PROFILE_MODEL_IDX) | (1 << PROFILE_PARALLEL_IDX);
1674e98e3e1Schristos 	  return set_profile_option_mask (sd, "-parallel", mask, arg);
1684e98e3e1Schristos 	}
1694e98e3e1Schristos       else
1704e98e3e1Schristos 	sim_io_eprintf (sd, "Parallel profiling not compiled in, `--profile-parallel' ignored\n");
1714e98e3e1Schristos       break;
1724e98e3e1Schristos 
1734e98e3e1Schristos     case OPTION_FRV_TIMER:
1744e98e3e1Schristos       {
1754e98e3e1Schristos 	char *chp = arg;
1764e98e3e1Schristos 	address_word cycles, interrupt;
1774e98e3e1Schristos 	chp = parse_size (chp, &cycles);
1784e98e3e1Schristos 	if (chp == arg)
1794e98e3e1Schristos 	  {
1804e98e3e1Schristos 	    sim_io_eprintf (sd, "Cycle count required for --timer\n");
1814e98e3e1Schristos 	    return SIM_RC_FAIL;
1824e98e3e1Schristos 	  }
1834e98e3e1Schristos 	if (*chp != ',')
1844e98e3e1Schristos 	  {
1854e98e3e1Schristos 	    sim_io_eprintf (sd, "Interrupt number required for --timer\n");
1864e98e3e1Schristos 	    return SIM_RC_FAIL;
1874e98e3e1Schristos 	  }
1884e98e3e1Schristos 	chp = parse_size (chp + 1, &interrupt);
1894e98e3e1Schristos 	if (interrupt < 1 || interrupt > 15)
1904e98e3e1Schristos 	  {
1914e98e3e1Schristos 	    sim_io_eprintf (sd, "Interrupt number for --timer must be greater than 0 and less that 16\n");
1924e98e3e1Schristos 	    return SIM_RC_FAIL;
1934e98e3e1Schristos 	  }
1944e98e3e1Schristos 	frv_interrupt_state.timer.enabled = 1;
1954e98e3e1Schristos 	frv_interrupt_state.timer.value = cycles;
1964e98e3e1Schristos 	frv_interrupt_state.timer.current = 0;
1974e98e3e1Schristos 	frv_interrupt_state.timer.interrupt =
1984e98e3e1Schristos 	  FRV_INTERRUPT_LEVEL_1 + interrupt - 1;
1994e98e3e1Schristos       }
2004e98e3e1Schristos       return SIM_RC_OK;
2014e98e3e1Schristos 
2024e98e3e1Schristos     case OPTION_FRV_MEMORY_LATENCY:
2034e98e3e1Schristos       {
2044e98e3e1Schristos 	int i;
2054e98e3e1Schristos 	char *chp = arg;
2064e98e3e1Schristos 	address_word cycles;
2074e98e3e1Schristos 	chp = parse_size (chp, &cycles);
2084e98e3e1Schristos 	if (chp == arg)
2094e98e3e1Schristos 	  {
2104e98e3e1Schristos 	    sim_io_eprintf (sd, "Cycle count required for --memory-latency\n");
2114e98e3e1Schristos 	    return SIM_RC_FAIL;
2124e98e3e1Schristos 	  }
2134e98e3e1Schristos 	for (i = 0; i < MAX_NR_PROCESSORS; ++i)
2144e98e3e1Schristos 	  {
215*28bcf0b9Schristos 	    SIM_CPU *cpu = STATE_CPU (sd, i);
216*28bcf0b9Schristos 	    FRV_CACHE *insn_cache = CPU_INSN_CACHE (cpu);
217*28bcf0b9Schristos 	    FRV_CACHE *data_cache = CPU_DATA_CACHE (cpu);
2184e98e3e1Schristos 	    insn_cache->memory_latency = cycles;
2194e98e3e1Schristos 	    data_cache->memory_latency = cycles;
2204e98e3e1Schristos 	  }
2214e98e3e1Schristos       }
2224e98e3e1Schristos       return SIM_RC_OK;
2234e98e3e1Schristos 
2244e98e3e1Schristos     default:
2254e98e3e1Schristos       sim_io_eprintf (sd, "Unknown FRV option %d\n", opt);
2264e98e3e1Schristos       return SIM_RC_FAIL;
2274e98e3e1Schristos 
2284e98e3e1Schristos     }
2294e98e3e1Schristos 
2304e98e3e1Schristos   return SIM_RC_FAIL;
2314e98e3e1Schristos }
232