| /* FRV simulator memory option handling. |
| Copyright (C) 1999-2024 Free Software Foundation, Inc. |
| Contributed by Red Hat. |
| |
| This file is part of GDB, the GNU debugger. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| |
| /* This must come before any other includes. */ |
| #include "defs.h" |
| |
| #define WANT_CPU frvbf |
| #define WANT_CPU_FRVBF |
| |
| #include "sim-main.h" |
| #include "sim-assert.h" |
| #include "sim-options.h" |
| |
| #include <string.h> |
| #include <stdlib.h> |
| |
| /* FRV specific command line options. */ |
| |
| enum { |
| OPTION_FRV_DATA_CACHE = OPTION_START, |
| OPTION_FRV_INSN_CACHE, |
| OPTION_FRV_PROFILE_CACHE, |
| OPTION_FRV_PROFILE_PARALLEL, |
| OPTION_FRV_TIMER, |
| OPTION_FRV_MEMORY_LATENCY |
| }; |
| |
| static DECLARE_OPTION_HANDLER (frv_option_handler); |
| |
| const OPTION frv_options[] = |
| { |
| { {"profile", optional_argument, NULL, 'p'}, |
| 'p', "on|off", "Perform profiling", |
| frv_option_handler }, |
| { {"data-cache", optional_argument, NULL, OPTION_FRV_DATA_CACHE }, |
| '\0', "WAYS[,SETS[,LINESIZE]]", "Enable data cache", |
| frv_option_handler }, |
| { {"insn-cache", optional_argument, NULL, OPTION_FRV_INSN_CACHE }, |
| '\0', "WAYS[,SETS[,LINESIZE]]", "Enable instruction cache", |
| frv_option_handler }, |
| { {"profile-cache", optional_argument, NULL, OPTION_FRV_PROFILE_CACHE }, |
| '\0', "on|off", "Profile caches", |
| frv_option_handler }, |
| { {"profile-parallel", optional_argument, NULL, OPTION_FRV_PROFILE_PARALLEL }, |
| '\0', "on|off", "Profile parallelism", |
| frv_option_handler }, |
| { {"timer", required_argument, NULL, OPTION_FRV_TIMER }, |
| '\0', "CYCLES,INTERRUPT", "Set Interrupt Timer", |
| frv_option_handler }, |
| { {"memory-latency", required_argument, NULL, OPTION_FRV_MEMORY_LATENCY }, |
| '\0', "CYCLES", "Set Latency of memory", |
| frv_option_handler }, |
| { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } |
| }; |
| |
| static char * |
| parse_size (char *chp, address_word *nr_bytes) |
| { |
| /* <nr_bytes> */ |
| *nr_bytes = strtoul (chp, &chp, 0); |
| return chp; |
| } |
| |
| static address_word |
| check_pow2 (address_word value, char *argname, char *optname, SIM_DESC sd) |
| { |
| if ((value & (value - 1)) != 0) |
| { |
| sim_io_eprintf (sd, "%s argument to %s must be a power of 2\n", |
| argname, optname); |
| return 0; /* will enable default value. */ |
| } |
| |
| return value; |
| } |
| |
| static void |
| parse_cache_option (SIM_DESC sd, char *arg, char *cache_name, int is_data_cache) |
| { |
| int i; |
| address_word ways = 0, sets = 0, linesize = 0; |
| if (arg != NULL) |
| { |
| char *chp = arg; |
| /* parse the arguments */ |
| chp = parse_size (chp, &ways); |
| ways = check_pow2 (ways, "WAYS", cache_name, sd); |
| if (*chp == ',') |
| { |
| chp = parse_size (chp + 1, &sets); |
| sets = check_pow2 (sets, "SETS", cache_name, sd); |
| if (*chp == ',') |
| { |
| chp = parse_size (chp + 1, &linesize); |
| linesize = check_pow2 (linesize, "LINESIZE", cache_name, sd); |
| } |
| } |
| } |
| for (i = 0; i < MAX_NR_PROCESSORS; ++i) |
| { |
| SIM_CPU *current_cpu = STATE_CPU (sd, i); |
| FRV_CACHE *cache = is_data_cache ? CPU_DATA_CACHE (current_cpu) |
| : CPU_INSN_CACHE (current_cpu); |
| cache->ways = ways; |
| cache->sets = sets; |
| cache->line_size = linesize; |
| frv_cache_init (current_cpu, cache); |
| } |
| } |
| |
| static SIM_RC |
| frv_option_handler (SIM_DESC sd, sim_cpu *current_cpu, int opt, |
| char *arg, int is_command) |
| { |
| switch (opt) |
| { |
| case 'p' : |
| if (! WITH_PROFILE) |
| sim_io_eprintf (sd, "Profiling not compiled in, `-p' ignored\n"); |
| else |
| { |
| unsigned mask = PROFILE_USEFUL_MASK; |
| if (WITH_PROFILE_CACHE_P) |
| mask |= (1 << PROFILE_CACHE_IDX); |
| if (WITH_PROFILE_PARALLEL_P) |
| mask |= (1 << PROFILE_PARALLEL_IDX); |
| return set_profile_option_mask (sd, "profile", mask, arg); |
| } |
| break; |
| |
| case OPTION_FRV_DATA_CACHE: |
| parse_cache_option (sd, arg, "data_cache", 1/*is_data_cache*/); |
| return SIM_RC_OK; |
| |
| case OPTION_FRV_INSN_CACHE: |
| parse_cache_option (sd, arg, "insn_cache", 0/*is_data_cache*/); |
| return SIM_RC_OK; |
| |
| case OPTION_FRV_PROFILE_CACHE: |
| if (WITH_PROFILE_CACHE_P) |
| return sim_profile_set_option (sd, "-cache", PROFILE_CACHE_IDX, arg); |
| else |
| sim_io_eprintf (sd, "Cache profiling not compiled in, `--profile-cache' ignored\n"); |
| break; |
| |
| case OPTION_FRV_PROFILE_PARALLEL: |
| if (WITH_PROFILE_PARALLEL_P) |
| { |
| unsigned mask |
| = (1 << PROFILE_MODEL_IDX) | (1 << PROFILE_PARALLEL_IDX); |
| return set_profile_option_mask (sd, "-parallel", mask, arg); |
| } |
| else |
| sim_io_eprintf (sd, "Parallel profiling not compiled in, `--profile-parallel' ignored\n"); |
| break; |
| |
| case OPTION_FRV_TIMER: |
| { |
| char *chp = arg; |
| address_word cycles, interrupt; |
| chp = parse_size (chp, &cycles); |
| if (chp == arg) |
| { |
| sim_io_eprintf (sd, "Cycle count required for --timer\n"); |
| return SIM_RC_FAIL; |
| } |
| if (*chp != ',') |
| { |
| sim_io_eprintf (sd, "Interrupt number required for --timer\n"); |
| return SIM_RC_FAIL; |
| } |
| chp = parse_size (chp + 1, &interrupt); |
| if (interrupt < 1 || interrupt > 15) |
| { |
| sim_io_eprintf (sd, "Interrupt number for --timer must be greater than 0 and less that 16\n"); |
| return SIM_RC_FAIL; |
| } |
| frv_interrupt_state.timer.enabled = 1; |
| frv_interrupt_state.timer.value = cycles; |
| frv_interrupt_state.timer.current = 0; |
| frv_interrupt_state.timer.interrupt = |
| FRV_INTERRUPT_LEVEL_1 + interrupt - 1; |
| } |
| return SIM_RC_OK; |
| |
| case OPTION_FRV_MEMORY_LATENCY: |
| { |
| int i; |
| char *chp = arg; |
| address_word cycles; |
| chp = parse_size (chp, &cycles); |
| if (chp == arg) |
| { |
| sim_io_eprintf (sd, "Cycle count required for --memory-latency\n"); |
| return SIM_RC_FAIL; |
| } |
| for (i = 0; i < MAX_NR_PROCESSORS; ++i) |
| { |
| SIM_CPU *cpu = STATE_CPU (sd, i); |
| FRV_CACHE *insn_cache = CPU_INSN_CACHE (cpu); |
| FRV_CACHE *data_cache = CPU_DATA_CACHE (cpu); |
| insn_cache->memory_latency = cycles; |
| data_cache->memory_latency = cycles; |
| } |
| } |
| return SIM_RC_OK; |
| |
| default: |
| sim_io_eprintf (sd, "Unknown FRV option %d\n", opt); |
| return SIM_RC_FAIL; |
| |
| } |
| |
| return SIM_RC_FAIL; |
| } |