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