base.cc revision 2897
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 52void 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, isCpuSide); 63} 64 65int 66BaseCache::CachePort::deviceBlockSize() 67{ 68 return cache->getBlockSize(); 69} 70 71bool 72BaseCache::CachePort::recvTiming(Packet *pkt) 73{ 74 if (blocked) 75 { 76 mustSendRetry = true; 77 return false; 78 } 79 return cache->doTimingAccess(pkt, this, isCpuSide); 80} 81 82Tick 83BaseCache::CachePort::recvAtomic(Packet *pkt) 84{ 85 return cache->doAtomicAccess(pkt, isCpuSide); 86} 87 88void 89BaseCache::CachePort::recvFunctional(Packet *pkt) 90{ 91 cache->doFunctionalAccess(pkt, isCpuSide); 92} 93 94void 95BaseCache::CachePort::setBlocked() 96{ 97 blocked = true; 98} 99 100void 101BaseCache::CachePort::clearBlocked() 102{ 103 if (mustSendRetry) 104 { 105 mustSendRetry = false; 106 sendRetry(); 107 } 108 blocked = false; 109} 110 111BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort) 112 : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort) 113{ 114 this->setFlags(AutoDelete); 115 pkt = NULL; 116} 117 118BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, Packet *_pkt) 119 : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort), pkt(_pkt) 120{ 121 this->setFlags(AutoDelete); 122} 123 124void 125BaseCache::CacheEvent::process() 126{ 127 if (!pkt) 128 { 129 if (!cachePort->isCpuSide) 130 { 131 pkt = cachePort->cache->getPacket(); 132 bool success = cachePort->sendTiming(pkt); 133 DPRINTF(Cache, "Address %x was %s in sending the timing request\n", 134 pkt->getAddr(), success ? "succesful" : "unsuccesful"); 135 cachePort->cache->sendResult(pkt, success); 136 if (success && cachePort->cache->doMasterRequest()) 137 { 138 //Still more to issue, rerequest in 1 cycle 139 pkt = NULL; 140 this->schedule(curTick+1); 141 } 142 } 143 else 144 { 145 pkt = cachePort->cache->getCoherencePacket(); 146 cachePort->sendTiming(pkt); 147 } 148 return; 149 } 150 //Know the packet to send, no need to mark in service (must succed) 151 bool success = cachePort->sendTiming(pkt); 152 assert(success); 153} 154 155const char * 156BaseCache::CacheEvent::description() 157{ 158 return "timing event\n"; 159} 160 161Port* 162BaseCache::getPort(const std::string &if_name, int idx) 163{ 164 if (if_name == "") 165 { 166 if(cpuSidePort == NULL) 167 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 168 return cpuSidePort; 169 } 170 else if (if_name == "functional") 171 { 172 if(cpuSidePort == NULL) 173 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 174 return cpuSidePort; 175 } 176 else if (if_name == "cpu_side") 177 { 178 if(cpuSidePort == NULL) 179 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 180 return cpuSidePort; 181 } 182 else if (if_name == "mem_side") 183 { 184 if (memSidePort != NULL) 185 panic("Already have a mem side for this cache\n"); 186 memSidePort = new CachePort(name() + "-mem_side_port", this, false); 187 return memSidePort; 188 } 189 else panic("Port name %s unrecognized\n", if_name); 190} 191 192void 193BaseCache::init() 194{ 195 if (!cpuSidePort || !memSidePort) 196 panic("Cache not hooked up on both sides\n"); 197 cpuSidePort->sendStatusChange(Port::RangeChange); 198} 199 200void 201BaseCache::regStats() 202{ 203 Request temp_req((Addr) NULL, 4, 0); 204 Packet::Command temp_cmd = Packet::ReadReq; 205 Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary 206 temp_pkt.allocate(); //Temp allocate, all need data 207 208 using namespace Stats; 209 210 // Hit statistics 211 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 212 Packet::Command cmd = (Packet::Command)access_idx; 213 const string &cstr = temp_pkt.cmdIdxToString(cmd); 214 215 hits[access_idx] 216 .init(maxThreadsPerCPU) 217 .name(name() + "." + cstr + "_hits") 218 .desc("number of " + cstr + " hits") 219 .flags(total | nozero | nonan) 220 ; 221 } 222 223 demandHits 224 .name(name() + ".demand_hits") 225 .desc("number of demand (read+write) hits") 226 .flags(total) 227 ; 228 demandHits = hits[Packet::ReadReq] + hits[Packet::WriteReq]; 229 230 overallHits 231 .name(name() + ".overall_hits") 232 .desc("number of overall hits") 233 .flags(total) 234 ; 235 overallHits = demandHits + hits[Packet::SoftPFReq] + hits[Packet::HardPFReq] 236 + hits[Packet::Writeback]; 237 238 // Miss statistics 239 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 240 Packet::Command cmd = (Packet::Command)access_idx; 241 const string &cstr = temp_pkt.cmdIdxToString(cmd); 242 243 misses[access_idx] 244 .init(maxThreadsPerCPU) 245 .name(name() + "." + cstr + "_misses") 246 .desc("number of " + cstr + " misses") 247 .flags(total | nozero | nonan) 248 ; 249 } 250 251 demandMisses 252 .name(name() + ".demand_misses") 253 .desc("number of demand (read+write) misses") 254 .flags(total) 255 ; 256 demandMisses = misses[Packet::ReadReq] + misses[Packet::WriteReq]; 257 258 overallMisses 259 .name(name() + ".overall_misses") 260 .desc("number of overall misses") 261 .flags(total) 262 ; 263 overallMisses = demandMisses + misses[Packet::SoftPFReq] + 264 misses[Packet::HardPFReq] + misses[Packet::Writeback]; 265 266 // Miss latency statistics 267 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 268 Packet::Command cmd = (Packet::Command)access_idx; 269 const string &cstr = temp_pkt.cmdIdxToString(cmd); 270 271 missLatency[access_idx] 272 .init(maxThreadsPerCPU) 273 .name(name() + "." + cstr + "_miss_latency") 274 .desc("number of " + cstr + " miss cycles") 275 .flags(total | nozero | nonan) 276 ; 277 } 278 279 demandMissLatency 280 .name(name() + ".demand_miss_latency") 281 .desc("number of demand (read+write) miss cycles") 282 .flags(total) 283 ; 284 demandMissLatency = missLatency[Packet::ReadReq] + missLatency[Packet::WriteReq]; 285 286 overallMissLatency 287 .name(name() + ".overall_miss_latency") 288 .desc("number of overall miss cycles") 289 .flags(total) 290 ; 291 overallMissLatency = demandMissLatency + missLatency[Packet::SoftPFReq] + 292 missLatency[Packet::HardPFReq]; 293 294 // access formulas 295 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 296 Packet::Command cmd = (Packet::Command)access_idx; 297 const string &cstr = temp_pkt.cmdIdxToString(cmd); 298 299 accesses[access_idx] 300 .name(name() + "." + cstr + "_accesses") 301 .desc("number of " + cstr + " accesses(hits+misses)") 302 .flags(total | nozero | nonan) 303 ; 304 305 accesses[access_idx] = hits[access_idx] + misses[access_idx]; 306 } 307 308 demandAccesses 309 .name(name() + ".demand_accesses") 310 .desc("number of demand (read+write) accesses") 311 .flags(total) 312 ; 313 demandAccesses = demandHits + demandMisses; 314 315 overallAccesses 316 .name(name() + ".overall_accesses") 317 .desc("number of overall (read+write) accesses") 318 .flags(total) 319 ; 320 overallAccesses = overallHits + overallMisses; 321 322 // miss rate formulas 323 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 324 Packet::Command cmd = (Packet::Command)access_idx; 325 const string &cstr = temp_pkt.cmdIdxToString(cmd); 326 327 missRate[access_idx] 328 .name(name() + "." + cstr + "_miss_rate") 329 .desc("miss rate for " + cstr + " accesses") 330 .flags(total | nozero | nonan) 331 ; 332 333 missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 334 } 335 336 demandMissRate 337 .name(name() + ".demand_miss_rate") 338 .desc("miss rate for demand accesses") 339 .flags(total) 340 ; 341 demandMissRate = demandMisses / demandAccesses; 342 343 overallMissRate 344 .name(name() + ".overall_miss_rate") 345 .desc("miss rate for overall accesses") 346 .flags(total) 347 ; 348 overallMissRate = overallMisses / overallAccesses; 349 350 // miss latency formulas 351 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 352 Packet::Command cmd = (Packet::Command)access_idx; 353 const string &cstr = temp_pkt.cmdIdxToString(cmd); 354 355 avgMissLatency[access_idx] 356 .name(name() + "." + cstr + "_avg_miss_latency") 357 .desc("average " + cstr + " miss latency") 358 .flags(total | nozero | nonan) 359 ; 360 361 avgMissLatency[access_idx] = 362 missLatency[access_idx] / misses[access_idx]; 363 } 364 365 demandAvgMissLatency 366 .name(name() + ".demand_avg_miss_latency") 367 .desc("average overall miss latency") 368 .flags(total) 369 ; 370 demandAvgMissLatency = demandMissLatency / demandMisses; 371 372 overallAvgMissLatency 373 .name(name() + ".overall_avg_miss_latency") 374 .desc("average overall miss latency") 375 .flags(total) 376 ; 377 overallAvgMissLatency = overallMissLatency / overallMisses; 378 379 blocked_cycles.init(NUM_BLOCKED_CAUSES); 380 blocked_cycles 381 .name(name() + ".blocked_cycles") 382 .desc("number of cycles access was blocked") 383 .subname(Blocked_NoMSHRs, "no_mshrs") 384 .subname(Blocked_NoTargets, "no_targets") 385 ; 386 387 388 blocked_causes.init(NUM_BLOCKED_CAUSES); 389 blocked_causes 390 .name(name() + ".blocked") 391 .desc("number of cycles access was blocked") 392 .subname(Blocked_NoMSHRs, "no_mshrs") 393 .subname(Blocked_NoTargets, "no_targets") 394 ; 395 396 avg_blocked 397 .name(name() + ".avg_blocked_cycles") 398 .desc("average number of cycles each access was blocked") 399 .subname(Blocked_NoMSHRs, "no_mshrs") 400 .subname(Blocked_NoTargets, "no_targets") 401 ; 402 403 avg_blocked = blocked_cycles / blocked_causes; 404 405 fastWrites 406 .name(name() + ".fast_writes") 407 .desc("number of fast writes performed") 408 ; 409 410 cacheCopies 411 .name(name() + ".cache_copies") 412 .desc("number of cache copies performed") 413 ; 414 415} 416