base.hh revision 2810
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 * Declares a basic cache interface BaseCache. 34 */ 35 36#ifndef __BASE_CACHE_HH__ 37#define __BASE_CACHE_HH__ 38 39#include <vector> 40#include <string> 41#include <list> 42#include <inttypes.h> 43 44#include "base/statistics.hh" 45#include "base/trace.hh" 46#include "mem/mem_object.hh" 47#include "mem/packet.hh" 48#include "mem/port.hh" 49#include "mem/request.hh" 50 51/** 52 * Reasons for Caches to be Blocked. 53 */ 54enum BlockedCause{ 55 Blocked_NoMSHRs, 56 Blocked_NoTargets, 57 Blocked_NoWBBuffers, 58 Blocked_Coherence, 59 Blocked_Copy, 60 NUM_BLOCKED_CAUSES 61}; 62 63/** 64 * Reasons for cache to request a bus. 65 */ 66enum RequestCause{ 67 Request_MSHR, 68 Request_WB, 69 Request_Coherence, 70 Request_PF 71}; 72 73/** 74 * A basic cache interface. Implements some common functions for speed. 75 */ 76class BaseCache : public MemObject 77{ 78 class CachePort : public Port 79 { 80 BaseCache *cache; 81 82 public: 83 CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide); 84 85 private: 86 virtual bool recvTiming(Packet *pkt); 87 88 virtual Tick recvAtomic(Packet *pkt); 89 90 virtual void recvFunctional(Packet *pkt); 91 92 virtual void recvStatusChange(Status status); 93 94 virtual void getDeviceAddressRanges(AddrRangeList &resp, 95 AddrRangeList &snoop); 96 97 virtual int deviceBlockSize(); 98 99 void setBlocked(); 100 101 void clearBlocked(); 102 103 bool blocked; 104 105 bool isCpuSide; 106 }; 107 108 struct CacheEvent : public Event 109 { 110 Packet *pkt; 111 CachePort *cachePort; 112 113 CacheResponseEvent(Packet *pkt, CachePort *cachePort); 114 void process(); 115 const char *description(); 116 } 117 118 protected: 119 CachePort *cpuSidePort; 120 CachePort *memSidePort; 121 122 public: 123 virtual Port *getPort(const std::string &if_name); 124 125 private: 126 //To be defined in cache_impl.hh not in base class 127 virtual bool doTimingAccess(Packet *pkt, MemoryPort *memoryPort, bool isCpuSide); 128 virtual Tick doAtomicAccess(Packet *pkt, bool isCpuSide); 129 virtual void doFunctionalAccess(Packet *pkt, bool isCpuSide); 130 virtual void recvStatusChange(Port::Status status, bool isCpuSide); 131 132 /** 133 * Bit vector of the blocking reasons for the access path. 134 * @sa #BlockedCause 135 */ 136 uint8_t blocked; 137 138 /** 139 * Bit vector for the blocking reasons for the snoop path. 140 * @sa #BlockedCause 141 */ 142 uint8_t blockedSnoop; 143 144 /** 145 * Bit vector for the outstanding requests for the master interface. 146 */ 147 uint8_t masterRequests; 148 149 /** 150 * Bit vector for the outstanding requests for the slave interface. 151 */ 152 uint8_t slaveRequests; 153 154 protected: 155 156 /** True if this cache is connected to the CPU. */ 157 bool topLevelCache; 158 159 /** Stores time the cache blocked for statistics. */ 160 Tick blockedCycle; 161 162 /** Block size of this cache */ 163 const int blkSize; 164 165 /** The number of misses to trigger an exit event. */ 166 Counter missCount; 167 168 public: 169 // Statistics 170 /** 171 * @addtogroup CacheStatistics 172 * @{ 173 */ 174 175 /** Number of hits per thread for each type of command. @sa Packet::Command */ 176 Stats::Vector<> hits[NUM_MEM_CMDS]; 177 /** Number of hits for demand accesses. */ 178 Stats::Formula demandHits; 179 /** Number of hit for all accesses. */ 180 Stats::Formula overallHits; 181 182 /** Number of misses per thread for each type of command. @sa Packet::Command */ 183 Stats::Vector<> misses[NUM_MEM_CMDS]; 184 /** Number of misses for demand accesses. */ 185 Stats::Formula demandMisses; 186 /** Number of misses for all accesses. */ 187 Stats::Formula overallMisses; 188 189 /** 190 * Total number of cycles per thread/command spent waiting for a miss. 191 * Used to calculate the average miss latency. 192 */ 193 Stats::Vector<> missLatency[NUM_MEM_CMDS]; 194 /** Total number of cycles spent waiting for demand misses. */ 195 Stats::Formula demandMissLatency; 196 /** Total number of cycles spent waiting for all misses. */ 197 Stats::Formula overallMissLatency; 198 199 /** The number of accesses per command and thread. */ 200 Stats::Formula accesses[NUM_MEM_CMDS]; 201 /** The number of demand accesses. */ 202 Stats::Formula demandAccesses; 203 /** The number of overall accesses. */ 204 Stats::Formula overallAccesses; 205 206 /** The miss rate per command and thread. */ 207 Stats::Formula missRate[NUM_MEM_CMDS]; 208 /** The miss rate of all demand accesses. */ 209 Stats::Formula demandMissRate; 210 /** The miss rate for all accesses. */ 211 Stats::Formula overallMissRate; 212 213 /** The average miss latency per command and thread. */ 214 Stats::Formula avgMissLatency[NUM_MEM_CMDS]; 215 /** The average miss latency for demand misses. */ 216 Stats::Formula demandAvgMissLatency; 217 /** The average miss latency for all misses. */ 218 Stats::Formula overallAvgMissLatency; 219 220 /** The total number of cycles blocked for each blocked cause. */ 221 Stats::Vector<> blocked_cycles; 222 /** The number of times this cache blocked for each blocked cause. */ 223 Stats::Vector<> blocked_causes; 224 225 /** The average number of cycles blocked for each blocked cause. */ 226 Stats::Formula avg_blocked; 227 228 /** The number of fast writes (WH64) performed. */ 229 Stats::Scalar<> fastWrites; 230 231 /** The number of cache copies performed. */ 232 Stats::Scalar<> cacheCopies; 233 234 /** 235 * @} 236 */ 237 238 /** 239 * Register stats for this object. 240 */ 241 virtual void regStats(); 242 243 public: 244 245 class Params 246 { 247 public: 248 /** List of address ranges of this cache. */ 249 std::vector<Range<Addr> > addrRange; 250 /** The hit latency for this cache. */ 251 int hitLatency; 252 /** The block size of this cache. */ 253 int blkSize; 254 /** 255 * The maximum number of misses this cache should handle before 256 * ending the simulation. 257 */ 258 Counter maxMisses; 259 260 /** 261 * Construct an instance of this parameter class. 262 */ 263 Params(std::vector<Range<Addr> > addr_range, 264 int hit_latency, int _blkSize, Counter max_misses) 265 : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize), 266 maxMisses(max_misses) 267 { 268 } 269 }; 270 271 /** 272 * Create and initialize a basic cache object. 273 * @param name The name of this cache. 274 * @param hier_params Pointer to the HierParams object for this hierarchy 275 * of this cache. 276 * @param params The parameter object for this BaseCache. 277 */ 278 BaseCache(const std::string &name, HierParams *hier_params, Params ¶ms) 279 : BaseMem(name, hier_params, params.hitLatency, params.addrRange), 280 blocked(0), blockedSnoop(0), masterRequests(0), slaveRequests(0), 281 topLevelCache(false), blkSize(params.blkSize), 282 missCount(params.maxMisses) 283 { 284 } 285 286 /** 287 * Query block size of a cache. 288 * @return The block size 289 */ 290 int getBlockSize() const 291 { 292 return blkSize; 293 } 294 295 /** 296 * Returns true if this cache is connect to the CPU. 297 * @return True if this is a L1 cache. 298 */ 299 bool isTopLevel() 300 { 301 return topLevelCache; 302 } 303 304 /** 305 * Returns true if the cache is blocked for accesses. 306 */ 307 bool isBlocked() 308 { 309 return blocked != 0; 310 } 311 312 /** 313 * Returns true if the cache is blocked for snoops. 314 */ 315 bool isBlockedForSnoop() 316 { 317 return blockedSnoop != 0; 318 } 319 320 /** 321 * Marks the access path of the cache as blocked for the given cause. This 322 * also sets the blocked flag in the slave interface. 323 * @param cause The reason for the cache blocking. 324 */ 325 void setBlocked(BlockedCause cause) 326 { 327 uint8_t flag = 1 << cause; 328 if (blocked == 0) { 329 blocked_causes[cause]++; 330 blockedCycle = curTick; 331 } 332 blocked |= flag; 333 DPRINTF(Cache,"Blocking for cause %s\n", cause); 334 cpuSidePort->setBlocked(); 335 } 336 337 /** 338 * Marks the snoop path of the cache as blocked for the given cause. This 339 * also sets the blocked flag in the master interface. 340 * @param cause The reason to block the snoop path. 341 */ 342 void setBlockedForSnoop(BlockedCause cause) 343 { 344 uint8_t flag = 1 << cause; 345 blockedSnoop |= flag; 346 memSidePort->setBlocked(); 347 } 348 349 /** 350 * Marks the cache as unblocked for the given cause. This also clears the 351 * blocked flags in the appropriate interfaces. 352 * @param cause The newly unblocked cause. 353 * @warning Calling this function can cause a blocked request on the bus to 354 * access the cache. The cache must be in a state to handle that request. 355 */ 356 void clearBlocked(BlockedCause cause) 357 { 358 uint8_t flag = 1 << cause; 359 blocked &= ~flag; 360 blockedSnoop &= ~flag; 361 DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n", 362 cause, blocked); 363 if (!isBlocked()) { 364 blocked_cycles[cause] += curTick - blockedCycle; 365 DPRINTF(Cache,"Unblocking from all causes\n"); 366 cpuSidePort->clearBlocked(); 367 } 368 if (!isBlockedForSnoop()) { 369 memSidePort->clearBlocked(); 370 } 371 372 } 373 374 /** 375 * True if the master bus should be requested. 376 * @return True if there are outstanding requests for the master bus. 377 */ 378 bool doMasterRequest() 379 { 380 return masterRequests != 0; 381 } 382 383 /** 384 * Request the master bus for the given cause and time. 385 * @param cause The reason for the request. 386 * @param time The time to make the request. 387 */ 388 void setMasterRequest(RequestCause cause, Tick time) 389 { 390 uint8_t flag = 1<<cause; 391 masterRequests |= flag; 392 assert("Implement\n" && 0); 393// mi->pktuest(time); 394 } 395 396 /** 397 * Clear the master bus request for the given cause. 398 * @param cause The request reason to clear. 399 */ 400 void clearMasterRequest(RequestCause cause) 401 { 402 uint8_t flag = 1<<cause; 403 masterRequests &= ~flag; 404 } 405 406 /** 407 * Return true if the slave bus should be requested. 408 * @return True if there are outstanding requests for the slave bus. 409 */ 410 bool doSlaveRequest() 411 { 412 return slaveRequests != 0; 413 } 414 415 /** 416 * Request the slave bus for the given reason and time. 417 * @param cause The reason for the request. 418 * @param time The time to make the request. 419 */ 420 void setSlaveRequest(RequestCause cause, Tick time) 421 { 422 uint8_t flag = 1<<cause; 423 slaveRequests |= flag; 424 assert("Implement\n" && 0); 425// si->pktuest(time); 426 } 427 428 /** 429 * Clear the slave bus request for the given reason. 430 * @param cause The request reason to clear. 431 */ 432 void clearSlaveRequest(RequestCause cause) 433 { 434 uint8_t flag = 1<<cause; 435 slaveRequests &= ~flag; 436 } 437 438 /** 439 * Send a response to the slave interface. 440 * @param req The request being responded to. 441 * @param time The time the response is ready. 442 */ 443 void respond(Packet *pkt, Tick time) 444 { 445 assert("Implement\n" && 0); 446// si->respond(pkt,time); 447 } 448 449 /** 450 * Send a reponse to the slave interface and calculate miss latency. 451 * @param req The request to respond to. 452 * @param time The time the response is ready. 453 */ 454 void respondToMiss(Packet *pkt, Tick time) 455 { 456 if (!pkt->isUncacheable()) { 457 missLatency[pkt->cmd.toIndex()][pkt->thread_num] += time - pkt->time; 458 } 459 assert("Implement\n" && 0); 460// si->respond(pkt,time); 461 } 462 463 /** 464 * Suppliess the data if cache to cache transfers are enabled. 465 * @param req The bus transaction to fulfill. 466 */ 467 void respondToSnoop(Packet *pkt) 468 { 469 assert("Implement\n" && 0); 470// mi->respond(pkt,curTick + hitLatency); 471 } 472 473 /** 474 * Notification from master interface that a address range changed. Nothing 475 * to do for a cache. 476 */ 477 void rangeChange() {} 478}; 479 480#endif //__BASE_CACHE_HH__ 481