base.hh revision 3126
12SN/A/* 21762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Erik Hallnor 292665Ssaidi@eecs.umich.edu */ 302SN/A 312SN/A/** 321717SN/A * @file 331717SN/A * Declares a basic cache interface BaseCache. 342SN/A */ 352SN/A 362SN/A#ifndef __BASE_CACHE_HH__ 374182Sgblack@eecs.umich.edu#define __BASE_CACHE_HH__ 38707SN/A 391858SN/A#include <vector> 4056SN/A#include <string> 414776Sgblack@eecs.umich.edu#include <list> 422856Srdreslin@umich.edu#include <inttypes.h> 432SN/A 443520Sgblack@eecs.umich.edu#include "base/misc.hh" 453520Sgblack@eecs.umich.edu#include "base/statistics.hh" 463520Sgblack@eecs.umich.edu#include "base/trace.hh" 473520Sgblack@eecs.umich.edu#include "mem/mem_object.hh" 482190SN/A#include "mem/packet.hh" 492315SN/A#include "mem/port.hh" 502680Sktlim@umich.edu#include "mem/request.hh" 512SN/A#include "sim/eventq.hh" 522856Srdreslin@umich.edu 532SN/A/** 544182Sgblack@eecs.umich.edu * Reasons for Caches to be Blocked. 554182Sgblack@eecs.umich.edu */ 564182Sgblack@eecs.umich.eduenum BlockedCause{ 574182Sgblack@eecs.umich.edu Blocked_NoMSHRs, 584182Sgblack@eecs.umich.edu Blocked_NoTargets, 592356SN/A Blocked_NoWBBuffers, 602356SN/A Blocked_Coherence, 612356SN/A Blocked_Copy, 622356SN/A NUM_BLOCKED_CAUSES 632356SN/A}; 642356SN/A 652356SN/A/** 662356SN/A * Reasons for cache to request a bus. 673126Sktlim@umich.edu */ 682356SN/Aenum RequestCause{ 692356SN/A Request_MSHR, 702356SN/A Request_WB, 712356SN/A Request_Coherence, 722356SN/A Request_PF 732356SN/A}; 742856Srdreslin@umich.edu 752SN/A/** 761634SN/A * A basic cache interface. Implements some common functions for speed. 771634SN/A */ 781695SN/Aclass BaseCache : public MemObject 793814Ssaidi@eecs.umich.edu{ 803814Ssaidi@eecs.umich.edu class CachePort : public Port 811634SN/A { 821634SN/A public: 832359SN/A BaseCache *cache; 841695SN/A 855100Ssaidi@eecs.umich.edu CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide); 861695SN/A 875099Ssaidi@eecs.umich.edu protected: 883814Ssaidi@eecs.umich.edu virtual bool recvTiming(Packet *pkt); 893814Ssaidi@eecs.umich.edu 901634SN/A virtual Tick recvAtomic(Packet *pkt); 913495Sktlim@umich.edu 923495Sktlim@umich.edu virtual void recvFunctional(Packet *pkt); 933495Sktlim@umich.edu 943495Sktlim@umich.edu virtual void recvStatusChange(Status status); 953495Sktlim@umich.edu 963495Sktlim@umich.edu virtual void getDeviceAddressRanges(AddrRangeList &resp, 973495Sktlim@umich.edu AddrRangeList &snoop); 983495Sktlim@umich.edu 993495Sktlim@umich.edu virtual int deviceBlockSize(); 1003495Sktlim@umich.edu 1013495Sktlim@umich.edu virtual void recvRetry(); 1023495Sktlim@umich.edu 1033495Sktlim@umich.edu public: 1043495Sktlim@umich.edu void setBlocked(); 1051858SN/A 1062SN/A void clearBlocked(); 1073520Sgblack@eecs.umich.edu 1083520Sgblack@eecs.umich.edu bool blocked; 1093520Sgblack@eecs.umich.edu 1102SN/A bool mustSendRetry; 1112SN/A 1122SN/A bool isCpuSide; 1132SN/A }; 1142SN/A 1154103Ssaidi@eecs.umich.edu struct CacheEvent : public Event 1162SN/A { 1173521Sgblack@eecs.umich.edu CachePort *cachePort; 1183521Sgblack@eecs.umich.edu Packet *pkt; 1191917SN/A 1201917SN/A CacheEvent(CachePort *_cachePort); 1211917SN/A CacheEvent(CachePort *_cachePort, Packet *_pkt); 1221917SN/A void process(); 1231917SN/A const char *description(); 1241917SN/A }; 1251917SN/A 1261917SN/A protected: 1271917SN/A CachePort *cpuSidePort; 1281917SN/A CachePort *memSidePort; 1291917SN/A 1301917SN/A public: 1312SN/A virtual Port *getPort(const std::string &if_name, int idx = -1); 1322SN/A 1332SN/A private: 1342680Sktlim@umich.edu //To be defined in cache_impl.hh not in base class 1354182Sgblack@eecs.umich.edu virtual bool doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide) 1362SN/A { 1374776Sgblack@eecs.umich.edu fatal("No implementation"); 1384776Sgblack@eecs.umich.edu } 1392SN/A 140393SN/A virtual Tick doAtomicAccess(Packet *pkt, bool isCpuSide) 1414776Sgblack@eecs.umich.edu { 1424776Sgblack@eecs.umich.edu fatal("No implementation"); 1434776Sgblack@eecs.umich.edu } 144393SN/A 145393SN/A virtual void doFunctionalAccess(Packet *pkt, bool isCpuSide) 146393SN/A { 147393SN/A fatal("No implementation"); 148393SN/A } 149393SN/A 150393SN/A void recvStatusChange(Port::Status status, bool isCpuSide) 151393SN/A { 152393SN/A if (status == Port::RangeChange) 153393SN/A { 154393SN/A if (!isCpuSide) 155393SN/A { 156393SN/A cpuSidePort->sendStatusChange(Port::RangeChange); 1572SN/A } 1584000Ssaidi@eecs.umich.edu else 1594000Ssaidi@eecs.umich.edu { 1604000Ssaidi@eecs.umich.edu memSidePort->sendStatusChange(Port::RangeChange); 1614000Ssaidi@eecs.umich.edu } 1624000Ssaidi@eecs.umich.edu } 1634000Ssaidi@eecs.umich.edu } 1642SN/A 1651400SN/A virtual Packet *getPacket() 1661400SN/A { 1671400SN/A fatal("No implementation"); 1681400SN/A } 1691400SN/A 1701400SN/A virtual Packet *getCoherencePacket() 1711400SN/A { 1721400SN/A fatal("No implementation"); 1731400SN/A } 1741695SN/A 1751400SN/A virtual void sendResult(Packet* &pkt, bool success) 1761400SN/A { 1772378SN/A 1783170Sstever@eecs.umich.edu fatal("No implementation"); 1794776Sgblack@eecs.umich.edu } 1804776Sgblack@eecs.umich.edu 1813661Srdreslin@umich.edu /** 1821858SN/A * Bit vector of the blocking reasons for the access path. 1831917SN/A * @sa #BlockedCause 1843617Sbinkertn@umich.edu */ 1853617Sbinkertn@umich.edu uint8_t blocked; 1863617Sbinkertn@umich.edu 1873617Sbinkertn@umich.edu /** 1881400SN/A * Bit vector for the blocking reasons for the snoop path. 1892356SN/A * @sa #BlockedCause 1902315SN/A */ 1911917SN/A uint8_t blockedSnoop; 1925222Sksewell@umich.edu 1935222Sksewell@umich.edu /** 1945222Sksewell@umich.edu * Bit vector for the outstanding requests for the master interface. 1955222Sksewell@umich.edu */ 1965222Sksewell@umich.edu uint8_t masterRequests; 1975222Sksewell@umich.edu 1985222Sksewell@umich.edu /** 1995222Sksewell@umich.edu * Bit vector for the outstanding requests for the slave interface. 2005222Sksewell@umich.edu */ 2015222Sksewell@umich.edu uint8_t slaveRequests; 2025222Sksewell@umich.edu 2035222Sksewell@umich.edu protected: 2045222Sksewell@umich.edu 2055222Sksewell@umich.edu /** True if this cache is connected to the CPU. */ 2065222Sksewell@umich.edu bool topLevelCache; 2075222Sksewell@umich.edu 2085222Sksewell@umich.edu /** Stores time the cache blocked for statistics. */ 2095222Sksewell@umich.edu Tick blockedCycle; 2105222Sksewell@umich.edu 2115222Sksewell@umich.edu /** Block size of this cache */ 2125222Sksewell@umich.edu const int blkSize; 2135222Sksewell@umich.edu 2145222Sksewell@umich.edu /** The number of misses to trigger an exit event. */ 2155222Sksewell@umich.edu Counter missCount; 2165222Sksewell@umich.edu 2175222Sksewell@umich.edu public: 2185222Sksewell@umich.edu // Statistics 2195222Sksewell@umich.edu /** 2205222Sksewell@umich.edu * @addtogroup CacheStatistics 2215222Sksewell@umich.edu * @{ 2225222Sksewell@umich.edu */ 2235222Sksewell@umich.edu 2245222Sksewell@umich.edu /** Number of hits per thread for each type of command. @sa Packet::Command */ 2255222Sksewell@umich.edu Stats::Vector<> hits[NUM_MEM_CMDS]; 2265222Sksewell@umich.edu /** Number of hits for demand accesses. */ 2275222Sksewell@umich.edu Stats::Formula demandHits; 2285222Sksewell@umich.edu /** Number of hit for all accesses. */ 2295222Sksewell@umich.edu Stats::Formula overallHits; 2305222Sksewell@umich.edu 2315222Sksewell@umich.edu /** Number of misses per thread for each type of command. @sa Packet::Command */ 2325222Sksewell@umich.edu Stats::Vector<> misses[NUM_MEM_CMDS]; 2335222Sksewell@umich.edu /** Number of misses for demand accesses. */ 2345222Sksewell@umich.edu Stats::Formula demandMisses; 2355222Sksewell@umich.edu /** Number of misses for all accesses. */ 2365222Sksewell@umich.edu Stats::Formula overallMisses; 2375222Sksewell@umich.edu 2385222Sksewell@umich.edu /** 2395222Sksewell@umich.edu * Total number of cycles per thread/command spent waiting for a miss. 2405222Sksewell@umich.edu * Used to calculate the average miss latency. 2415222Sksewell@umich.edu */ 2425222Sksewell@umich.edu Stats::Vector<> missLatency[NUM_MEM_CMDS]; 2435222Sksewell@umich.edu /** Total number of cycles spent waiting for demand misses. */ 2445222Sksewell@umich.edu Stats::Formula demandMissLatency; 2455222Sksewell@umich.edu /** Total number of cycles spent waiting for all misses. */ 2465222Sksewell@umich.edu Stats::Formula overallMissLatency; 2475222Sksewell@umich.edu 2485222Sksewell@umich.edu /** The number of accesses per command and thread. */ 2495222Sksewell@umich.edu Stats::Formula accesses[NUM_MEM_CMDS]; 2505222Sksewell@umich.edu /** The number of demand accesses. */ 2515222Sksewell@umich.edu Stats::Formula demandAccesses; 2525222Sksewell@umich.edu /** The number of overall accesses. */ 2535222Sksewell@umich.edu Stats::Formula overallAccesses; 2545222Sksewell@umich.edu 2555222Sksewell@umich.edu /** The miss rate per command and thread. */ 2565222Sksewell@umich.edu Stats::Formula missRate[NUM_MEM_CMDS]; 2575222Sksewell@umich.edu /** The miss rate of all demand accesses. */ 2585222Sksewell@umich.edu Stats::Formula demandMissRate; 2595222Sksewell@umich.edu /** The miss rate for all accesses. */ 2605222Sksewell@umich.edu Stats::Formula overallMissRate; 2615222Sksewell@umich.edu 2625222Sksewell@umich.edu /** The average miss latency per command and thread. */ 2631917SN/A Stats::Formula avgMissLatency[NUM_MEM_CMDS]; 2641400SN/A /** The average miss latency for demand misses. */ 2652SN/A Stats::Formula demandAvgMissLatency; 2661400SN/A /** The average miss latency for all misses. */ 2672SN/A Stats::Formula overallAvgMissLatency; 2681400SN/A 2691191SN/A /** The total number of cycles blocked for each blocked cause. */ 2702SN/A Stats::Vector<> blocked_cycles; 2711129SN/A /** The number of times this cache blocked for each blocked cause. */ 2721917SN/A Stats::Vector<> blocked_causes; 2732SN/A 2742SN/A /** The average number of cycles blocked for each blocked cause. */ 2752103SN/A Stats::Formula avg_blocked; 2762103SN/A 2772680Sktlim@umich.edu /** The number of fast writes (WH64) performed. */ 278180SN/A Stats::Scalar<> fastWrites; 2791492SN/A 2801492SN/A /** The number of cache copies performed. */ 2812798Sktlim@umich.edu Stats::Scalar<> cacheCopies; 282180SN/A 283180SN/A /** 284180SN/A * @} 2854192Sktlim@umich.edu */ 286180SN/A 287124SN/A /** 288124SN/A * Register stats for this object. 289124SN/A */ 290124SN/A virtual void regStats(); 2912SN/A 2922SN/A public: 293124SN/A 294124SN/A class Params 295124SN/A { 296124SN/A public: 297124SN/A /** List of address ranges of this cache. */ 298503SN/A std::vector<Range<Addr> > addrRange; 2992SN/A /** The hit latency for this cache. */ 300124SN/A int hitLatency; 301124SN/A /** The block size of this cache. */ 302124SN/A int blkSize; 303124SN/A /** 304124SN/A * The maximum number of misses this cache should handle before 305124SN/A * ending the simulation. 306124SN/A */ 3072SN/A Counter maxMisses; 308921SN/A 3093661Srdreslin@umich.edu /** 3103661Srdreslin@umich.edu * Construct an instance of this parameter class. 3112378SN/A */ 312921SN/A Params(std::vector<Range<Addr> > addr_range, 313921SN/A int hit_latency, int _blkSize, Counter max_misses) 314921SN/A : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize), 315921SN/A maxMisses(max_misses) 316921SN/A { 317921SN/A } 318921SN/A }; 319921SN/A 320921SN/A /** 321921SN/A * Create and initialize a basic cache object. 322921SN/A * @param name The name of this cache. 323921SN/A * @param hier_params Pointer to the HierParams object for this hierarchy 324921SN/A * of this cache. 3252SN/A * @param params The parameter object for this BaseCache. 3262SN/A */ 327124SN/A BaseCache(const std::string &name, Params ¶ms) 328124SN/A : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0), 329124SN/A slaveRequests(0), topLevelCache(false), blkSize(params.blkSize), 330124SN/A missCount(params.maxMisses) 3312SN/A { 3322SN/A //Start ports at null if more than one is created we should panic 333707SN/A cpuSidePort = NULL; 334707SN/A memSidePort = NULL; 3351191SN/A } 3361191SN/A 3371191SN/A virtual void init(); 3381191SN/A 3391191SN/A /** 3401191SN/A * Query block size of a cache. 3411191SN/A * @return The block size 3421191SN/A */ 3431191SN/A int getBlockSize() const 3441191SN/A { 3451191SN/A return blkSize; 3461191SN/A } 3471191SN/A 3481191SN/A /** 3491191SN/A * Returns true if this cache is connect to the CPU. 3501191SN/A * @return True if this is a L1 cache. 3511191SN/A */ 3522SN/A bool isTopLevel() 3532SN/A { 3542SN/A return topLevelCache; 3552SN/A } 3562SN/A 357707SN/A /** 358707SN/A * Returns true if the cache is blocked for accesses. 359707SN/A */ 360707SN/A bool isBlocked() 361707SN/A { 362707SN/A return blocked != 0; 363707SN/A } 364707SN/A 365707SN/A /** 366707SN/A * Returns true if the cache is blocked for snoops. 367707SN/A */ 368707SN/A bool isBlockedForSnoop() 369707SN/A { 370729SN/A return blockedSnoop != 0; 3712SN/A } 3722SN/A 3731717SN/A /** 374 * Marks the access path of the cache as blocked for the given cause. This 375 * also sets the blocked flag in the slave interface. 376 * @param cause The reason for the cache blocking. 377 */ 378 void setBlocked(BlockedCause cause) 379 { 380 uint8_t flag = 1 << cause; 381 if (blocked == 0) { 382 blocked_causes[cause]++; 383 blockedCycle = curTick; 384 } 385 blocked |= flag; 386 DPRINTF(Cache,"Blocking for cause %s\n", cause); 387 cpuSidePort->setBlocked(); 388 } 389 390 /** 391 * Marks the snoop path of the cache as blocked for the given cause. This 392 * also sets the blocked flag in the master interface. 393 * @param cause The reason to block the snoop path. 394 */ 395 void setBlockedForSnoop(BlockedCause cause) 396 { 397 uint8_t flag = 1 << cause; 398 blockedSnoop |= flag; 399 memSidePort->setBlocked(); 400 } 401 402 /** 403 * Marks the cache as unblocked for the given cause. This also clears the 404 * blocked flags in the appropriate interfaces. 405 * @param cause The newly unblocked cause. 406 * @warning Calling this function can cause a blocked request on the bus to 407 * access the cache. The cache must be in a state to handle that request. 408 */ 409 void clearBlocked(BlockedCause cause) 410 { 411 uint8_t flag = 1 << cause; 412 DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n", 413 cause, blocked); 414 if (blocked & flag) 415 { 416 blocked &= ~flag; 417 if (!isBlocked()) { 418 blocked_cycles[cause] += curTick - blockedCycle; 419 DPRINTF(Cache,"Unblocking from all causes\n"); 420 cpuSidePort->clearBlocked(); 421 } 422 } 423 if (blockedSnoop & flag) 424 { 425 blockedSnoop &= ~flag; 426 if (!isBlockedForSnoop()) { 427 memSidePort->clearBlocked(); 428 } 429 } 430 } 431 432 /** 433 * True if the master bus should be requested. 434 * @return True if there are outstanding requests for the master bus. 435 */ 436 bool doMasterRequest() 437 { 438 return masterRequests != 0; 439 } 440 441 /** 442 * Request the master bus for the given cause and time. 443 * @param cause The reason for the request. 444 * @param time The time to make the request. 445 */ 446 void setMasterRequest(RequestCause cause, Tick time) 447 { 448 if (!doMasterRequest()) 449 { 450 BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(memSidePort); 451 reqCpu->schedule(time); 452 } 453 uint8_t flag = 1<<cause; 454 masterRequests |= flag; 455 } 456 457 /** 458 * Clear the master bus request for the given cause. 459 * @param cause The request reason to clear. 460 */ 461 void clearMasterRequest(RequestCause cause) 462 { 463 uint8_t flag = 1<<cause; 464 masterRequests &= ~flag; 465 } 466 467 /** 468 * Return true if the slave bus should be requested. 469 * @return True if there are outstanding requests for the slave bus. 470 */ 471 bool doSlaveRequest() 472 { 473 return slaveRequests != 0; 474 } 475 476 /** 477 * Request the slave bus for the given reason and time. 478 * @param cause The reason for the request. 479 * @param time The time to make the request. 480 */ 481 void setSlaveRequest(RequestCause cause, Tick time) 482 { 483 uint8_t flag = 1<<cause; 484 slaveRequests |= flag; 485 assert("Implement\n" && 0); 486// si->pktuest(time); 487 } 488 489 /** 490 * Clear the slave bus request for the given reason. 491 * @param cause The request reason to clear. 492 */ 493 void clearSlaveRequest(RequestCause cause) 494 { 495 uint8_t flag = 1<<cause; 496 slaveRequests &= ~flag; 497 } 498 499 /** 500 * Send a response to the slave interface. 501 * @param pkt The request being responded to. 502 * @param time The time the response is ready. 503 */ 504 void respond(Packet *pkt, Tick time) 505 { 506 pkt->makeTimingResponse(); 507 pkt->result = Packet::Success; 508 CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 509 reqCpu->schedule(time); 510 } 511 512 /** 513 * Send a reponse to the slave interface and calculate miss latency. 514 * @param pkt The request to respond to. 515 * @param time The time the response is ready. 516 */ 517 void respondToMiss(Packet *pkt, Tick time) 518 { 519 if (!pkt->req->isUncacheable()) { 520 missLatency[pkt->cmdToIndex()][pkt->req->getThreadNum()] += time - pkt->time; 521 } 522 pkt->makeTimingResponse(); 523 pkt->result = Packet::Success; 524 CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 525 reqCpu->schedule(time); 526 } 527 528 /** 529 * Suppliess the data if cache to cache transfers are enabled. 530 * @param pkt The bus transaction to fulfill. 531 */ 532 void respondToSnoop(Packet *pkt) 533 { 534 assert("Implement\n" && 0); 535// mi->respond(pkt,curTick + hitLatency); 536 } 537 538 /** 539 * Notification from master interface that a address range changed. Nothing 540 * to do for a cache. 541 */ 542 void rangeChange() {} 543 544 void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide) 545 { 546 if (isCpuSide) 547 { 548 AddrRangeList dummy; 549 memSidePort->getPeerAddressRanges(resp, dummy); 550 } 551 else 552 { 553 //This is where snoops get updated 554 return; 555 } 556 } 557}; 558 559#endif //__BASE_CACHE_HH__ 560