base.cc revision 4666
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 "cpu/base.hh" 37#include "cpu/smt.hh" 38#include "mem/cache/base_cache.hh" 39#include "mem/cache/miss/mshr.hh" 40 41using namespace std; 42 43BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache) 44 : SimpleTimingPort(_name, _cache), cache(_cache), otherPort(NULL), 45 blocked(false), mustSendRetry(false) 46{ 47} 48 49 50BaseCache::BaseCache(const std::string &name, Params ¶ms) 51 : MemObject(name), 52 mshrQueue(params.numMSHRs, 4, MSHRQueue_MSHRs), 53 writeBuffer(params.numWriteBuffers, params.numMSHRs+1000, 54 MSHRQueue_WriteBuffer), 55 blkSize(params.blkSize), 56 hitLatency(params.hitLatency), 57 numTarget(params.numTargets), 58 blocked(0), 59 noTargetMSHR(NULL), 60 missCount(params.maxMisses), 61 drainEvent(NULL) 62{ 63} 64 65 66void 67BaseCache::CachePort::recvStatusChange(Port::Status status) 68{ 69 if (status == Port::RangeChange) { 70 otherPort->sendStatusChange(Port::RangeChange); 71 } 72} 73 74int 75BaseCache::CachePort::deviceBlockSize() 76{ 77 return cache->getBlockSize(); 78} 79 80 81void 82BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt) 83{ 84 checkFunctional(pkt); 85 if (pkt->result != Packet::Success) 86 sendFunctional(pkt); 87} 88 89 90bool 91BaseCache::CachePort::recvRetryCommon() 92{ 93 assert(waitingOnRetry); 94 waitingOnRetry = false; 95 return false; 96} 97 98 99void 100BaseCache::CachePort::setBlocked() 101{ 102 assert(!blocked); 103 DPRINTF(Cache, "Cache Blocking\n"); 104 blocked = true; 105 //Clear the retry flag 106 mustSendRetry = false; 107} 108 109void 110BaseCache::CachePort::clearBlocked() 111{ 112 assert(blocked); 113 DPRINTF(Cache, "Cache Unblocking\n"); 114 blocked = false; 115 if (mustSendRetry) 116 { 117 DPRINTF(Cache, "Cache Sending Retry\n"); 118 mustSendRetry = false; 119 SendRetryEvent *ev = new SendRetryEvent(this, true); 120 // @TODO: need to find a better time (next bus cycle?) 121 ev->schedule(curTick + 1); 122 } 123} 124 125 126void 127BaseCache::init() 128{ 129 if (!cpuSidePort || !memSidePort) 130 panic("Cache not hooked up on both sides\n"); 131 cpuSidePort->sendStatusChange(Port::RangeChange); 132} 133 134 135void 136BaseCache::regStats() 137{ 138 using namespace Stats; 139 140 // Hit statistics 141 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 142 MemCmd cmd(access_idx); 143 const string &cstr = cmd.toString(); 144 145 hits[access_idx] 146 .init(maxThreadsPerCPU) 147 .name(name() + "." + cstr + "_hits") 148 .desc("number of " + cstr + " hits") 149 .flags(total | nozero | nonan) 150 ; 151 } 152 153 demandHits 154 .name(name() + ".demand_hits") 155 .desc("number of demand (read+write) hits") 156 .flags(total) 157 ; 158 demandHits = hits[MemCmd::ReadReq] + hits[MemCmd::WriteReq]; 159 160 overallHits 161 .name(name() + ".overall_hits") 162 .desc("number of overall hits") 163 .flags(total) 164 ; 165 overallHits = demandHits + hits[MemCmd::SoftPFReq] + hits[MemCmd::HardPFReq] 166 + hits[MemCmd::Writeback]; 167 168 // Miss statistics 169 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 170 MemCmd cmd(access_idx); 171 const string &cstr = cmd.toString(); 172 173 misses[access_idx] 174 .init(maxThreadsPerCPU) 175 .name(name() + "." + cstr + "_misses") 176 .desc("number of " + cstr + " misses") 177 .flags(total | nozero | nonan) 178 ; 179 } 180 181 demandMisses 182 .name(name() + ".demand_misses") 183 .desc("number of demand (read+write) misses") 184 .flags(total) 185 ; 186 demandMisses = misses[MemCmd::ReadReq] + misses[MemCmd::WriteReq]; 187 188 overallMisses 189 .name(name() + ".overall_misses") 190 .desc("number of overall misses") 191 .flags(total) 192 ; 193 overallMisses = demandMisses + misses[MemCmd::SoftPFReq] + 194 misses[MemCmd::HardPFReq] + misses[MemCmd::Writeback]; 195 196 // Miss latency statistics 197 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 198 MemCmd cmd(access_idx); 199 const string &cstr = cmd.toString(); 200 201 missLatency[access_idx] 202 .init(maxThreadsPerCPU) 203 .name(name() + "." + cstr + "_miss_latency") 204 .desc("number of " + cstr + " miss cycles") 205 .flags(total | nozero | nonan) 206 ; 207 } 208 209 demandMissLatency 210 .name(name() + ".demand_miss_latency") 211 .desc("number of demand (read+write) miss cycles") 212 .flags(total) 213 ; 214 demandMissLatency = missLatency[MemCmd::ReadReq] + missLatency[MemCmd::WriteReq]; 215 216 overallMissLatency 217 .name(name() + ".overall_miss_latency") 218 .desc("number of overall miss cycles") 219 .flags(total) 220 ; 221 overallMissLatency = demandMissLatency + missLatency[MemCmd::SoftPFReq] + 222 missLatency[MemCmd::HardPFReq]; 223 224 // access formulas 225 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 226 MemCmd cmd(access_idx); 227 const string &cstr = cmd.toString(); 228 229 accesses[access_idx] 230 .name(name() + "." + cstr + "_accesses") 231 .desc("number of " + cstr + " accesses(hits+misses)") 232 .flags(total | nozero | nonan) 233 ; 234 235 accesses[access_idx] = hits[access_idx] + misses[access_idx]; 236 } 237 238 demandAccesses 239 .name(name() + ".demand_accesses") 240 .desc("number of demand (read+write) accesses") 241 .flags(total) 242 ; 243 demandAccesses = demandHits + demandMisses; 244 245 overallAccesses 246 .name(name() + ".overall_accesses") 247 .desc("number of overall (read+write) accesses") 248 .flags(total) 249 ; 250 overallAccesses = overallHits + overallMisses; 251 252 // miss rate formulas 253 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 254 MemCmd cmd(access_idx); 255 const string &cstr = cmd.toString(); 256 257 missRate[access_idx] 258 .name(name() + "." + cstr + "_miss_rate") 259 .desc("miss rate for " + cstr + " accesses") 260 .flags(total | nozero | nonan) 261 ; 262 263 missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 264 } 265 266 demandMissRate 267 .name(name() + ".demand_miss_rate") 268 .desc("miss rate for demand accesses") 269 .flags(total) 270 ; 271 demandMissRate = demandMisses / demandAccesses; 272 273 overallMissRate 274 .name(name() + ".overall_miss_rate") 275 .desc("miss rate for overall accesses") 276 .flags(total) 277 ; 278 overallMissRate = overallMisses / overallAccesses; 279 280 // miss latency formulas 281 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 282 MemCmd cmd(access_idx); 283 const string &cstr = cmd.toString(); 284 285 avgMissLatency[access_idx] 286 .name(name() + "." + cstr + "_avg_miss_latency") 287 .desc("average " + cstr + " miss latency") 288 .flags(total | nozero | nonan) 289 ; 290 291 avgMissLatency[access_idx] = 292 missLatency[access_idx] / misses[access_idx]; 293 } 294 295 demandAvgMissLatency 296 .name(name() + ".demand_avg_miss_latency") 297 .desc("average overall miss latency") 298 .flags(total) 299 ; 300 demandAvgMissLatency = demandMissLatency / demandMisses; 301 302 overallAvgMissLatency 303 .name(name() + ".overall_avg_miss_latency") 304 .desc("average overall miss latency") 305 .flags(total) 306 ; 307 overallAvgMissLatency = overallMissLatency / overallMisses; 308 309 blocked_cycles.init(NUM_BLOCKED_CAUSES); 310 blocked_cycles 311 .name(name() + ".blocked_cycles") 312 .desc("number of cycles access was blocked") 313 .subname(Blocked_NoMSHRs, "no_mshrs") 314 .subname(Blocked_NoTargets, "no_targets") 315 ; 316 317 318 blocked_causes.init(NUM_BLOCKED_CAUSES); 319 blocked_causes 320 .name(name() + ".blocked") 321 .desc("number of cycles access was blocked") 322 .subname(Blocked_NoMSHRs, "no_mshrs") 323 .subname(Blocked_NoTargets, "no_targets") 324 ; 325 326 avg_blocked 327 .name(name() + ".avg_blocked_cycles") 328 .desc("average number of cycles each access was blocked") 329 .subname(Blocked_NoMSHRs, "no_mshrs") 330 .subname(Blocked_NoTargets, "no_targets") 331 ; 332 333 avg_blocked = blocked_cycles / blocked_causes; 334 335 fastWrites 336 .name(name() + ".fast_writes") 337 .desc("number of fast writes performed") 338 ; 339 340 cacheCopies 341 .name(name() + ".cache_copies") 342 .desc("number of cache copies performed") 343 ; 344 345 writebacks 346 .init(maxThreadsPerCPU) 347 .name(name() + ".writebacks") 348 .desc("number of writebacks") 349 .flags(total) 350 ; 351 352 // MSHR statistics 353 // MSHR hit statistics 354 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 355 MemCmd cmd(access_idx); 356 const string &cstr = cmd.toString(); 357 358 mshr_hits[access_idx] 359 .init(maxThreadsPerCPU) 360 .name(name() + "." + cstr + "_mshr_hits") 361 .desc("number of " + cstr + " MSHR hits") 362 .flags(total | nozero | nonan) 363 ; 364 } 365 366 demandMshrHits 367 .name(name() + ".demand_mshr_hits") 368 .desc("number of demand (read+write) MSHR hits") 369 .flags(total) 370 ; 371 demandMshrHits = mshr_hits[MemCmd::ReadReq] + mshr_hits[MemCmd::WriteReq]; 372 373 overallMshrHits 374 .name(name() + ".overall_mshr_hits") 375 .desc("number of overall MSHR hits") 376 .flags(total) 377 ; 378 overallMshrHits = demandMshrHits + mshr_hits[MemCmd::SoftPFReq] + 379 mshr_hits[MemCmd::HardPFReq]; 380 381 // MSHR miss statistics 382 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 383 MemCmd cmd(access_idx); 384 const string &cstr = cmd.toString(); 385 386 mshr_misses[access_idx] 387 .init(maxThreadsPerCPU) 388 .name(name() + "." + cstr + "_mshr_misses") 389 .desc("number of " + cstr + " MSHR misses") 390 .flags(total | nozero | nonan) 391 ; 392 } 393 394 demandMshrMisses 395 .name(name() + ".demand_mshr_misses") 396 .desc("number of demand (read+write) MSHR misses") 397 .flags(total) 398 ; 399 demandMshrMisses = mshr_misses[MemCmd::ReadReq] + mshr_misses[MemCmd::WriteReq]; 400 401 overallMshrMisses 402 .name(name() + ".overall_mshr_misses") 403 .desc("number of overall MSHR misses") 404 .flags(total) 405 ; 406 overallMshrMisses = demandMshrMisses + mshr_misses[MemCmd::SoftPFReq] + 407 mshr_misses[MemCmd::HardPFReq]; 408 409 // MSHR miss latency statistics 410 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 411 MemCmd cmd(access_idx); 412 const string &cstr = cmd.toString(); 413 414 mshr_miss_latency[access_idx] 415 .init(maxThreadsPerCPU) 416 .name(name() + "." + cstr + "_mshr_miss_latency") 417 .desc("number of " + cstr + " MSHR miss cycles") 418 .flags(total | nozero | nonan) 419 ; 420 } 421 422 demandMshrMissLatency 423 .name(name() + ".demand_mshr_miss_latency") 424 .desc("number of demand (read+write) MSHR miss cycles") 425 .flags(total) 426 ; 427 demandMshrMissLatency = mshr_miss_latency[MemCmd::ReadReq] 428 + mshr_miss_latency[MemCmd::WriteReq]; 429 430 overallMshrMissLatency 431 .name(name() + ".overall_mshr_miss_latency") 432 .desc("number of overall MSHR miss cycles") 433 .flags(total) 434 ; 435 overallMshrMissLatency = demandMshrMissLatency + 436 mshr_miss_latency[MemCmd::SoftPFReq] + mshr_miss_latency[MemCmd::HardPFReq]; 437 438 // MSHR uncacheable statistics 439 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 440 MemCmd cmd(access_idx); 441 const string &cstr = cmd.toString(); 442 443 mshr_uncacheable[access_idx] 444 .init(maxThreadsPerCPU) 445 .name(name() + "." + cstr + "_mshr_uncacheable") 446 .desc("number of " + cstr + " MSHR uncacheable") 447 .flags(total | nozero | nonan) 448 ; 449 } 450 451 overallMshrUncacheable 452 .name(name() + ".overall_mshr_uncacheable_misses") 453 .desc("number of overall MSHR uncacheable misses") 454 .flags(total) 455 ; 456 overallMshrUncacheable = mshr_uncacheable[MemCmd::ReadReq] 457 + mshr_uncacheable[MemCmd::WriteReq] + mshr_uncacheable[MemCmd::SoftPFReq] 458 + mshr_uncacheable[MemCmd::HardPFReq]; 459 460 // MSHR miss latency statistics 461 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 462 MemCmd cmd(access_idx); 463 const string &cstr = cmd.toString(); 464 465 mshr_uncacheable_lat[access_idx] 466 .init(maxThreadsPerCPU) 467 .name(name() + "." + cstr + "_mshr_uncacheable_latency") 468 .desc("number of " + cstr + " MSHR uncacheable cycles") 469 .flags(total | nozero | nonan) 470 ; 471 } 472 473 overallMshrUncacheableLatency 474 .name(name() + ".overall_mshr_uncacheable_latency") 475 .desc("number of overall MSHR uncacheable cycles") 476 .flags(total) 477 ; 478 overallMshrUncacheableLatency = mshr_uncacheable_lat[MemCmd::ReadReq] 479 + mshr_uncacheable_lat[MemCmd::WriteReq] 480 + mshr_uncacheable_lat[MemCmd::SoftPFReq] 481 + mshr_uncacheable_lat[MemCmd::HardPFReq]; 482 483#if 0 484 // MSHR access formulas 485 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 486 MemCmd cmd(access_idx); 487 const string &cstr = cmd.toString(); 488 489 mshrAccesses[access_idx] 490 .name(name() + "." + cstr + "_mshr_accesses") 491 .desc("number of " + cstr + " mshr accesses(hits+misses)") 492 .flags(total | nozero | nonan) 493 ; 494 mshrAccesses[access_idx] = 495 mshr_hits[access_idx] + mshr_misses[access_idx] 496 + mshr_uncacheable[access_idx]; 497 } 498 499 demandMshrAccesses 500 .name(name() + ".demand_mshr_accesses") 501 .desc("number of demand (read+write) mshr accesses") 502 .flags(total | nozero | nonan) 503 ; 504 demandMshrAccesses = demandMshrHits + demandMshrMisses; 505 506 overallMshrAccesses 507 .name(name() + ".overall_mshr_accesses") 508 .desc("number of overall (read+write) mshr accesses") 509 .flags(total | nozero | nonan) 510 ; 511 overallMshrAccesses = overallMshrHits + overallMshrMisses 512 + overallMshrUncacheable; 513#endif 514 515 // MSHR miss rate formulas 516 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 517 MemCmd cmd(access_idx); 518 const string &cstr = cmd.toString(); 519 520 mshrMissRate[access_idx] 521 .name(name() + "." + cstr + "_mshr_miss_rate") 522 .desc("mshr miss rate for " + cstr + " accesses") 523 .flags(total | nozero | nonan) 524 ; 525 526 mshrMissRate[access_idx] = 527 mshr_misses[access_idx] / accesses[access_idx]; 528 } 529 530 demandMshrMissRate 531 .name(name() + ".demand_mshr_miss_rate") 532 .desc("mshr miss rate for demand accesses") 533 .flags(total) 534 ; 535 demandMshrMissRate = demandMshrMisses / demandAccesses; 536 537 overallMshrMissRate 538 .name(name() + ".overall_mshr_miss_rate") 539 .desc("mshr miss rate for overall accesses") 540 .flags(total) 541 ; 542 overallMshrMissRate = overallMshrMisses / overallAccesses; 543 544 // mshrMiss latency formulas 545 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 546 MemCmd cmd(access_idx); 547 const string &cstr = cmd.toString(); 548 549 avgMshrMissLatency[access_idx] 550 .name(name() + "." + cstr + "_avg_mshr_miss_latency") 551 .desc("average " + cstr + " mshr miss latency") 552 .flags(total | nozero | nonan) 553 ; 554 555 avgMshrMissLatency[access_idx] = 556 mshr_miss_latency[access_idx] / mshr_misses[access_idx]; 557 } 558 559 demandAvgMshrMissLatency 560 .name(name() + ".demand_avg_mshr_miss_latency") 561 .desc("average overall mshr miss latency") 562 .flags(total) 563 ; 564 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses; 565 566 overallAvgMshrMissLatency 567 .name(name() + ".overall_avg_mshr_miss_latency") 568 .desc("average overall mshr miss latency") 569 .flags(total) 570 ; 571 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses; 572 573 // mshrUncacheable latency formulas 574 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 575 MemCmd cmd(access_idx); 576 const string &cstr = cmd.toString(); 577 578 avgMshrUncacheableLatency[access_idx] 579 .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency") 580 .desc("average " + cstr + " mshr uncacheable latency") 581 .flags(total | nozero | nonan) 582 ; 583 584 avgMshrUncacheableLatency[access_idx] = 585 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx]; 586 } 587 588 overallAvgMshrUncacheableLatency 589 .name(name() + ".overall_avg_mshr_uncacheable_latency") 590 .desc("average overall mshr uncacheable latency") 591 .flags(total) 592 ; 593 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable; 594 595 mshr_cap_events 596 .init(maxThreadsPerCPU) 597 .name(name() + ".mshr_cap_events") 598 .desc("number of times MSHR cap was activated") 599 .flags(total) 600 ; 601 602 //software prefetching stats 603 soft_prefetch_mshr_full 604 .init(maxThreadsPerCPU) 605 .name(name() + ".soft_prefetch_mshr_full") 606 .desc("number of mshr full events for SW prefetching instrutions") 607 .flags(total) 608 ; 609 610 mshr_no_allocate_misses 611 .name(name() +".no_allocate_misses") 612 .desc("Number of misses that were no-allocate") 613 ; 614 615} 616 617unsigned int 618BaseCache::drain(Event *de) 619{ 620 int count = memSidePort->drain(de) + cpuSidePort->drain(de); 621 622 // Set status 623 if (count != 0) { 624 drainEvent = de; 625 626 changeState(SimObject::Draining); 627 return count; 628 } 629 630 changeState(SimObject::Drained); 631 return 0; 632} 633