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