base.hh revision 3194
1892SN/A/* 21762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 3892SN/A * All rights reserved. 4892SN/A * 5892SN/A * Redistribution and use in source and binary forms, with or without 6892SN/A * modification, are permitted provided that the following conditions are 7892SN/A * met: redistributions of source code must retain the above copyright 8892SN/A * notice, this list of conditions and the following disclaimer; 9892SN/A * redistributions in binary form must reproduce the above copyright 10892SN/A * notice, this list of conditions and the following disclaimer in the 11892SN/A * documentation and/or other materials provided with the distribution; 12892SN/A * neither the name of the copyright holders nor the names of its 13892SN/A * contributors may be used to endorse or promote products derived from 14892SN/A * this software without specific prior written permission. 15892SN/A * 16892SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17892SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18892SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19892SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20892SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21892SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22892SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23892SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24892SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25892SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26892SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665SN/A * 282665SN/A * Authors: Erik Hallnor 292665SN/A */ 30892SN/A 31767SN/A/** 321730SN/A * @file 33798SN/A * Declares a basic cache interface BaseCache. 34767SN/A */ 35767SN/A 36767SN/A#ifndef __BASE_CACHE_HH__ 37767SN/A#define __BASE_CACHE_HH__ 38767SN/A 39767SN/A#include <vector> 402432SN/A#include <string> 41767SN/A#include <list> 423348SN/A#include <inttypes.h> 433348SN/A 443540Sgblack@eecs.umich.edu#include "base/misc.hh" 453540Sgblack@eecs.umich.edu#include "base/statistics.hh" 463540Sgblack@eecs.umich.edu#include "base/trace.hh" 473348SN/A#include "mem/mem_object.hh" 483348SN/A#include "mem/packet.hh" 492523SN/A#include "mem/port.hh" 50767SN/A#include "mem/request.hh" 51767SN/A#include "sim/eventq.hh" 52767SN/A 53767SN/A/** 542107SN/A * Reasons for Caches to be Blocked. 552107SN/A */ 56767SN/Aenum BlockedCause{ 572523SN/A Blocked_NoMSHRs, 582523SN/A Blocked_NoTargets, 59767SN/A Blocked_NoWBBuffers, 603846Shsul@eecs.umich.edu Blocked_Coherence, 61909SN/A Blocked_Copy, 62767SN/A NUM_BLOCKED_CAUSES 631290SN/A}; 641290SN/A 651290SN/A/** 661290SN/A * Reasons for cache to request a bus. 671290SN/A */ 681290SN/Aenum RequestCause{ 691290SN/A Request_MSHR, 701290SN/A Request_WB, 71775SN/A Request_Coherence, 72775SN/A Request_PF 73775SN/A}; 74767SN/A 75767SN/Aclass MSHR; 762523SN/A/** 773349SN/A * A basic cache interface. Implements some common functions for speed. 78767SN/A */ 792641SN/Aclass BaseCache : public MemObject 80767SN/A{ 812641SN/A class CachePort : public Port 821290SN/A { 832641SN/A public: 842641SN/A BaseCache *cache; 85767SN/A 862630SN/A CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide); 872641SN/A 88767SN/A protected: 89767SN/A virtual bool recvTiming(Packet *pkt); 903875Sbinkertn@umich.edu 913875Sbinkertn@umich.edu virtual Tick recvAtomic(Packet *pkt); 921290SN/A 931290SN/A virtual void recvFunctional(Packet *pkt); 942630SN/A 952523SN/A virtual void recvStatusChange(Status status); 961290SN/A 971290SN/A virtual void getDeviceAddressRanges(AddrRangeList &resp, 981290SN/A AddrRangeList &snoop); 991290SN/A 1002630SN/A virtual int deviceBlockSize(); 1012523SN/A 1021290SN/A virtual void recvRetry(); 1031290SN/A 1041290SN/A public: 105767SN/A void setBlocked(); 1062630SN/A 1072523SN/A void clearBlocked(); 108767SN/A 109767SN/A bool blocked; 1102523SN/A 111767SN/A bool mustSendRetry; 1122630SN/A 1132630SN/A bool isCpuSide; 1142523SN/A 115767SN/A std::list<Packet *> drainList; 116767SN/A 117767SN/A Packet *cshrRetry; 118767SN/A }; 1192630SN/A 1202523SN/A struct CacheEvent : public Event 121767SN/A { 1222630SN/A CachePort *cachePort; 1232523SN/A Packet *pkt; 124767SN/A 1252630SN/A CacheEvent(CachePort *_cachePort); 1262523SN/A CacheEvent(CachePort *_cachePort, Packet *_pkt); 127767SN/A void process(); 1282630SN/A const char *description(); 1292523SN/A }; 130767SN/A 1312630SN/A protected: 1322523SN/A CachePort *cpuSidePort; 133767SN/A CachePort *memSidePort; 1342630SN/A 1352523SN/A bool snoopRangesSent; 136767SN/A 1372630SN/A public: 1382523SN/A virtual Port *getPort(const std::string &if_name, int idx = -1); 139767SN/A 1402630SN/A private: 1412523SN/A //To be defined in cache_impl.hh not in base class 142767SN/A virtual bool doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide) 1432630SN/A { 1442523SN/A fatal("No implementation"); 145767SN/A } 1462630SN/A 1472523SN/A virtual Tick doAtomicAccess(Packet *pkt, bool isCpuSide) 148767SN/A { 149767SN/A fatal("No implementation"); 1502523SN/A } 151767SN/A 152767SN/A virtual void doFunctionalAccess(Packet *pkt, bool isCpuSide) 153767SN/A { 154767SN/A fatal("No implementation"); 155767SN/A } 1562523SN/A 157767SN/A void recvStatusChange(Port::Status status, bool isCpuSide) 158767SN/A { 159767SN/A if (status == Port::RangeChange){ 160767SN/A if (!isCpuSide) { 161767SN/A cpuSidePort->sendStatusChange(Port::RangeChange); 1622523SN/A if (!snoopRangesSent) { 1631290SN/A snoopRangesSent = true; 1642630SN/A memSidePort->sendStatusChange(Port::RangeChange); 1652523SN/A } 1661290SN/A } 1672630SN/A else { 1682523SN/A memSidePort->sendStatusChange(Port::RangeChange); 169768SN/A } 170768SN/A } 171767SN/A } 172767SN/A 173767SN/A virtual Packet *getPacket() 174767SN/A { 175767SN/A fatal("No implementation"); 176767SN/A } 177767SN/A 178768SN/A virtual Packet *getCoherencePacket() 179767SN/A { 1802549SN/A fatal("No implementation"); 1812641SN/A } 182767SN/A 1834870Sstever@eecs.umich.edu virtual void sendResult(Packet* &pkt, MSHR* mshr, bool success) 1842523SN/A { 185767SN/A 186767SN/A fatal("No implementation"); 1872523SN/A } 1883349SN/A 189767SN/A /** 1902641SN/A * Bit vector of the blocking reasons for the access path. 1912641SN/A * @sa #BlockedCause 1922641SN/A */ 1932539SN/A uint8_t blocked; 1942523SN/A 1952641SN/A /** 1962523SN/A * Bit vector for the blocking reasons for the snoop path. 1972641SN/A * @sa #BlockedCause 198767SN/A */ 199830SN/A uint8_t blockedSnoop; 200830SN/A 201767SN/A /** 2022539SN/A * Bit vector for the outstanding requests for the master interface. 2032539SN/A */ 2042539SN/A uint8_t masterRequests; 2051290SN/A 2062539SN/A /** 2072539SN/A * Bit vector for the outstanding requests for the slave interface. 2082539SN/A */ 2091290SN/A uint8_t slaveRequests; 2102539SN/A 2112539SN/A protected: 2122630SN/A 2132539SN/A /** True if this cache is connected to the CPU. */ 2142539SN/A bool topLevelCache; 2152539SN/A 2162539SN/A 2172539SN/A /** Stores time the cache blocked for statistics. */ 2182539SN/A Tick blockedCycle; 2192539SN/A 2202539SN/A /** Block size of this cache */ 2212539SN/A const int blkSize; 2222539SN/A 2232539SN/A /** The number of misses to trigger an exit event. */ 2242539SN/A Counter missCount; 2252539SN/A 2262539SN/A public: 2272539SN/A // Statistics 2282539SN/A /** 2292539SN/A * @addtogroup CacheStatistics 2302539SN/A * @{ 2312539SN/A */ 2322539SN/A 2332539SN/A /** Number of hits per thread for each type of command. @sa Packet::Command */ 2342539SN/A Stats::Vector<> hits[NUM_MEM_CMDS]; 2351290SN/A /** Number of hits for demand accesses. */ 2361074SN/A Stats::Formula demandHits; 2371074SN/A /** Number of hit for all accesses. */ 2382539SN/A Stats::Formula overallHits; 2392539SN/A 2402539SN/A /** Number of misses per thread for each type of command. @sa Packet::Command */ 2412539SN/A Stats::Vector<> misses[NUM_MEM_CMDS]; 2422539SN/A /** Number of misses for demand accesses. */ 2432539SN/A Stats::Formula demandMisses; 2442539SN/A /** Number of misses for all accesses. */ 2452539SN/A Stats::Formula overallMisses; 2462539SN/A 2472539SN/A /** 2482539SN/A * Total number of cycles per thread/command spent waiting for a miss. 2492630SN/A * Used to calculate the average miss latency. 2502539SN/A */ 2512539SN/A Stats::Vector<> missLatency[NUM_MEM_CMDS]; 2522539SN/A /** Total number of cycles spent waiting for demand misses. */ 2532539SN/A Stats::Formula demandMissLatency; 2542539SN/A /** Total number of cycles spent waiting for all misses. */ 2552539SN/A Stats::Formula overallMissLatency; 2562539SN/A 2572539SN/A /** The number of accesses per command and thread. */ 2582630SN/A Stats::Formula accesses[NUM_MEM_CMDS]; 2592539SN/A /** The number of demand accesses. */ 2602539SN/A Stats::Formula demandAccesses; 2612539SN/A /** The number of overall accesses. */ 2622539SN/A Stats::Formula overallAccesses; 2632539SN/A 2642539SN/A /** The miss rate per command and thread. */ 2652539SN/A Stats::Formula missRate[NUM_MEM_CMDS]; 2662630SN/A /** The miss rate of all demand accesses. */ 2672539SN/A Stats::Formula demandMissRate; 2682539SN/A /** The miss rate for all accesses. */ 2692539SN/A Stats::Formula overallMissRate; 2702539SN/A 2712539SN/A /** The average miss latency per command and thread. */ 2722539SN/A Stats::Formula avgMissLatency[NUM_MEM_CMDS]; 2732630SN/A /** The average miss latency for demand misses. */ 2742539SN/A Stats::Formula demandAvgMissLatency; 2752539SN/A /** The average miss latency for all misses. */ 2762539SN/A Stats::Formula overallAvgMissLatency; 2772539SN/A 2782539SN/A /** The total number of cycles blocked for each blocked cause. */ 2792549SN/A Stats::Vector<> blocked_cycles; 2802539SN/A /** The number of times this cache blocked for each blocked cause. */ 2812539SN/A Stats::Vector<> blocked_causes; 2822539SN/A 2832539SN/A /** The average number of cycles blocked for each blocked cause. */ 2842539SN/A Stats::Formula avg_blocked; 2852539SN/A 2862539SN/A /** The number of fast writes (WH64) performed. */ 2872539SN/A Stats::Scalar<> fastWrites; 2882539SN/A 2892539SN/A /** The number of cache copies performed. */ 2902539SN/A Stats::Scalar<> cacheCopies; 2912539SN/A 2922539SN/A /** 2932539SN/A * @} 2942539SN/A */ 2952539SN/A 2962539SN/A /** 2972539SN/A * Register stats for this object. 2982539SN/A */ 2992539SN/A virtual void regStats(); 3002539SN/A 3012539SN/A public: 3022539SN/A 3032539SN/A class Params 3042539SN/A { 3052630SN/A public: 3062539SN/A /** List of address ranges of this cache. */ 3072539SN/A std::vector<Range<Addr> > addrRange; 3082539SN/A /** The hit latency for this cache. */ 3092539SN/A int hitLatency; 3102539SN/A /** The block size of this cache. */ 3112539SN/A int blkSize; 3122539SN/A /** 3132539SN/A * The maximum number of misses this cache should handle before 3142539SN/A * ending the simulation. 3152539SN/A */ 3162539SN/A Counter maxMisses; 3172539SN/A 3182539SN/A /** 3192539SN/A * Construct an instance of this parameter class. 3202539SN/A */ 3212539SN/A Params(std::vector<Range<Addr> > addr_range, 3222539SN/A int hit_latency, int _blkSize, Counter max_misses) 3232539SN/A : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize), 3242539SN/A maxMisses(max_misses) 3252539SN/A { 3262539SN/A } 3272539SN/A }; 3282539SN/A 3292539SN/A /** 3302539SN/A * Create and initialize a basic cache object. 3312539SN/A * @param name The name of this cache. 3322539SN/A * @param hier_params Pointer to the HierParams object for this hierarchy 3331074SN/A * of this cache. 3342539SN/A * @param params The parameter object for this BaseCache. 3352539SN/A */ 3362539SN/A BaseCache(const std::string &name, Params ¶ms) 3372539SN/A : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0), 3382539SN/A slaveRequests(0), topLevelCache(false), blkSize(params.blkSize), 3392539SN/A missCount(params.maxMisses) 3402539SN/A { 3412539SN/A //Start ports at null if more than one is created we should panic 3422539SN/A cpuSidePort = NULL; 3432539SN/A memSidePort = NULL; 3442539SN/A snoopRangesSent = false; 3452539SN/A } 3462539SN/A 3472539SN/A virtual void init(); 3482539SN/A 3492539SN/A /** 3502539SN/A * Query block size of a cache. 3512539SN/A * @return The block size 3522539SN/A */ 3532539SN/A int getBlockSize() const 3542539SN/A { 3552630SN/A return blkSize; 3562539SN/A } 3572539SN/A 3582630SN/A /** 3592539SN/A * Returns true if this cache is connect to the CPU. 3602539SN/A * @return True if this is a L1 cache. 3612630SN/A */ 3622539SN/A bool isTopLevel() 3632539SN/A { 3642539SN/A return topLevelCache; 3652539SN/A } 3662539SN/A 3674870Sstever@eecs.umich.edu /** 3682539SN/A * Returns true if the cache is blocked for accesses. 369767SN/A */ 370767SN/A bool isBlocked() 371767SN/A { 3721290SN/A return blocked != 0; 3731290SN/A } 3744103Ssaidi@eecs.umich.edu 3751290SN/A /** 3761290SN/A * Returns true if the cache is blocked for snoops. 3771290SN/A */ 3781290SN/A bool isBlockedForSnoop() 3791290SN/A { 3801290SN/A return blockedSnoop != 0; 3811290SN/A } 3821290SN/A 3831290SN/A /** 3841290SN/A * Marks the access path of the cache as blocked for the given cause. This 3851290SN/A * also sets the blocked flag in the slave interface. 3861290SN/A * @param cause The reason for the cache blocking. 3871290SN/A */ 3881290SN/A void setBlocked(BlockedCause cause) 3891290SN/A { 3901290SN/A uint8_t flag = 1 << cause; 3911290SN/A if (blocked == 0) { 3921290SN/A blocked_causes[cause]++; 3931290SN/A blockedCycle = curTick; 3941290SN/A } 3951290SN/A if (!(blocked & flag)) { 3961290SN/A //Wasn't already blocked for this cause 3971290SN/A blocked |= flag; 3981290SN/A DPRINTF(Cache,"Blocking for cause %s\n", cause); 3991290SN/A cpuSidePort->setBlocked(); 4004103Ssaidi@eecs.umich.edu } 4011290SN/A } 4021290SN/A 4031290SN/A /** 4041290SN/A * Marks the snoop path of the cache as blocked for the given cause. This 4051290SN/A * also sets the blocked flag in the master interface. 4061290SN/A * @param cause The reason to block the snoop path. 4071290SN/A */ 4081290SN/A void setBlockedForSnoop(BlockedCause cause) 4091290SN/A { 4101290SN/A uint8_t flag = 1 << cause; 4111290SN/A if (!(blocked & flag)) { 4121290SN/A //Wasn't already blocked for this cause 4131290SN/A blockedSnoop |= flag; 4141290SN/A memSidePort->setBlocked(); 4151290SN/A } 4161290SN/A } 4171290SN/A 4181290SN/A /** 4191290SN/A * Marks the cache as unblocked for the given cause. This also clears the 4204103Ssaidi@eecs.umich.edu * blocked flags in the appropriate interfaces. 4211290SN/A * @param cause The newly unblocked cause. 4221290SN/A * @warning Calling this function can cause a blocked request on the bus to 4231290SN/A * access the cache. The cache must be in a state to handle that request. 4241290SN/A */ 4251290SN/A void clearBlocked(BlockedCause cause) 4261290SN/A { 4271290SN/A uint8_t flag = 1 << cause; 4281290SN/A DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n", 4291290SN/A cause, blocked); 4301290SN/A if (blocked & flag) 4311290SN/A { 4321290SN/A blocked &= ~flag; 4331290SN/A if (!isBlocked()) { 4341290SN/A blocked_cycles[cause] += curTick - blockedCycle; 4351290SN/A DPRINTF(Cache,"Unblocking from all causes\n"); 4361290SN/A cpuSidePort->clearBlocked(); 4371290SN/A } 4381290SN/A } 4391290SN/A if (blockedSnoop & flag) 4401290SN/A { 4411290SN/A blockedSnoop &= ~flag; 4421290SN/A if (!isBlockedForSnoop()) { 4431290SN/A memSidePort->clearBlocked(); 4441290SN/A } 445831SN/A } 446831SN/A } 4474103Ssaidi@eecs.umich.edu 4481290SN/A /** 449831SN/A * True if the master bus should be requested. 450831SN/A * @return True if there are outstanding requests for the master bus. 4511290SN/A */ 4522539SN/A bool doMasterRequest() 4532539SN/A { 4542539SN/A return masterRequests != 0; 4552539SN/A } 4562539SN/A 457831SN/A /** 458831SN/A * Request the master bus for the given cause and time. 459831SN/A * @param cause The reason for the request. 460831SN/A * @param time The time to make the request. 461831SN/A */ 462817SN/A void setMasterRequest(RequestCause cause, Tick time) 463777SN/A { 4641290SN/A if (!doMasterRequest()) 4654103Ssaidi@eecs.umich.edu { 4661290SN/A BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(memSidePort); 467777SN/A reqCpu->schedule(time); 4681290SN/A } 469831SN/A uint8_t flag = 1<<cause; 470817SN/A masterRequests |= flag; 4712539SN/A } 4722539SN/A 4732539SN/A /** 474817SN/A * Clear the master bus request for the given cause. 4752539SN/A * @param cause The request reason to clear. 476777SN/A */ 477777SN/A void clearMasterRequest(RequestCause cause) 478777SN/A { 479777SN/A uint8_t flag = 1<<cause; 480817SN/A masterRequests &= ~flag; 481777SN/A } 4821290SN/A 4834103Ssaidi@eecs.umich.edu /** 4841290SN/A * Return true if the slave bus should be requested. 4851290SN/A * @return True if there are outstanding requests for the slave bus. 486817SN/A */ 487817SN/A bool doSlaveRequest() 488817SN/A { 489831SN/A return slaveRequests != 0; 4902539SN/A } 4912539SN/A 4922539SN/A /** 493817SN/A * Request the slave bus for the given reason and time. 494777SN/A * @param cause The reason for the request. 4952539SN/A * @param time The time to make the request. 4962539SN/A */ 497777SN/A void setSlaveRequest(RequestCause cause, Tick time) 498777SN/A { 499817SN/A uint8_t flag = 1<<cause; 500817SN/A slaveRequests |= flag; 501777SN/A assert("Implement\n" && 0); 502777SN/A// si->pktuest(time); 503909SN/A } 504777SN/A 505767SN/A /** 506767SN/A * Clear the slave bus request for the given reason. 507811SN/A * @param cause The request reason to clear. 508811SN/A */ 5091290SN/A void clearSlaveRequest(RequestCause cause) 5101290SN/A { 511811SN/A uint8_t flag = 1<<cause; 512767SN/A slaveRequests &= ~flag; 513767SN/A } 514767SN/A 515767SN/A /** 516767SN/A * Send a response to the slave interface. 517811SN/A * @param pkt The request being responded to. 518811SN/A * @param time The time the response is ready. 5191290SN/A */ 5201290SN/A void respond(Packet *pkt, Tick time) 521811SN/A { 522767SN/A if (pkt->needsResponse()) { 523767SN/A CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 524767SN/A reqCpu->schedule(time); 525767SN/A } 5262539SN/A } 5272539SN/A 5282539SN/A /** 5292539SN/A * Send a reponse to the slave interface and calculate miss latency. 530775SN/A * @param pkt The request to respond to. 531767SN/A * @param time The time the response is ready. 532767SN/A */ 533767SN/A void respondToMiss(Packet *pkt, Tick time) 534767SN/A { 535767SN/A if (!pkt->req->isUncacheable()) { 5362539SN/A missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += time - pkt->time; 5372539SN/A } 5382539SN/A if (pkt->needsResponse()) { 5392539SN/A CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 5402539SN/A reqCpu->schedule(time); 541767SN/A } 542767SN/A } 543767SN/A 544767SN/A /** 545767SN/A * Suppliess the data if cache to cache transfers are enabled. 5462539SN/A * @param pkt The bus transaction to fulfill. 5472539SN/A */ 5482539SN/A void respondToSnoop(Packet *pkt, Tick time) 5492539SN/A { 5502539SN/A// assert("Implement\n" && 0); 5512539SN/A// mi->respond(pkt,curTick + hitLatency); 5522539SN/A assert (pkt->needsResponse()); 5532539SN/A CacheEvent *reqMem = new CacheEvent(memSidePort, pkt); 554767SN/A reqMem->schedule(time); 555767SN/A } 556767SN/A 557 /** 558 * Notification from master interface that a address range changed. Nothing 559 * to do for a cache. 560 */ 561 void rangeChange() {} 562 563 void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide) 564 { 565 if (isCpuSide) 566 { 567 AddrRangeList dummy; 568 memSidePort->getPeerAddressRanges(resp, dummy); 569 } 570 else 571 { 572 //This is where snoops get updated 573 AddrRangeList dummy; 574// if (!topLevelCache) 575// { 576 cpuSidePort->getPeerAddressRanges(dummy, snoop); 577// } 578// else 579// { 580// snoop.push_back(RangeSize(0,-1)); 581// } 582 583 return; 584 } 585 } 586}; 587 588#endif //__BASE_CACHE_HH__ 589