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