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