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