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