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