base.cc revision 2810
1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Erik Hallnor 29 */ 30 31/** 32 * @file 33 * Definition of BaseCache functions. 34 */ 35 36#include "mem/cache/base_cache.hh" 37#include "cpu/smt.hh" 38#include "cpu/base.hh" 39 40using namespace std; 41 42BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, 43 bool _isCpuSide) 44 : Port(_name), cache(_cache), isCpuSide(_isCpuSide) 45{ 46 blocked = false; 47 //Start ports at null if more than one is created we should panic 48 cpuSidePort = NULL; 49 memSidePort = NULL; 50} 51 52bool 53BaseCache::CachePort::recvStatusChange(Port::Status status) 54{ 55 cache->recvStatusChange(status, isCpuSide); 56} 57 58void 59BaseCache::CachePort::getDeviceAddressRanges(AddrRangeList &resp, 60 AddrRangeList &snoop) 61{ 62 cache->getAddressRanges(resp, snoop); 63} 64 65int 66BaseCache::CachePort::deviceBlockSize() 67{ 68 return cache->getBlockSize(); 69} 70 71bool 72BaseCache::CachePort::recvTiming(Packet *pkt) 73{ 74 return cache->doTimingAccess(pkt, this, isCpuSide); 75} 76 77Tick 78BaseCache::CachePort::recvAtomic(Packet *pkt) 79{ 80 return cache->doAtomicAccess(pkt, isCpuSide); 81} 82 83void 84BaseCache::CachePort::recvFunctional(Packet *pkt) 85{ 86 cache->doFunctionalAccess(pkt, isCpuSide); 87} 88 89void 90BaseCache::CachePort::setBlocked() 91{ 92 blocked = true; 93} 94 95void 96BaseCache::CachePort::clearBlocked() 97{ 98 blocked = false; 99} 100 101Port* 102BaseCache::getPort(const std::string &if_name) 103{ 104 if(if_name == "cpu_side") 105 { 106 if(cpuSidePort != NULL) 107 panic("Already have a cpu side for this cache\n"); 108 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 109 return cpuSidePort; 110 } 111 else if(if_name == "mem_side") 112 { 113 if(memSidePort != NULL) 114 panic("Already have a mem side for this cache\n"); 115 memSidePort = new CachePort(name() + "-mem_side_port", this, false); 116 return memSidePort; 117 } 118 else panic("Port name %s unrecognized\n", if_name); 119} 120 121void 122BaseCache::regStats() 123{ 124 using namespace Stats; 125 126 // Hit statistics 127 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 128 Packet::Command cmd = (Packet::CommandEnum)access_idx; 129 const string &cstr = cmd.toString(); 130 131 hits[access_idx] 132 .init(maxThreadsPerCPU) 133 .name(name() + "." + cstr + "_hits") 134 .desc("number of " + cstr + " hits") 135 .flags(total | nozero | nonan) 136 ; 137 } 138 139 demandHits 140 .name(name() + ".demand_hits") 141 .desc("number of demand (read+write) hits") 142 .flags(total) 143 ; 144 demandHits = hits[Read] + hits[Write]; 145 146 overallHits 147 .name(name() + ".overall_hits") 148 .desc("number of overall hits") 149 .flags(total) 150 ; 151 overallHits = demandHits + hits[Soft_Prefetch] + hits[Hard_Prefetch] 152 + hits[Writeback]; 153 154 // Miss statistics 155 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 156 Packet::Command cmd = (Packet::CommandEnum)access_idx; 157 const string &cstr = cmd.toString(); 158 159 misses[access_idx] 160 .init(maxThreadsPerCPU) 161 .name(name() + "." + cstr + "_misses") 162 .desc("number of " + cstr + " misses") 163 .flags(total | nozero | nonan) 164 ; 165 } 166 167 demandMisses 168 .name(name() + ".demand_misses") 169 .desc("number of demand (read+write) misses") 170 .flags(total) 171 ; 172 demandMisses = misses[Read] + misses[Write]; 173 174 overallMisses 175 .name(name() + ".overall_misses") 176 .desc("number of overall misses") 177 .flags(total) 178 ; 179 overallMisses = demandMisses + misses[Soft_Prefetch] + 180 misses[Hard_Prefetch] + misses[Writeback]; 181 182 // Miss latency statistics 183 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 184 Packet::Command cmd = (Packet::CommandEnum)access_idx; 185 const string &cstr = cmd.toString(); 186 187 missLatency[access_idx] 188 .init(maxThreadsPerCPU) 189 .name(name() + "." + cstr + "_miss_latency") 190 .desc("number of " + cstr + " miss cycles") 191 .flags(total | nozero | nonan) 192 ; 193 } 194 195 demandMissLatency 196 .name(name() + ".demand_miss_latency") 197 .desc("number of demand (read+write) miss cycles") 198 .flags(total) 199 ; 200 demandMissLatency = missLatency[Read] + missLatency[Write]; 201 202 overallMissLatency 203 .name(name() + ".overall_miss_latency") 204 .desc("number of overall miss cycles") 205 .flags(total) 206 ; 207 overallMissLatency = demandMissLatency + missLatency[Soft_Prefetch] + 208 missLatency[Hard_Prefetch]; 209 210 // access formulas 211 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 212 Packet::Command cmd = (Packet::CommandEnum)access_idx; 213 const string &cstr = cmd.toString(); 214 215 accesses[access_idx] 216 .name(name() + "." + cstr + "_accesses") 217 .desc("number of " + cstr + " accesses(hits+misses)") 218 .flags(total | nozero | nonan) 219 ; 220 221 accesses[access_idx] = hits[access_idx] + misses[access_idx]; 222 } 223 224 demandAccesses 225 .name(name() + ".demand_accesses") 226 .desc("number of demand (read+write) accesses") 227 .flags(total) 228 ; 229 demandAccesses = demandHits + demandMisses; 230 231 overallAccesses 232 .name(name() + ".overall_accesses") 233 .desc("number of overall (read+write) accesses") 234 .flags(total) 235 ; 236 overallAccesses = overallHits + overallMisses; 237 238 // miss rate formulas 239 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 240 Packet::Command cmd = (Packet::CommandEnum)access_idx; 241 const string &cstr = cmd.toString(); 242 243 missRate[access_idx] 244 .name(name() + "." + cstr + "_miss_rate") 245 .desc("miss rate for " + cstr + " accesses") 246 .flags(total | nozero | nonan) 247 ; 248 249 missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 250 } 251 252 demandMissRate 253 .name(name() + ".demand_miss_rate") 254 .desc("miss rate for demand accesses") 255 .flags(total) 256 ; 257 demandMissRate = demandMisses / demandAccesses; 258 259 overallMissRate 260 .name(name() + ".overall_miss_rate") 261 .desc("miss rate for overall accesses") 262 .flags(total) 263 ; 264 overallMissRate = overallMisses / overallAccesses; 265 266 // miss latency formulas 267 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 268 Packet::Command cmd = (Packet::CommandEnum)access_idx; 269 const string &cstr = cmd.toString(); 270 271 avgMissLatency[access_idx] 272 .name(name() + "." + cstr + "_avg_miss_latency") 273 .desc("average " + cstr + " miss latency") 274 .flags(total | nozero | nonan) 275 ; 276 277 avgMissLatency[access_idx] = 278 missLatency[access_idx] / misses[access_idx]; 279 } 280 281 demandAvgMissLatency 282 .name(name() + ".demand_avg_miss_latency") 283 .desc("average overall miss latency") 284 .flags(total) 285 ; 286 demandAvgMissLatency = demandMissLatency / demandMisses; 287 288 overallAvgMissLatency 289 .name(name() + ".overall_avg_miss_latency") 290 .desc("average overall miss latency") 291 .flags(total) 292 ; 293 overallAvgMissLatency = overallMissLatency / overallMisses; 294 295 blocked_cycles.init(NUM_BLOCKED_CAUSES); 296 blocked_cycles 297 .name(name() + ".blocked_cycles") 298 .desc("number of cycles access was blocked") 299 .subname(Blocked_NoMSHRs, "no_mshrs") 300 .subname(Blocked_NoTargets, "no_targets") 301 ; 302 303 304 blocked_causes.init(NUM_BLOCKED_CAUSES); 305 blocked_causes 306 .name(name() + ".blocked") 307 .desc("number of cycles access was blocked") 308 .subname(Blocked_NoMSHRs, "no_mshrs") 309 .subname(Blocked_NoTargets, "no_targets") 310 ; 311 312 avg_blocked 313 .name(name() + ".avg_blocked_cycles") 314 .desc("average number of cycles each access was blocked") 315 .subname(Blocked_NoMSHRs, "no_mshrs") 316 .subname(Blocked_NoTargets, "no_targets") 317 ; 318 319 avg_blocked = blocked_cycles / blocked_causes; 320 321 fastWrites 322 .name(name() + ".fast_writes") 323 .desc("number of fast writes performed") 324 ; 325 326 cacheCopies 327 .name(name() + ".cache_copies") 328 .desc("number of cache copies performed") 329 ; 330} 331