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