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