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