base.cc revision 3348
17584SN/A/* 28869SAli.Saidi@ARM.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 37584SN/A * All rights reserved. 47584SN/A * 57584SN/A * Redistribution and use in source and binary forms, with or without 67584SN/A * modification, are permitted provided that the following conditions are 77584SN/A * met: redistributions of source code must retain the above copyright 87584SN/A * notice, this list of conditions and the following disclaimer; 97584SN/A * redistributions in binary form must reproduce the above copyright 107584SN/A * notice, this list of conditions and the following disclaimer in the 117584SN/A * documentation and/or other materials provided with the distribution; 127584SN/A * neither the name of the copyright holders nor the names of its 137584SN/A * contributors may be used to endorse or promote products derived from 147584SN/A * this software without specific prior written permission. 157584SN/A * 167584SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177584SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187584SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197584SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207584SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217584SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227584SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237584SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247584SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257584SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267584SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277584SN/A * 287584SN/A * Authors: Erik Hallnor 297584SN/A */ 307584SN/A 317584SN/A/** 327584SN/A * @file 337584SN/A * Definition of BaseCache functions. 347584SN/A */ 357584SN/A 367584SN/A#include "cpu/base.hh" 377584SN/A#include "cpu/smt.hh" 387584SN/A#include "mem/cache/base_cache.hh" 397584SN/A#include "mem/cache/miss/mshr.hh" 4011793Sbrandon.potter@amd.com 4111793Sbrandon.potter@amd.comusing namespace std; 427584SN/A 438869SAli.Saidi@ARM.comBaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, 447584SN/A bool _isCpuSide) 458245SN/A : Port(_name), cache(_cache), isCpuSide(_isCpuSide) 468245SN/A{ 478869SAli.Saidi@ARM.com blocked = false; 487584SN/A waitingOnRetry = false; 497584SN/A //Start ports at null if more than one is created we should panic 507584SN/A //cpuSidePort = NULL; 518869SAli.Saidi@ARM.com //memSidePort = NULL; 5212772Snikos.nikoleris@arm.com} 539808Sstever@gmail.com 5412086Sspwilson2@wisc.eduvoid 5512086Sspwilson2@wisc.eduBaseCache::CachePort::recvStatusChange(Port::Status status) 567584SN/A{ 577584SN/A cache->recvStatusChange(status, isCpuSide); 587584SN/A} 597584SN/A 607584SN/Avoid 618869SAli.Saidi@ARM.comBaseCache::CachePort::getDeviceAddressRanges(AddrRangeList &resp, 627584SN/A AddrRangeList &snoop) 637584SN/A{ 647584SN/A cache->getAddressRanges(resp, snoop, isCpuSide); 657584SN/A} 668869SAli.Saidi@ARM.com 677584SN/Aint 688869SAli.Saidi@ARM.comBaseCache::CachePort::deviceBlockSize() 698869SAli.Saidi@ARM.com{ 708869SAli.Saidi@ARM.com return cache->getBlockSize(); 718869SAli.Saidi@ARM.com} 728869SAli.Saidi@ARM.com 738869SAli.Saidi@ARM.combool 748869SAli.Saidi@ARM.comBaseCache::CachePort::recvTiming(Packet *pkt) 758869SAli.Saidi@ARM.com{ 768869SAli.Saidi@ARM.com if (isCpuSide 778869SAli.Saidi@ARM.com && !pkt->req->isUncacheable() 788869SAli.Saidi@ARM.com && pkt->isInvalidate() 798869SAli.Saidi@ARM.com && !pkt->isRead() && !pkt->isWrite()) { 808869SAli.Saidi@ARM.com //Upgrade or Invalidate 818869SAli.Saidi@ARM.com //Look into what happens if two slave caches on bus 828869SAli.Saidi@ARM.com DPRINTF(Cache, "%s %x ? blk_addr: %x\n", pkt->cmdString(), 838869SAli.Saidi@ARM.com pkt->getAddr() & (((ULL(1))<<48)-1), 848869SAli.Saidi@ARM.com pkt->getAddr() & ~((Addr)cache->blkSize - 1)); 858869SAli.Saidi@ARM.com 868869SAli.Saidi@ARM.com assert(!(pkt->flags & SATISFIED)); 878869SAli.Saidi@ARM.com pkt->flags |= SATISFIED; 888869SAli.Saidi@ARM.com //Invalidates/Upgrades need no response if they get the bus 898869SAli.Saidi@ARM.com return true; 908869SAli.Saidi@ARM.com } 918869SAli.Saidi@ARM.com 928869SAli.Saidi@ARM.com if (pkt->isRequest() && blocked) 939806Sstever@gmail.com { 948869SAli.Saidi@ARM.com DPRINTF(Cache,"Scheduling a retry while blocked\n"); 9513230Sgabeblack@google.com mustSendRetry = true; 968869SAli.Saidi@ARM.com return false; 978869SAli.Saidi@ARM.com } 988869SAli.Saidi@ARM.com return cache->doTimingAccess(pkt, this, isCpuSide); 998869SAli.Saidi@ARM.com} 1008869SAli.Saidi@ARM.com 1018869SAli.Saidi@ARM.comTick 1028869SAli.Saidi@ARM.comBaseCache::CachePort::recvAtomic(Packet *pkt) 1038869SAli.Saidi@ARM.com{ 10413230Sgabeblack@google.com return cache->doAtomicAccess(pkt, isCpuSide); 1058869SAli.Saidi@ARM.com} 1068869SAli.Saidi@ARM.com 10713230Sgabeblack@google.comvoid 1088869SAli.Saidi@ARM.comBaseCache::CachePort::recvFunctional(Packet *pkt) 1098869SAli.Saidi@ARM.com{ 11013230Sgabeblack@google.com //Check storage here first 1118869SAli.Saidi@ARM.com list<Packet *>::iterator i = drainList.begin(); 1128869SAli.Saidi@ARM.com list<Packet *>::iterator end = drainList.end(); 1138869SAli.Saidi@ARM.com for (; i != end; ++i) { 1148869SAli.Saidi@ARM.com Packet * target = *i; 1158869SAli.Saidi@ARM.com // If the target contains data, and it overlaps the 1168869SAli.Saidi@ARM.com // probed request, need to update data 1178869SAli.Saidi@ARM.com if (target->intersect(pkt)) { 1187584SN/A uint8_t* pkt_data; 1197584SN/A uint8_t* write_data; 1207584SN/A int data_size; 1217584SN/A if (target->getAddr() < pkt->getAddr()) { 1227584SN/A int offset = pkt->getAddr() - target->getAddr(); 1238869SAli.Saidi@ARM.com pkt_data = pkt->getPtr<uint8_t>(); 1247584SN/A write_data = target->getPtr<uint8_t>() + offset; 1257584SN/A data_size = target->getSize() - offset; 1267584SN/A assert(data_size > 0); 1277584SN/A if (data_size > pkt->getSize()) 1288869SAli.Saidi@ARM.com data_size = pkt->getSize(); 1297584SN/A } else { 1308869SAli.Saidi@ARM.com int offset = target->getAddr() - pkt->getAddr(); 1318869SAli.Saidi@ARM.com pkt_data = pkt->getPtr<uint8_t>() + offset; 1328869SAli.Saidi@ARM.com write_data = target->getPtr<uint8_t>(); 1338869SAli.Saidi@ARM.com data_size = pkt->getSize() - offset; 13413230Sgabeblack@google.com assert(data_size >= pkt->getSize()); 1358869SAli.Saidi@ARM.com if (data_size > target->getSize()) 1368869SAli.Saidi@ARM.com data_size = target->getSize(); 1378869SAli.Saidi@ARM.com } 1388869SAli.Saidi@ARM.com 13913230Sgabeblack@google.com if (pkt->isWrite()) { 1408869SAli.Saidi@ARM.com memcpy(pkt_data, write_data, data_size); 1418869SAli.Saidi@ARM.com } else { 1428869SAli.Saidi@ARM.com memcpy(write_data, pkt_data, data_size); 1438869SAli.Saidi@ARM.com } 1448869SAli.Saidi@ARM.com } 1458869SAli.Saidi@ARM.com } 14613230Sgabeblack@google.com cache->doFunctionalAccess(pkt, isCpuSide); 1478869SAli.Saidi@ARM.com} 1488869SAli.Saidi@ARM.com 14913230Sgabeblack@google.comvoid 1508869SAli.Saidi@ARM.comBaseCache::CachePort::recvRetry() 1518869SAli.Saidi@ARM.com{ 1528869SAli.Saidi@ARM.com Packet *pkt; 1538869SAli.Saidi@ARM.com assert(waitingOnRetry); 1548869SAli.Saidi@ARM.com if (!drainList.empty()) { 1559806Sstever@gmail.com DPRINTF(CachePort, "%s attempting to send a retry for response\n", name()); 1568869SAli.Saidi@ARM.com //We have some responses to drain first 1578869SAli.Saidi@ARM.com if (sendTiming(drainList.front())) { 1588869SAli.Saidi@ARM.com DPRINTF(CachePort, "%s sucessful in sending a retry for response\n", name()); 1598869SAli.Saidi@ARM.com drainList.pop_front(); 1608869SAli.Saidi@ARM.com if (!drainList.empty() || 1617584SN/A !isCpuSide && cache->doMasterRequest() || 1627584SN/A isCpuSide && cache->doSlaveRequest()) { 1637584SN/A 1647584SN/A DPRINTF(CachePort, "%s has more responses/requests\n", name()); 1657584SN/A BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); 1668869SAli.Saidi@ARM.com reqCpu->schedule(curTick + 1); 1677584SN/A } 1688869SAli.Saidi@ARM.com waitingOnRetry = false; 1698869SAli.Saidi@ARM.com } 1708869SAli.Saidi@ARM.com } 1718869SAli.Saidi@ARM.com else if (!isCpuSide) 1728869SAli.Saidi@ARM.com { 1738869SAli.Saidi@ARM.com DPRINTF(CachePort, "%s attempting to send a retry for MSHR\n", name()); 1748869SAli.Saidi@ARM.com if (!cache->doMasterRequest()) { 1758869SAli.Saidi@ARM.com //This can happen if I am the owner of a block and see an upgrade 1768869SAli.Saidi@ARM.com //while the block was in my WB Buffers. I just remove the 1778869SAli.Saidi@ARM.com //wb and de-assert the masterRequest 1788869SAli.Saidi@ARM.com waitingOnRetry = false; 1798869SAli.Saidi@ARM.com return; 1808869SAli.Saidi@ARM.com } 1818869SAli.Saidi@ARM.com pkt = cache->getPacket(); 1828869SAli.Saidi@ARM.com MSHR* mshr = (MSHR*) pkt->senderState; 1838869SAli.Saidi@ARM.com //Copy the packet, it may be modified/destroyed elsewhere 1848869SAli.Saidi@ARM.com Packet * copyPkt = new Packet(*pkt); 1858869SAli.Saidi@ARM.com copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>()); 1868869SAli.Saidi@ARM.com mshr->pkt = copyPkt; 1878869SAli.Saidi@ARM.com 1888869SAli.Saidi@ARM.com bool success = sendTiming(pkt); 1898869SAli.Saidi@ARM.com DPRINTF(Cache, "Address %x was %s in sending the timing request\n", 1908993SAli.Saidi@ARM.com pkt->getAddr(), success ? "succesful" : "unsuccesful"); 1918869SAli.Saidi@ARM.com 1928869SAli.Saidi@ARM.com waitingOnRetry = !success; 1937584SN/A if (waitingOnRetry) { 1947584SN/A DPRINTF(CachePort, "%s now waiting on a retry\n", name()); 1957584SN/A } 1967584SN/A 19710905Sandreas.sandberg@arm.com cache->sendResult(pkt, mshr, success); 1987584SN/A 1998869SAli.Saidi@ARM.com if (success && cache->doMasterRequest()) 2008869SAli.Saidi@ARM.com { 2018869SAli.Saidi@ARM.com DPRINTF(CachePort, "%s has more requests\n", name()); 2028869SAli.Saidi@ARM.com //Still more to issue, rerequest in 1 cycle 2038869SAli.Saidi@ARM.com BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); 2048869SAli.Saidi@ARM.com reqCpu->schedule(curTick + 1); 2058869SAli.Saidi@ARM.com } 2068869SAli.Saidi@ARM.com } 2077584SN/A else 2088869SAli.Saidi@ARM.com { 2097733SN/A assert(cache->doSlaveRequest()); 2107733SN/A //pkt = cache->getCoherencePacket(); 2117733SN/A //We save the packet, no reordering on CSHRS 2127733SN/A pkt = cache->getCoherencePacket(); 2138869SAli.Saidi@ARM.com MSHR* cshr = (MSHR*)pkt->senderState; 2147733SN/A bool success = sendTiming(pkt); 2157733SN/A cache->sendCoherenceResult(pkt, cshr, success); 2167733SN/A waitingOnRetry = !success; 2177733SN/A if (success && cache->doSlaveRequest()) 2187733SN/A { 21910905Sandreas.sandberg@arm.com DPRINTF(CachePort, "%s has more requests\n", name()); 2207733SN/A //Still more to issue, rerequest in 1 cycle 2218869SAli.Saidi@ARM.com BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); 2227733SN/A reqCpu->schedule(curTick + 1); 2238869SAli.Saidi@ARM.com } 2248869SAli.Saidi@ARM.com } 2258869SAli.Saidi@ARM.com if (waitingOnRetry) DPRINTF(CachePort, "%s STILL Waiting on retry\n", name()); 2268869SAli.Saidi@ARM.com else DPRINTF(CachePort, "%s no longer waiting on retry\n", name()); 2277733SN/A return; 2288869SAli.Saidi@ARM.com} 2297733SN/Avoid 2307733SN/ABaseCache::CachePort::setBlocked() 2317733SN/A{ 2327733SN/A assert(!blocked); 2337733SN/A DPRINTF(Cache, "Cache Blocking\n"); 2347733SN/A blocked = true; 2357733SN/A //Clear the retry flag 2367733SN/A mustSendRetry = false; 2378869SAli.Saidi@ARM.com} 2387733SN/A 2397733SN/Avoid 2407733SN/ABaseCache::CachePort::clearBlocked() 2417733SN/A{ 2427584SN/A assert(blocked); 2438869SAli.Saidi@ARM.com DPRINTF(Cache, "Cache Unblocking\n"); 2448869SAli.Saidi@ARM.com blocked = false; 2457584SN/A if (mustSendRetry) 2468869SAli.Saidi@ARM.com { 2477584SN/A DPRINTF(Cache, "Cache Sending Retry\n"); 248 mustSendRetry = false; 249 sendRetry(); 250 } 251} 252 253BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort) 254 : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort) 255{ 256 this->setFlags(AutoDelete); 257 pkt = NULL; 258} 259 260BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, Packet *_pkt) 261 : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort), pkt(_pkt) 262{ 263 this->setFlags(AutoDelete); 264} 265 266void 267BaseCache::CacheEvent::process() 268{ 269 if (!pkt) 270 { 271 if (cachePort->waitingOnRetry) return; 272 //We have some responses to drain first 273 if (!cachePort->drainList.empty()) { 274 DPRINTF(CachePort, "%s trying to drain a response\n", cachePort->name()); 275 if (cachePort->sendTiming(cachePort->drainList.front())) { 276 DPRINTF(CachePort, "%s drains a response succesfully\n", cachePort->name()); 277 cachePort->drainList.pop_front(); 278 if (!cachePort->drainList.empty() || 279 !cachePort->isCpuSide && cachePort->cache->doMasterRequest() || 280 cachePort->isCpuSide && cachePort->cache->doSlaveRequest()) { 281 282 DPRINTF(CachePort, "%s still has outstanding bus reqs\n", cachePort->name()); 283 this->schedule(curTick + 1); 284 } 285 } 286 else { 287 cachePort->waitingOnRetry = true; 288 DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name()); 289 } 290 } 291 else if (!cachePort->isCpuSide) 292 { //MSHR 293 DPRINTF(CachePort, "%s trying to send a MSHR request\n", cachePort->name()); 294 if (!cachePort->cache->doMasterRequest()) { 295 //This can happen if I am the owner of a block and see an upgrade 296 //while the block was in my WB Buffers. I just remove the 297 //wb and de-assert the masterRequest 298 return; 299 } 300 301 pkt = cachePort->cache->getPacket(); 302 MSHR* mshr = (MSHR*) pkt->senderState; 303 //Copy the packet, it may be modified/destroyed elsewhere 304 Packet * copyPkt = new Packet(*pkt); 305 copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>()); 306 mshr->pkt = copyPkt; 307 308 bool success = cachePort->sendTiming(pkt); 309 DPRINTF(Cache, "Address %x was %s in sending the timing request\n", 310 pkt->getAddr(), success ? "succesful" : "unsuccesful"); 311 312 cachePort->waitingOnRetry = !success; 313 if (cachePort->waitingOnRetry) { 314 DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name()); 315 } 316 317 cachePort->cache->sendResult(pkt, mshr, success); 318 if (success && cachePort->cache->doMasterRequest()) 319 { 320 DPRINTF(CachePort, "%s still more MSHR requests to send\n", 321 cachePort->name()); 322 //Still more to issue, rerequest in 1 cycle 323 pkt = NULL; 324 this->schedule(curTick+1); 325 } 326 } 327 else 328 { 329 //CSHR 330 assert(cachePort->cache->doSlaveRequest()); 331 pkt = cachePort->cache->getCoherencePacket(); 332 MSHR* cshr = (MSHR*) pkt->senderState; 333 bool success = cachePort->sendTiming(pkt); 334 cachePort->cache->sendCoherenceResult(pkt, cshr, success); 335 cachePort->waitingOnRetry = !success; 336 if (cachePort->waitingOnRetry) 337 DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name()); 338 if (success && cachePort->cache->doSlaveRequest()) 339 { 340 DPRINTF(CachePort, "%s still more CSHR requests to send\n", 341 cachePort->name()); 342 //Still more to issue, rerequest in 1 cycle 343 pkt = NULL; 344 this->schedule(curTick+1); 345 } 346 } 347 return; 348 } 349 //Response 350 //Know the packet to send 351 if (pkt->flags & NACKED_LINE) 352 pkt->result = Packet::Nacked; 353 else 354 pkt->result = Packet::Success; 355 pkt->makeTimingResponse(); 356 DPRINTF(CachePort, "%s attempting to send a response\n", cachePort->name()); 357 if (!cachePort->drainList.empty() || cachePort->waitingOnRetry) { 358 //Already have a list, just append 359 cachePort->drainList.push_back(pkt); 360 DPRINTF(CachePort, "%s appending response onto drain list\n", cachePort->name()); 361 } 362 else if (!cachePort->sendTiming(pkt)) { 363 //It failed, save it to list of drain events 364 DPRINTF(CachePort, "%s now waiting for a retry\n", cachePort->name()); 365 cachePort->drainList.push_back(pkt); 366 cachePort->waitingOnRetry = true; 367 } 368} 369 370const char * 371BaseCache::CacheEvent::description() 372{ 373 return "timing event\n"; 374} 375 376Port* 377BaseCache::getPort(const std::string &if_name, int idx) 378{ 379 if (if_name == "") 380 { 381 if(cpuSidePort == NULL) 382 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 383 return cpuSidePort; 384 } 385 else if (if_name == "functional") 386 { 387 if(cpuSidePort == NULL) 388 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 389 return cpuSidePort; 390 } 391 else if (if_name == "cpu_side") 392 { 393 if(cpuSidePort == NULL) 394 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 395 return cpuSidePort; 396 } 397 else if (if_name == "mem_side") 398 { 399 if (memSidePort != NULL) 400 panic("Already have a mem side for this cache\n"); 401 memSidePort = new CachePort(name() + "-mem_side_port", this, false); 402 return memSidePort; 403 } 404 else panic("Port name %s unrecognized\n", if_name); 405} 406 407void 408BaseCache::init() 409{ 410 if (!cpuSidePort || !memSidePort) 411 panic("Cache not hooked up on both sides\n"); 412 cpuSidePort->sendStatusChange(Port::RangeChange); 413} 414 415void 416BaseCache::regStats() 417{ 418 Request temp_req((Addr) NULL, 4, 0); 419 Packet::Command temp_cmd = Packet::ReadReq; 420 Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary 421 temp_pkt.allocate(); //Temp allocate, all need data 422 423 using namespace Stats; 424 425 // Hit statistics 426 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 427 Packet::Command cmd = (Packet::Command)access_idx; 428 const string &cstr = temp_pkt.cmdIdxToString(cmd); 429 430 hits[access_idx] 431 .init(maxThreadsPerCPU) 432 .name(name() + "." + cstr + "_hits") 433 .desc("number of " + cstr + " hits") 434 .flags(total | nozero | nonan) 435 ; 436 } 437 438 demandHits 439 .name(name() + ".demand_hits") 440 .desc("number of demand (read+write) hits") 441 .flags(total) 442 ; 443 demandHits = hits[Packet::ReadReq] + hits[Packet::WriteReq]; 444 445 overallHits 446 .name(name() + ".overall_hits") 447 .desc("number of overall hits") 448 .flags(total) 449 ; 450 overallHits = demandHits + hits[Packet::SoftPFReq] + hits[Packet::HardPFReq] 451 + hits[Packet::Writeback]; 452 453 // Miss statistics 454 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 455 Packet::Command cmd = (Packet::Command)access_idx; 456 const string &cstr = temp_pkt.cmdIdxToString(cmd); 457 458 misses[access_idx] 459 .init(maxThreadsPerCPU) 460 .name(name() + "." + cstr + "_misses") 461 .desc("number of " + cstr + " misses") 462 .flags(total | nozero | nonan) 463 ; 464 } 465 466 demandMisses 467 .name(name() + ".demand_misses") 468 .desc("number of demand (read+write) misses") 469 .flags(total) 470 ; 471 demandMisses = misses[Packet::ReadReq] + misses[Packet::WriteReq]; 472 473 overallMisses 474 .name(name() + ".overall_misses") 475 .desc("number of overall misses") 476 .flags(total) 477 ; 478 overallMisses = demandMisses + misses[Packet::SoftPFReq] + 479 misses[Packet::HardPFReq] + misses[Packet::Writeback]; 480 481 // Miss latency statistics 482 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 483 Packet::Command cmd = (Packet::Command)access_idx; 484 const string &cstr = temp_pkt.cmdIdxToString(cmd); 485 486 missLatency[access_idx] 487 .init(maxThreadsPerCPU) 488 .name(name() + "." + cstr + "_miss_latency") 489 .desc("number of " + cstr + " miss cycles") 490 .flags(total | nozero | nonan) 491 ; 492 } 493 494 demandMissLatency 495 .name(name() + ".demand_miss_latency") 496 .desc("number of demand (read+write) miss cycles") 497 .flags(total) 498 ; 499 demandMissLatency = missLatency[Packet::ReadReq] + missLatency[Packet::WriteReq]; 500 501 overallMissLatency 502 .name(name() + ".overall_miss_latency") 503 .desc("number of overall miss cycles") 504 .flags(total) 505 ; 506 overallMissLatency = demandMissLatency + missLatency[Packet::SoftPFReq] + 507 missLatency[Packet::HardPFReq]; 508 509 // access formulas 510 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 511 Packet::Command cmd = (Packet::Command)access_idx; 512 const string &cstr = temp_pkt.cmdIdxToString(cmd); 513 514 accesses[access_idx] 515 .name(name() + "." + cstr + "_accesses") 516 .desc("number of " + cstr + " accesses(hits+misses)") 517 .flags(total | nozero | nonan) 518 ; 519 520 accesses[access_idx] = hits[access_idx] + misses[access_idx]; 521 } 522 523 demandAccesses 524 .name(name() + ".demand_accesses") 525 .desc("number of demand (read+write) accesses") 526 .flags(total) 527 ; 528 demandAccesses = demandHits + demandMisses; 529 530 overallAccesses 531 .name(name() + ".overall_accesses") 532 .desc("number of overall (read+write) accesses") 533 .flags(total) 534 ; 535 overallAccesses = overallHits + overallMisses; 536 537 // miss rate formulas 538 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 539 Packet::Command cmd = (Packet::Command)access_idx; 540 const string &cstr = temp_pkt.cmdIdxToString(cmd); 541 542 missRate[access_idx] 543 .name(name() + "." + cstr + "_miss_rate") 544 .desc("miss rate for " + cstr + " accesses") 545 .flags(total | nozero | nonan) 546 ; 547 548 missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 549 } 550 551 demandMissRate 552 .name(name() + ".demand_miss_rate") 553 .desc("miss rate for demand accesses") 554 .flags(total) 555 ; 556 demandMissRate = demandMisses / demandAccesses; 557 558 overallMissRate 559 .name(name() + ".overall_miss_rate") 560 .desc("miss rate for overall accesses") 561 .flags(total) 562 ; 563 overallMissRate = overallMisses / overallAccesses; 564 565 // miss latency formulas 566 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 567 Packet::Command cmd = (Packet::Command)access_idx; 568 const string &cstr = temp_pkt.cmdIdxToString(cmd); 569 570 avgMissLatency[access_idx] 571 .name(name() + "." + cstr + "_avg_miss_latency") 572 .desc("average " + cstr + " miss latency") 573 .flags(total | nozero | nonan) 574 ; 575 576 avgMissLatency[access_idx] = 577 missLatency[access_idx] / misses[access_idx]; 578 } 579 580 demandAvgMissLatency 581 .name(name() + ".demand_avg_miss_latency") 582 .desc("average overall miss latency") 583 .flags(total) 584 ; 585 demandAvgMissLatency = demandMissLatency / demandMisses; 586 587 overallAvgMissLatency 588 .name(name() + ".overall_avg_miss_latency") 589 .desc("average overall miss latency") 590 .flags(total) 591 ; 592 overallAvgMissLatency = overallMissLatency / overallMisses; 593 594 blocked_cycles.init(NUM_BLOCKED_CAUSES); 595 blocked_cycles 596 .name(name() + ".blocked_cycles") 597 .desc("number of cycles access was blocked") 598 .subname(Blocked_NoMSHRs, "no_mshrs") 599 .subname(Blocked_NoTargets, "no_targets") 600 ; 601 602 603 blocked_causes.init(NUM_BLOCKED_CAUSES); 604 blocked_causes 605 .name(name() + ".blocked") 606 .desc("number of cycles access was blocked") 607 .subname(Blocked_NoMSHRs, "no_mshrs") 608 .subname(Blocked_NoTargets, "no_targets") 609 ; 610 611 avg_blocked 612 .name(name() + ".avg_blocked_cycles") 613 .desc("average number of cycles each access was blocked") 614 .subname(Blocked_NoMSHRs, "no_mshrs") 615 .subname(Blocked_NoTargets, "no_targets") 616 ; 617 618 avg_blocked = blocked_cycles / blocked_causes; 619 620 fastWrites 621 .name(name() + ".fast_writes") 622 .desc("number of fast writes performed") 623 ; 624 625 cacheCopies 626 .name(name() + ".cache_copies") 627 .desc("number of cache copies performed") 628 ; 629 630} 631