1 /*--------------------------------------------------------------------*/ 2 /*--- Cachegrind: cache configuration. ---*/ 3 /*--- The architecture specific void VG_(configure_caches) are ---*/ 4 /*--- located in the cg-<architecture>.c files. ---*/ 5 /*--- cg-arch.c ---*/ 6 /*--------------------------------------------------------------------*/ 7 8 /* 9 This file is part of Cachegrind, a Valgrind tool for cache 10 profiling programs. 11 12 Copyright (C) 2011-2011 Nicholas Nethercote 13 njn (at) valgrind.org 14 15 This program is free software; you can redistribute it and/or 16 modify it under the terms of the GNU General Public License as 17 published by the Free Software Foundation; either version 2 of the 18 License, or (at your option) any later version. 19 20 This program is distributed in the hope that it will be useful, but 21 WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 General Public License for more details. 24 25 You should have received a copy of the GNU General Public License 26 along with this program; if not, write to the Free Software 27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 28 02111-1307, USA. 29 30 The GNU General Public License is contained in the file COPYING. 31 */ 32 33 #include "pub_tool_basics.h" 34 #include "pub_tool_libcassert.h" 35 #include "pub_tool_libcbase.h" 36 #include "pub_tool_libcprint.h" 37 #include "pub_tool_options.h" 38 39 #include "cg_arch.h" 40 41 // Checks cache config is ok. Returns NULL if ok, or a pointer to an error 42 // string otherwise. 43 static Char* check_cache(cache_t* cache) 44 { 45 // Simulator requires set count to be a power of two. 46 if ((cache->size % (cache->line_size * cache->assoc) != 0) || 47 (-1 == VG_(log2)(cache->size/cache->line_size/cache->assoc))) 48 { 49 return "Cache set count is not a power of two.\n"; 50 } 51 52 // Simulator requires line size to be a power of two. 53 if (-1 == VG_(log2)(cache->line_size)) { 54 return "Cache line size is not a power of two.\n"; 55 } 56 57 // Then check line size >= 16 -- any smaller and a single instruction could 58 // straddle three cache lines, which breaks a simulation assertion and is 59 // stupid anyway. 60 if (cache->line_size < MIN_LINE_SIZE) { 61 return "Cache line size is too small.\n"; 62 } 63 64 /* Then check cache size > line size (causes seg faults if not). */ 65 if (cache->size <= cache->line_size) { 66 return "Cache size <= line size.\n"; 67 } 68 69 /* Then check assoc <= (size / line size) (seg faults otherwise). */ 70 if (cache->assoc > (cache->size / cache->line_size)) { 71 return "Cache associativity > (size / line size).\n"; 72 } 73 74 return NULL; 75 } 76 77 78 static void parse_cache_opt ( cache_t* cache, Char* opt, Char* optval ) 79 { 80 Long i1, i2, i3; 81 Char* endptr; 82 Char* checkRes; 83 84 // Option argument looks like "65536,2,64". Extract them. 85 i1 = VG_(strtoll10)(optval, &endptr); if (*endptr != ',') goto bad; 86 i2 = VG_(strtoll10)(endptr+1, &endptr); if (*endptr != ',') goto bad; 87 i3 = VG_(strtoll10)(endptr+1, &endptr); if (*endptr != '\0') goto bad; 88 89 // Check for overflow. 90 cache->size = (Int)i1; 91 cache->assoc = (Int)i2; 92 cache->line_size = (Int)i3; 93 if (cache->size != i1) goto overflow; 94 if (cache->assoc != i2) goto overflow; 95 if (cache->line_size != i3) goto overflow; 96 97 checkRes = check_cache(cache); 98 if (checkRes) { 99 VG_(fmsg)("%s", checkRes); 100 goto bad; 101 } 102 103 return; 104 105 bad: 106 VG_(fmsg_bad_option)(opt, ""); 107 108 overflow: 109 VG_(fmsg_bad_option)(opt, 110 "One of the cache parameters was too large and overflowed.\n"); 111 } 112 113 114 Bool VG_(str_clo_cache_opt)(Char *arg, 115 cache_t* clo_I1c, 116 cache_t* clo_D1c, 117 cache_t* clo_LLc) 118 { 119 Char* tmp_str; 120 121 if VG_STR_CLO(arg, "--I1", tmp_str) { 122 parse_cache_opt(clo_I1c, arg, tmp_str); 123 return True; 124 } else if VG_STR_CLO(arg, "--D1", tmp_str) { 125 parse_cache_opt(clo_D1c, arg, tmp_str); 126 return True; 127 } else if (VG_STR_CLO(arg, "--L2", tmp_str) || // for backwards compatibility 128 VG_STR_CLO(arg, "--LL", tmp_str)) { 129 parse_cache_opt(clo_LLc, arg, tmp_str); 130 return True; 131 } else 132 return False; 133 } 134 135 static void umsg_cache_img(Char* desc, cache_t* c) 136 { 137 VG_(umsg)(" %s: %'d B, %d-way, %d B lines\n", desc, 138 c->size, c->assoc, c->line_size); 139 } 140 141 // Verifies if c is a valid cache. 142 // An invalid value causes an assert, unless clo_redefined is True. 143 static void check_cache_or_override(Char* desc, cache_t* c, Bool clo_redefined) 144 { 145 Char* checkRes; 146 147 checkRes = check_cache(c); 148 if (checkRes) { 149 VG_(umsg)("Auto-detected %s cache configuration not supported: %s", 150 desc, checkRes); 151 umsg_cache_img(desc, c); 152 if (!clo_redefined) { 153 VG_(umsg)("As it probably should be supported, please report a bug!\n"); 154 VG_(umsg)("Bypass this message by using option --%s=...\n", desc); 155 tl_assert(0); 156 } 157 } 158 } 159 160 void VG_(post_clo_init_configure_caches)(cache_t* I1c, 161 cache_t* D1c, 162 cache_t* LLc, 163 cache_t* clo_I1c, 164 cache_t* clo_D1c, 165 cache_t* clo_LLc) 166 { 167 #define DEFINED(L) (-1 != L->size || -1 != L->assoc || -1 != L->line_size) 168 169 // Count how many were defined on the command line. 170 Bool all_caches_clo_defined = 171 (DEFINED(clo_I1c) && 172 DEFINED(clo_D1c) && 173 DEFINED(clo_LLc)); 174 175 // Set the cache config (using auto-detection, if supported by the 176 // architecture). 177 VG_(configure_caches)( I1c, D1c, LLc, all_caches_clo_defined ); 178 179 // Check the default/auto-detected values. 180 // Allow the user to override invalid auto-detected caches 181 // with command line. 182 check_cache_or_override ("I1", I1c, DEFINED(clo_I1c)); 183 check_cache_or_override ("D1", D1c, DEFINED(clo_D1c)); 184 check_cache_or_override ("LL", LLc, DEFINED(clo_LLc)); 185 186 // Then replace with any defined on the command line. (Already checked in 187 // VG(parse_clo_cache_opt)().) 188 if (DEFINED(clo_I1c)) { *I1c = *clo_I1c; } 189 if (DEFINED(clo_D1c)) { *D1c = *clo_D1c; } 190 if (DEFINED(clo_LLc)) { *LLc = *clo_LLc; } 191 192 if (VG_(clo_verbosity) >= 2) { 193 VG_(umsg)("Cache configuration used:\n"); 194 umsg_cache_img ("I1", I1c); 195 umsg_cache_img ("D1", D1c); 196 umsg_cache_img ("LL", LLc); 197 } 198 #undef DEFINED 199 } 200 201 void VG_(print_cache_clo_opts)() 202 { 203 VG_(printf)( 204 " --I1=<size>,<assoc>,<line_size> set I1 cache manually\n" 205 " --D1=<size>,<assoc>,<line_size> set D1 cache manually\n" 206 " --LL=<size>,<assoc>,<line_size> set LL cache manually\n" 207 ); 208 } 209