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