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