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