base.cc revision 4628
1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Erik Hallnor 29 */ 30 31/** 32 * @file 33 * Definition of BaseCache functions. 34 */ 35 36#include "cpu/base.hh" 37#include "cpu/smt.hh" 38#include "mem/cache/base_cache.hh" 39#include "mem/cache/miss/mshr.hh" 40 41using namespace std; 42 43BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache) 44 : SimpleTimingPort(_name, _cache), cache(_cache), otherPort(NULL), 45 blocked(false), waitingOnRetry(false), mustSendRetry(false), 46 requestCauses(0) 47{ 48} 49 50 51BaseCache::BaseCache(const std::string &name, Params ¶ms) 52 : MemObject(name), 53 mshrQueue(params.numMSHRs, 4, MSHRQueue_MSHRs), 54 writeBuffer(params.numWriteBuffers, params.numMSHRs+1000, 55 MSHRQueue_WriteBuffer), 56 blkSize(params.blkSize), 57 numTarget(params.numTargets), 58 blocked(0), 59 noTargetMSHR(NULL), 60 missCount(params.maxMisses), 61 drainEvent(NULL) 62{ 63} 64 65 66void 67BaseCache::CachePort::recvStatusChange(Port::Status status) 68{ 69 if (status == Port::RangeChange) { 70 otherPort->sendStatusChange(Port::RangeChange); 71 } 72} 73 74int 75BaseCache::CachePort::deviceBlockSize() 76{ 77 return cache->getBlockSize(); 78} 79 80 81void 82BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt) 83{ 84 checkFunctional(pkt); 85 if (pkt->result != Packet::Success) 86 sendFunctional(pkt); 87} 88 89 90bool 91BaseCache::CachePort::recvRetryCommon() 92{ 93 assert(waitingOnRetry); 94 waitingOnRetry = false; 95 return false; 96} 97 98 99void 100BaseCache::CachePort::setBlocked() 101{ 102 assert(!blocked); 103 DPRINTF(Cache, "Cache Blocking\n"); 104 blocked = true; 105 //Clear the retry flag 106 mustSendRetry = false; 107} 108 109void 110BaseCache::CachePort::clearBlocked() 111{ 112 assert(blocked); 113 DPRINTF(Cache, "Cache Unblocking\n"); 114 blocked = false; 115 if (mustSendRetry) 116 { 117 DPRINTF(Cache, "Cache Sending Retry\n"); 118 mustSendRetry = false; 119 sendRetry(); 120 } 121} 122 123 124void 125BaseCache::init() 126{ 127 if (!cpuSidePort || !memSidePort) 128 panic("Cache not hooked up on both sides\n"); 129 cpuSidePort->sendStatusChange(Port::RangeChange); 130} 131 132 133void 134BaseCache::regStats() 135{ 136 using namespace Stats; 137 138 // Hit statistics 139 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 140 MemCmd cmd(access_idx); 141 const string &cstr = cmd.toString(); 142 143 hits[access_idx] 144 .init(maxThreadsPerCPU) 145 .name(name() + "." + cstr + "_hits") 146 .desc("number of " + cstr + " hits") 147 .flags(total | nozero | nonan) 148 ; 149 } 150 151 demandHits 152 .name(name() + ".demand_hits") 153 .desc("number of demand (read+write) hits") 154 .flags(total) 155 ; 156 demandHits = hits[MemCmd::ReadReq] + hits[MemCmd::WriteReq]; 157 158 overallHits 159 .name(name() + ".overall_hits") 160 .desc("number of overall hits") 161 .flags(total) 162 ; 163 overallHits = demandHits + hits[MemCmd::SoftPFReq] + hits[MemCmd::HardPFReq] 164 + hits[MemCmd::Writeback]; 165 166 // Miss statistics 167 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 168 MemCmd cmd(access_idx); 169 const string &cstr = cmd.toString(); 170 171 misses[access_idx] 172 .init(maxThreadsPerCPU) 173 .name(name() + "." + cstr + "_misses") 174 .desc("number of " + cstr + " misses") 175 .flags(total | nozero | nonan) 176 ; 177 } 178 179 demandMisses 180 .name(name() + ".demand_misses") 181 .desc("number of demand (read+write) misses") 182 .flags(total) 183 ; 184 demandMisses = misses[MemCmd::ReadReq] + misses[MemCmd::WriteReq]; 185 186 overallMisses 187 .name(name() + ".overall_misses") 188 .desc("number of overall misses") 189 .flags(total) 190 ; 191 overallMisses = demandMisses + misses[MemCmd::SoftPFReq] + 192 misses[MemCmd::HardPFReq] + misses[MemCmd::Writeback]; 193 194 // Miss latency statistics 195 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 196 MemCmd cmd(access_idx); 197 const string &cstr = cmd.toString(); 198 199 missLatency[access_idx] 200 .init(maxThreadsPerCPU) 201 .name(name() + "." + cstr + "_miss_latency") 202 .desc("number of " + cstr + " miss cycles") 203 .flags(total | nozero | nonan) 204 ; 205 } 206 207 demandMissLatency 208 .name(name() + ".demand_miss_latency") 209 .desc("number of demand (read+write) miss cycles") 210 .flags(total) 211 ; 212 demandMissLatency = missLatency[MemCmd::ReadReq] + missLatency[MemCmd::WriteReq]; 213 214 overallMissLatency 215 .name(name() + ".overall_miss_latency") 216 .desc("number of overall miss cycles") 217 .flags(total) 218 ; 219 overallMissLatency = demandMissLatency + missLatency[MemCmd::SoftPFReq] + 220 missLatency[MemCmd::HardPFReq]; 221 222 // access formulas 223 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 224 MemCmd cmd(access_idx); 225 const string &cstr = cmd.toString(); 226 227 accesses[access_idx] 228 .name(name() + "." + cstr + "_accesses") 229 .desc("number of " + cstr + " accesses(hits+misses)") 230 .flags(total | nozero | nonan) 231 ; 232 233 accesses[access_idx] = hits[access_idx] + misses[access_idx]; 234 } 235 236 demandAccesses 237 .name(name() + ".demand_accesses") 238 .desc("number of demand (read+write) accesses") 239 .flags(total) 240 ; 241 demandAccesses = demandHits + demandMisses; 242 243 overallAccesses 244 .name(name() + ".overall_accesses") 245 .desc("number of overall (read+write) accesses") 246 .flags(total) 247 ; 248 overallAccesses = overallHits + overallMisses; 249 250 // miss rate formulas 251 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 252 MemCmd cmd(access_idx); 253 const string &cstr = cmd.toString(); 254 255 missRate[access_idx] 256 .name(name() + "." + cstr + "_miss_rate") 257 .desc("miss rate for " + cstr + " accesses") 258 .flags(total | nozero | nonan) 259 ; 260 261 missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 262 } 263 264 demandMissRate 265 .name(name() + ".demand_miss_rate") 266 .desc("miss rate for demand accesses") 267 .flags(total) 268 ; 269 demandMissRate = demandMisses / demandAccesses; 270 271 overallMissRate 272 .name(name() + ".overall_miss_rate") 273 .desc("miss rate for overall accesses") 274 .flags(total) 275 ; 276 overallMissRate = overallMisses / overallAccesses; 277 278 // miss latency formulas 279 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 280 MemCmd cmd(access_idx); 281 const string &cstr = cmd.toString(); 282 283 avgMissLatency[access_idx] 284 .name(name() + "." + cstr + "_avg_miss_latency") 285 .desc("average " + cstr + " miss latency") 286 .flags(total | nozero | nonan) 287 ; 288 289 avgMissLatency[access_idx] = 290 missLatency[access_idx] / misses[access_idx]; 291 } 292 293 demandAvgMissLatency 294 .name(name() + ".demand_avg_miss_latency") 295 .desc("average overall miss latency") 296 .flags(total) 297 ; 298 demandAvgMissLatency = demandMissLatency / demandMisses; 299 300 overallAvgMissLatency 301 .name(name() + ".overall_avg_miss_latency") 302 .desc("average overall miss latency") 303 .flags(total) 304 ; 305 overallAvgMissLatency = overallMissLatency / overallMisses; 306 307 blocked_cycles.init(NUM_BLOCKED_CAUSES); 308 blocked_cycles 309 .name(name() + ".blocked_cycles") 310 .desc("number of cycles access was blocked") 311 .subname(Blocked_NoMSHRs, "no_mshrs") 312 .subname(Blocked_NoTargets, "no_targets") 313 ; 314 315 316 blocked_causes.init(NUM_BLOCKED_CAUSES); 317 blocked_causes 318 .name(name() + ".blocked") 319 .desc("number of cycles access was blocked") 320 .subname(Blocked_NoMSHRs, "no_mshrs") 321 .subname(Blocked_NoTargets, "no_targets") 322 ; 323 324 avg_blocked 325 .name(name() + ".avg_blocked_cycles") 326 .desc("average number of cycles each access was blocked") 327 .subname(Blocked_NoMSHRs, "no_mshrs") 328 .subname(Blocked_NoTargets, "no_targets") 329 ; 330 331 avg_blocked = blocked_cycles / blocked_causes; 332 333 fastWrites 334 .name(name() + ".fast_writes") 335 .desc("number of fast writes performed") 336 ; 337 338 cacheCopies 339 .name(name() + ".cache_copies") 340 .desc("number of cache copies performed") 341 ; 342 343 writebacks 344 .init(maxThreadsPerCPU) 345 .name(name() + ".writebacks") 346 .desc("number of writebacks") 347 .flags(total) 348 ; 349 350 // MSHR statistics 351 // MSHR hit statistics 352 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 353 MemCmd cmd(access_idx); 354 const string &cstr = cmd.toString(); 355 356 mshr_hits[access_idx] 357 .init(maxThreadsPerCPU) 358 .name(name() + "." + cstr + "_mshr_hits") 359 .desc("number of " + cstr + " MSHR hits") 360 .flags(total | nozero | nonan) 361 ; 362 } 363 364 demandMshrHits 365 .name(name() + ".demand_mshr_hits") 366 .desc("number of demand (read+write) MSHR hits") 367 .flags(total) 368 ; 369 demandMshrHits = mshr_hits[MemCmd::ReadReq] + mshr_hits[MemCmd::WriteReq]; 370 371 overallMshrHits 372 .name(name() + ".overall_mshr_hits") 373 .desc("number of overall MSHR hits") 374 .flags(total) 375 ; 376 overallMshrHits = demandMshrHits + mshr_hits[MemCmd::SoftPFReq] + 377 mshr_hits[MemCmd::HardPFReq]; 378 379 // MSHR miss statistics 380 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 381 MemCmd cmd(access_idx); 382 const string &cstr = cmd.toString(); 383 384 mshr_misses[access_idx] 385 .init(maxThreadsPerCPU) 386 .name(name() + "." + cstr + "_mshr_misses") 387 .desc("number of " + cstr + " MSHR misses") 388 .flags(total | nozero | nonan) 389 ; 390 } 391 392 demandMshrMisses 393 .name(name() + ".demand_mshr_misses") 394 .desc("number of demand (read+write) MSHR misses") 395 .flags(total) 396 ; 397 demandMshrMisses = mshr_misses[MemCmd::ReadReq] + mshr_misses[MemCmd::WriteReq]; 398 399 overallMshrMisses 400 .name(name() + ".overall_mshr_misses") 401 .desc("number of overall MSHR misses") 402 .flags(total) 403 ; 404 overallMshrMisses = demandMshrMisses + mshr_misses[MemCmd::SoftPFReq] + 405 mshr_misses[MemCmd::HardPFReq]; 406 407 // MSHR miss latency statistics 408 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 409 MemCmd cmd(access_idx); 410 const string &cstr = cmd.toString(); 411 412 mshr_miss_latency[access_idx] 413 .init(maxThreadsPerCPU) 414 .name(name() + "." + cstr + "_mshr_miss_latency") 415 .desc("number of " + cstr + " MSHR miss cycles") 416 .flags(total | nozero | nonan) 417 ; 418 } 419 420 demandMshrMissLatency 421 .name(name() + ".demand_mshr_miss_latency") 422 .desc("number of demand (read+write) MSHR miss cycles") 423 .flags(total) 424 ; 425 demandMshrMissLatency = mshr_miss_latency[MemCmd::ReadReq] 426 + mshr_miss_latency[MemCmd::WriteReq]; 427 428 overallMshrMissLatency 429 .name(name() + ".overall_mshr_miss_latency") 430 .desc("number of overall MSHR miss cycles") 431 .flags(total) 432 ; 433 overallMshrMissLatency = demandMshrMissLatency + 434 mshr_miss_latency[MemCmd::SoftPFReq] + mshr_miss_latency[MemCmd::HardPFReq]; 435 436 // MSHR uncacheable statistics 437 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 438 MemCmd cmd(access_idx); 439 const string &cstr = cmd.toString(); 440 441 mshr_uncacheable[access_idx] 442 .init(maxThreadsPerCPU) 443 .name(name() + "." + cstr + "_mshr_uncacheable") 444 .desc("number of " + cstr + " MSHR uncacheable") 445 .flags(total | nozero | nonan) 446 ; 447 } 448 449 overallMshrUncacheable 450 .name(name() + ".overall_mshr_uncacheable_misses") 451 .desc("number of overall MSHR uncacheable misses") 452 .flags(total) 453 ; 454 overallMshrUncacheable = mshr_uncacheable[MemCmd::ReadReq] 455 + mshr_uncacheable[MemCmd::WriteReq] + mshr_uncacheable[MemCmd::SoftPFReq] 456 + mshr_uncacheable[MemCmd::HardPFReq]; 457 458 // MSHR miss latency 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_lat[access_idx] 464 .init(maxThreadsPerCPU) 465 .name(name() + "." + cstr + "_mshr_uncacheable_latency") 466 .desc("number of " + cstr + " MSHR uncacheable cycles") 467 .flags(total | nozero | nonan) 468 ; 469 } 470 471 overallMshrUncacheableLatency 472 .name(name() + ".overall_mshr_uncacheable_latency") 473 .desc("number of overall MSHR uncacheable cycles") 474 .flags(total) 475 ; 476 overallMshrUncacheableLatency = mshr_uncacheable_lat[MemCmd::ReadReq] 477 + mshr_uncacheable_lat[MemCmd::WriteReq] 478 + mshr_uncacheable_lat[MemCmd::SoftPFReq] 479 + mshr_uncacheable_lat[MemCmd::HardPFReq]; 480 481#if 0 482 // MSHR access formulas 483 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 484 MemCmd cmd(access_idx); 485 const string &cstr = cmd.toString(); 486 487 mshrAccesses[access_idx] 488 .name(name() + "." + cstr + "_mshr_accesses") 489 .desc("number of " + cstr + " mshr accesses(hits+misses)") 490 .flags(total | nozero | nonan) 491 ; 492 mshrAccesses[access_idx] = 493 mshr_hits[access_idx] + mshr_misses[access_idx] 494 + mshr_uncacheable[access_idx]; 495 } 496 497 demandMshrAccesses 498 .name(name() + ".demand_mshr_accesses") 499 .desc("number of demand (read+write) mshr accesses") 500 .flags(total | nozero | nonan) 501 ; 502 demandMshrAccesses = demandMshrHits + demandMshrMisses; 503 504 overallMshrAccesses 505 .name(name() + ".overall_mshr_accesses") 506 .desc("number of overall (read+write) mshr accesses") 507 .flags(total | nozero | nonan) 508 ; 509 overallMshrAccesses = overallMshrHits + overallMshrMisses 510 + overallMshrUncacheable; 511#endif 512 513 // MSHR miss rate formulas 514 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 515 MemCmd cmd(access_idx); 516 const string &cstr = cmd.toString(); 517 518 mshrMissRate[access_idx] 519 .name(name() + "." + cstr + "_mshr_miss_rate") 520 .desc("mshr miss rate for " + cstr + " accesses") 521 .flags(total | nozero | nonan) 522 ; 523 524 mshrMissRate[access_idx] = 525 mshr_misses[access_idx] / accesses[access_idx]; 526 } 527 528 demandMshrMissRate 529 .name(name() + ".demand_mshr_miss_rate") 530 .desc("mshr miss rate for demand accesses") 531 .flags(total) 532 ; 533 demandMshrMissRate = demandMshrMisses / demandAccesses; 534 535 overallMshrMissRate 536 .name(name() + ".overall_mshr_miss_rate") 537 .desc("mshr miss rate for overall accesses") 538 .flags(total) 539 ; 540 overallMshrMissRate = overallMshrMisses / overallAccesses; 541 542 // mshrMiss latency formulas 543 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 544 MemCmd cmd(access_idx); 545 const string &cstr = cmd.toString(); 546 547 avgMshrMissLatency[access_idx] 548 .name(name() + "." + cstr + "_avg_mshr_miss_latency") 549 .desc("average " + cstr + " mshr miss latency") 550 .flags(total | nozero | nonan) 551 ; 552 553 avgMshrMissLatency[access_idx] = 554 mshr_miss_latency[access_idx] / mshr_misses[access_idx]; 555 } 556 557 demandAvgMshrMissLatency 558 .name(name() + ".demand_avg_mshr_miss_latency") 559 .desc("average overall mshr miss latency") 560 .flags(total) 561 ; 562 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses; 563 564 overallAvgMshrMissLatency 565 .name(name() + ".overall_avg_mshr_miss_latency") 566 .desc("average overall mshr miss latency") 567 .flags(total) 568 ; 569 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses; 570 571 // mshrUncacheable latency formulas 572 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { 573 MemCmd cmd(access_idx); 574 const string &cstr = cmd.toString(); 575 576 avgMshrUncacheableLatency[access_idx] 577 .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency") 578 .desc("average " + cstr + " mshr uncacheable latency") 579 .flags(total | nozero | nonan) 580 ; 581 582 avgMshrUncacheableLatency[access_idx] = 583 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx]; 584 } 585 586 overallAvgMshrUncacheableLatency 587 .name(name() + ".overall_avg_mshr_uncacheable_latency") 588 .desc("average overall mshr uncacheable latency") 589 .flags(total) 590 ; 591 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable; 592 593 mshr_cap_events 594 .init(maxThreadsPerCPU) 595 .name(name() + ".mshr_cap_events") 596 .desc("number of times MSHR cap was activated") 597 .flags(total) 598 ; 599 600 //software prefetching stats 601 soft_prefetch_mshr_full 602 .init(maxThreadsPerCPU) 603 .name(name() + ".soft_prefetch_mshr_full") 604 .desc("number of mshr full events for SW prefetching instrutions") 605 .flags(total) 606 ; 607 608 mshr_no_allocate_misses 609 .name(name() +".no_allocate_misses") 610 .desc("Number of misses that were no-allocate") 611 ; 612 613} 614 615unsigned int 616BaseCache::drain(Event *de) 617{ 618 int count = memSidePort->drain(de) + cpuSidePort->drain(de); 619 620 // Set status 621 if (count != 0) { 622 drainEvent = de; 623 624 changeState(SimObject::Draining); 625 return count; 626 } 627 628 changeState(SimObject::Drained); 629 return 0; 630} 631