base.hh revision 5100
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 * Steve Reinhardt 30 * Ron Dreslinski 31 */ 32 33/** 34 * @file 35 * Declares a basic cache interface BaseCache. 36 */ 37 38#ifndef __BASE_CACHE_HH__ 39#define __BASE_CACHE_HH__ 40 41#include <vector> 42#include <string> 43#include <list> 44#include <algorithm> 45#include <inttypes.h> 46 47#include "base/misc.hh" 48#include "base/statistics.hh" 49#include "base/trace.hh" 50#include "mem/cache/miss/mshr_queue.hh" 51#include "mem/mem_object.hh" 52#include "mem/packet.hh" 53#include "mem/tport.hh" 54#include "mem/request.hh" 55#include "params/BaseCache.hh" 56#include "sim/eventq.hh" 57#include "sim/sim_exit.hh" 58 59class MSHR; 60/** 61 * A basic cache interface. Implements some common functions for speed. 62 */ 63class BaseCache : public MemObject 64{ 65 /** 66 * Indexes to enumerate the MSHR queues. 67 */ 68 enum MSHRQueueIndex { 69 MSHRQueue_MSHRs, 70 MSHRQueue_WriteBuffer 71 }; 72 73 /** 74 * Reasons for caches to be blocked. 75 */ 76 enum BlockedCause { 77 Blocked_NoMSHRs = MSHRQueue_MSHRs, 78 Blocked_NoWBBuffers = MSHRQueue_WriteBuffer, 79 Blocked_NoTargets, 80 NUM_BLOCKED_CAUSES 81 }; 82 83 public: 84 /** 85 * Reasons for cache to request a bus. 86 */ 87 enum RequestCause { 88 Request_MSHR = MSHRQueue_MSHRs, 89 Request_WB = MSHRQueue_WriteBuffer, 90 Request_PF, 91 NUM_REQUEST_CAUSES 92 }; 93 94 private: 95 96 class CachePort : public SimpleTimingPort 97 { 98 public: 99 BaseCache *cache; 100 101 protected: 102 CachePort(const std::string &_name, BaseCache *_cache, 103 std::vector<Range<Addr> > filter_ranges); 104 105 virtual void recvStatusChange(Status status); 106 107 virtual int deviceBlockSize(); 108 109 bool recvRetryCommon(); 110 111 typedef EventWrapper<Port, &Port::sendRetry> 112 SendRetryEvent; 113 114 public: 115 void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; } 116 117 void setBlocked(); 118 119 void clearBlocked(); 120 121 void checkAndSendFunctional(PacketPtr pkt); 122 123 CachePort *otherPort; 124 125 bool blocked; 126 127 bool mustSendRetry; 128 129 /** filter ranges */ 130 std::vector<Range<Addr> > filterRanges; 131 132 void requestBus(RequestCause cause, Tick time) 133 { 134 DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause); 135 if (!waitingOnRetry) { 136 schedSendEvent(time); 137 } 138 } 139 140 void respond(PacketPtr pkt, Tick time) { 141 schedSendTiming(pkt, time); 142 } 143 }; 144 145 public: //Made public so coherence can get at it. 146 CachePort *cpuSidePort; 147 CachePort *memSidePort; 148 149 protected: 150 151 /** Miss status registers */ 152 MSHRQueue mshrQueue; 153 154 /** Write/writeback buffer */ 155 MSHRQueue writeBuffer; 156 157 MSHR *allocateBufferInternal(MSHRQueue *mq, Addr addr, int size, 158 PacketPtr pkt, Tick time, bool requestBus) 159 { 160 MSHR *mshr = mq->allocate(addr, size, pkt, time, order++); 161 162 if (mq->isFull()) { 163 setBlocked((BlockedCause)mq->index); 164 } 165 166 if (requestBus) { 167 requestMemSideBus((RequestCause)mq->index, time); 168 } 169 170 return mshr; 171 } 172 173 void markInServiceInternal(MSHR *mshr) 174 { 175 MSHRQueue *mq = mshr->queue; 176 bool wasFull = mq->isFull(); 177 mq->markInService(mshr); 178 if (wasFull && !mq->isFull()) { 179 clearBlocked((BlockedCause)mq->index); 180 } 181 } 182 183 /** Block size of this cache */ 184 const int blkSize; 185 186 /** 187 * The latency of a hit in this device. 188 */ 189 int hitLatency; 190 191 /** The number of targets for each MSHR. */ 192 const int numTarget; 193 194 /** Increasing order number assigned to each incoming request. */ 195 uint64_t order; 196 197 /** 198 * Bit vector of the blocking reasons for the access path. 199 * @sa #BlockedCause 200 */ 201 uint8_t blocked; 202 203 /** Stores time the cache blocked for statistics. */ 204 Tick blockedCycle; 205 206 /** Pointer to the MSHR that has no targets. */ 207 MSHR *noTargetMSHR; 208 209 /** The number of misses to trigger an exit event. */ 210 Counter missCount; 211 212 /** The drain event. */ 213 Event *drainEvent; 214 215 public: 216 // Statistics 217 /** 218 * @addtogroup CacheStatistics 219 * @{ 220 */ 221 222 /** Number of hits per thread for each type of command. @sa Packet::Command */ 223 Stats::Vector<> hits[MemCmd::NUM_MEM_CMDS]; 224 /** Number of hits for demand accesses. */ 225 Stats::Formula demandHits; 226 /** Number of hit for all accesses. */ 227 Stats::Formula overallHits; 228 229 /** Number of misses per thread for each type of command. @sa Packet::Command */ 230 Stats::Vector<> misses[MemCmd::NUM_MEM_CMDS]; 231 /** Number of misses for demand accesses. */ 232 Stats::Formula demandMisses; 233 /** Number of misses for all accesses. */ 234 Stats::Formula overallMisses; 235 236 /** 237 * Total number of cycles per thread/command spent waiting for a miss. 238 * Used to calculate the average miss latency. 239 */ 240 Stats::Vector<> missLatency[MemCmd::NUM_MEM_CMDS]; 241 /** Total number of cycles spent waiting for demand misses. */ 242 Stats::Formula demandMissLatency; 243 /** Total number of cycles spent waiting for all misses. */ 244 Stats::Formula overallMissLatency; 245 246 /** The number of accesses per command and thread. */ 247 Stats::Formula accesses[MemCmd::NUM_MEM_CMDS]; 248 /** The number of demand accesses. */ 249 Stats::Formula demandAccesses; 250 /** The number of overall accesses. */ 251 Stats::Formula overallAccesses; 252 253 /** The miss rate per command and thread. */ 254 Stats::Formula missRate[MemCmd::NUM_MEM_CMDS]; 255 /** The miss rate of all demand accesses. */ 256 Stats::Formula demandMissRate; 257 /** The miss rate for all accesses. */ 258 Stats::Formula overallMissRate; 259 260 /** The average miss latency per command and thread. */ 261 Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS]; 262 /** The average miss latency for demand misses. */ 263 Stats::Formula demandAvgMissLatency; 264 /** The average miss latency for all misses. */ 265 Stats::Formula overallAvgMissLatency; 266 267 /** The total number of cycles blocked for each blocked cause. */ 268 Stats::Vector<> blocked_cycles; 269 /** The number of times this cache blocked for each blocked cause. */ 270 Stats::Vector<> blocked_causes; 271 272 /** The average number of cycles blocked for each blocked cause. */ 273 Stats::Formula avg_blocked; 274 275 /** The number of fast writes (WH64) performed. */ 276 Stats::Scalar<> fastWrites; 277 278 /** The number of cache copies performed. */ 279 Stats::Scalar<> cacheCopies; 280 281 /** Number of blocks written back per thread. */ 282 Stats::Vector<> writebacks; 283 284 /** Number of misses that hit in the MSHRs per command and thread. */ 285 Stats::Vector<> mshr_hits[MemCmd::NUM_MEM_CMDS]; 286 /** Demand misses that hit in the MSHRs. */ 287 Stats::Formula demandMshrHits; 288 /** Total number of misses that hit in the MSHRs. */ 289 Stats::Formula overallMshrHits; 290 291 /** Number of misses that miss in the MSHRs, per command and thread. */ 292 Stats::Vector<> mshr_misses[MemCmd::NUM_MEM_CMDS]; 293 /** Demand misses that miss in the MSHRs. */ 294 Stats::Formula demandMshrMisses; 295 /** Total number of misses that miss in the MSHRs. */ 296 Stats::Formula overallMshrMisses; 297 298 /** Number of misses that miss in the MSHRs, per command and thread. */ 299 Stats::Vector<> mshr_uncacheable[MemCmd::NUM_MEM_CMDS]; 300 /** Total number of misses that miss in the MSHRs. */ 301 Stats::Formula overallMshrUncacheable; 302 303 /** Total cycle latency of each MSHR miss, per command and thread. */ 304 Stats::Vector<> mshr_miss_latency[MemCmd::NUM_MEM_CMDS]; 305 /** Total cycle latency of demand MSHR misses. */ 306 Stats::Formula demandMshrMissLatency; 307 /** Total cycle latency of overall MSHR misses. */ 308 Stats::Formula overallMshrMissLatency; 309 310 /** Total cycle latency of each MSHR miss, per command and thread. */ 311 Stats::Vector<> mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS]; 312 /** Total cycle latency of overall MSHR misses. */ 313 Stats::Formula overallMshrUncacheableLatency; 314 315 /** The total number of MSHR accesses per command and thread. */ 316 Stats::Formula mshrAccesses[MemCmd::NUM_MEM_CMDS]; 317 /** The total number of demand MSHR accesses. */ 318 Stats::Formula demandMshrAccesses; 319 /** The total number of MSHR accesses. */ 320 Stats::Formula overallMshrAccesses; 321 322 /** The miss rate in the MSHRs pre command and thread. */ 323 Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS]; 324 /** The demand miss rate in the MSHRs. */ 325 Stats::Formula demandMshrMissRate; 326 /** The overall miss rate in the MSHRs. */ 327 Stats::Formula overallMshrMissRate; 328 329 /** The average latency of an MSHR miss, per command and thread. */ 330 Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS]; 331 /** The average latency of a demand MSHR miss. */ 332 Stats::Formula demandAvgMshrMissLatency; 333 /** The average overall latency of an MSHR miss. */ 334 Stats::Formula overallAvgMshrMissLatency; 335 336 /** The average latency of an MSHR miss, per command and thread. */ 337 Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS]; 338 /** The average overall latency of an MSHR miss. */ 339 Stats::Formula overallAvgMshrUncacheableLatency; 340 341 /** The number of times a thread hit its MSHR cap. */ 342 Stats::Vector<> mshr_cap_events; 343 /** The number of times software prefetches caused the MSHR to block. */ 344 Stats::Vector<> soft_prefetch_mshr_full; 345 346 Stats::Scalar<> mshr_no_allocate_misses; 347 348 /** 349 * @} 350 */ 351 352 /** 353 * Register stats for this object. 354 */ 355 virtual void regStats(); 356 357 public: 358 typedef BaseCacheParams Params; 359 BaseCache(const Params *p); 360 ~BaseCache() {} 361 362 virtual void init(); 363 364 /** 365 * Query block size of a cache. 366 * @return The block size 367 */ 368 int getBlockSize() const 369 { 370 return blkSize; 371 } 372 373 374 Addr blockAlign(Addr addr) const { return (addr & ~(blkSize - 1)); } 375 376 377 MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool requestBus) 378 { 379 assert(!pkt->req->isUncacheable()); 380 return allocateBufferInternal(&mshrQueue, 381 blockAlign(pkt->getAddr()), blkSize, 382 pkt, time, requestBus); 383 } 384 385 MSHR *allocateWriteBuffer(PacketPtr pkt, Tick time, bool requestBus) 386 { 387 assert(pkt->isWrite() && !pkt->isRead()); 388 return allocateBufferInternal(&writeBuffer, 389 pkt->getAddr(), pkt->getSize(), 390 pkt, time, requestBus); 391 } 392 393 MSHR *allocateUncachedReadBuffer(PacketPtr pkt, Tick time, bool requestBus) 394 { 395 assert(pkt->req->isUncacheable()); 396 assert(pkt->isRead()); 397 return allocateBufferInternal(&mshrQueue, 398 pkt->getAddr(), pkt->getSize(), 399 pkt, time, requestBus); 400 } 401 402 /** 403 * Returns true if the cache is blocked for accesses. 404 */ 405 bool isBlocked() 406 { 407 return blocked != 0; 408 } 409 410 /** 411 * Marks the access path of the cache as blocked for the given cause. This 412 * also sets the blocked flag in the slave interface. 413 * @param cause The reason for the cache blocking. 414 */ 415 void setBlocked(BlockedCause cause) 416 { 417 uint8_t flag = 1 << cause; 418 if (blocked == 0) { 419 blocked_causes[cause]++; 420 blockedCycle = curTick; 421 cpuSidePort->setBlocked(); 422 } 423 blocked |= flag; 424 DPRINTF(Cache,"Blocking for cause %d, mask=%d\n", cause, blocked); 425 } 426 427 /** 428 * Marks the cache as unblocked for the given cause. This also clears the 429 * blocked flags in the appropriate interfaces. 430 * @param cause The newly unblocked cause. 431 * @warning Calling this function can cause a blocked request on the bus to 432 * access the cache. The cache must be in a state to handle that request. 433 */ 434 void clearBlocked(BlockedCause cause) 435 { 436 uint8_t flag = 1 << cause; 437 blocked &= ~flag; 438 DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked); 439 if (blocked == 0) { 440 blocked_cycles[cause] += curTick - blockedCycle; 441 cpuSidePort->clearBlocked(); 442 } 443 } 444 445 Tick nextMSHRReadyTime() 446 { 447 return std::min(mshrQueue.nextMSHRReadyTime(), 448 writeBuffer.nextMSHRReadyTime()); 449 } 450 451 /** 452 * Request the master bus for the given cause and time. 453 * @param cause The reason for the request. 454 * @param time The time to make the request. 455 */ 456 void requestMemSideBus(RequestCause cause, Tick time) 457 { 458 memSidePort->requestBus(cause, time); 459 } 460 461 /** 462 * Clear the master bus request for the given cause. 463 * @param cause The request reason to clear. 464 */ 465 void deassertMemSideBusRequest(RequestCause cause) 466 { 467 // obsolete!! 468 assert(false); 469 // memSidePort->deassertBusRequest(cause); 470 // checkDrain(); 471 } 472 473 virtual unsigned int drain(Event *de); 474 475 virtual bool inCache(Addr addr) = 0; 476 477 virtual bool inMissQueue(Addr addr) = 0; 478 479 void incMissCount(PacketPtr pkt) 480 { 481 misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; 482 483 if (missCount) { 484 --missCount; 485 if (missCount == 0) 486 exitSimLoop("A cache reached the maximum miss count"); 487 } 488 } 489 490}; 491 492#endif //__BASE_CACHE_HH__ 493