base.hh revision 3606
18504SN/A/* 28504SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 38504SN/A * All rights reserved. 48825Snilay@cs.wisc.edu * 58504SN/A * Redistribution and use in source and binary forms, with or without 68504SN/A * modification, are permitted provided that the following conditions are 78504SN/A * met: redistributions of source code must retain the above copyright 88504SN/A * notice, this list of conditions and the following disclaimer; 98504SN/A * redistributions in binary form must reproduce the above copyright 108504SN/A * notice, this list of conditions and the following disclaimer in the 118835SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 128504SN/A * neither the name of the copyright holders nor the names of its 138504SN/A * contributors may be used to endorse or promote products derived from 148504SN/A * this software without specific prior written permission. 158504SN/A * 168504SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 178504SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189039Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 198504SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 208504SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 218504SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 228673SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 238504SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 248504SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258504SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 268504SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278504SN/A * 288504SN/A * Authors: Erik Hallnor 298504SN/A */ 308504SN/A 318504SN/A/** 328504SN/A * @file 338963Sgblack@eecs.umich.edu * Declares a basic cache interface BaseCache. 348504SN/A */ 358504SN/A 368504SN/A#ifndef __BASE_CACHE_HH__ 378504SN/A#define __BASE_CACHE_HH__ 388504SN/A 398504SN/A#include <vector> 408504SN/A#include <string> 418504SN/A#include <list> 428504SN/A#include <inttypes.h> 438504SN/A 448504SN/A#include "base/misc.hh" 458504SN/A#include "base/statistics.hh" 468504SN/A#include "base/trace.hh" 478504SN/A#include "mem/mem_object.hh" 488504SN/A#include "mem/packet.hh" 498504SN/A#include "mem/port.hh" 508504SN/A#include "mem/request.hh" 518504SN/A#include "sim/eventq.hh" 528835SAli.Saidi@ARM.com 538835SAli.Saidi@ARM.com/** 548835SAli.Saidi@ARM.com * Reasons for Caches to be Blocked. 558835SAli.Saidi@ARM.com */ 568835SAli.Saidi@ARM.comenum BlockedCause{ 578835SAli.Saidi@ARM.com Blocked_NoMSHRs, 588835SAli.Saidi@ARM.com Blocked_NoTargets, 598835SAli.Saidi@ARM.com Blocked_NoWBBuffers, 608963Sgblack@eecs.umich.edu Blocked_Coherence, 618963Sgblack@eecs.umich.edu NUM_BLOCKED_CAUSES 628835SAli.Saidi@ARM.com}; 638504SN/A 648504SN/A/** 658504SN/A * Reasons for cache to request a bus. 668504SN/A */ 678721SN/Aenum RequestCause{ 688721SN/A Request_MSHR, 698721SN/A Request_WB, 708504SN/A Request_Coherence, 718963Sgblack@eecs.umich.edu Request_PF 728963Sgblack@eecs.umich.edu}; 738504SN/A 748504SN/Aclass MSHR; 758504SN/A/** 768504SN/A * A basic cache interface. Implements some common functions for speed. 778504SN/A */ 788504SN/Aclass BaseCache : public MemObject 798504SN/A{ 808504SN/A class CachePort : public Port 818504SN/A { 828504SN/A public: 838504SN/A BaseCache *cache; 848504SN/A 858504SN/A CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide); 868504SN/A 878504SN/A protected: 888504SN/A virtual bool recvTiming(PacketPtr pkt); 898504SN/A 908504SN/A virtual Tick recvAtomic(PacketPtr pkt); 918504SN/A 928504SN/A virtual void recvFunctional(PacketPtr pkt); 938504SN/A 948504SN/A virtual void recvStatusChange(Status status); 958504SN/A 968504SN/A virtual void getDeviceAddressRanges(AddrRangeList &resp, 978504SN/A AddrRangeList &snoop); 988504SN/A 998504SN/A virtual int deviceBlockSize(); 1008504SN/A 1018504SN/A virtual void recvRetry(); 1028504SN/A 1038504SN/A public: 1048504SN/A void setBlocked(); 1058504SN/A 1068504SN/A void clearBlocked(); 1078504SN/A 1088504SN/A bool checkFunctional(PacketPtr pkt); 1098504SN/A 1108504SN/A void checkAndSendFunctional(PacketPtr pkt); 1118504SN/A 1128504SN/A bool canDrain() { return drainList.empty() && transmitList.empty(); } 1138504SN/A 1148504SN/A bool blocked; 1158504SN/A 1168504SN/A bool mustSendRetry; 1178504SN/A 1188504SN/A bool isCpuSide; 1198504SN/A 1208504SN/A bool waitingOnRetry; 1218504SN/A 1228504SN/A std::list<PacketPtr> drainList; 1238504SN/A 1248504SN/A std::list<std::pair<Tick,PacketPtr> > transmitList; 1258504SN/A }; 1268504SN/A 1278504SN/A struct CacheEvent : public Event 1288504SN/A { 1298504SN/A CachePort *cachePort; 1308504SN/A PacketPtr pkt; 1318504SN/A bool newResponse; 1328504SN/A 1338504SN/A CacheEvent(CachePort *_cachePort, bool response); 1348504SN/A void process(); 1358728SN/A const char *description(); 1368504SN/A }; 1378504SN/A 1388504SN/A public: //Made public so coherence can get at it. 1398504SN/A CachePort *cpuSidePort; 1408504SN/A 1418504SN/A CacheEvent *sendEvent; 1428504SN/A CacheEvent *memSendEvent; 1438504SN/A 1448504SN/A protected: 1458504SN/A CachePort *memSidePort; 1468504SN/A 1478504SN/A bool snoopRangesSent; 1488504SN/A 1498504SN/A public: 1508504SN/A virtual Port *getPort(const std::string &if_name, int idx = -1); 1518504SN/A 1528504SN/A private: 1538504SN/A //To be defined in cache_impl.hh not in base class 1548504SN/A virtual bool doTimingAccess(PacketPtr pkt, CachePort *cachePort, bool isCpuSide) 1558504SN/A { 1568504SN/A fatal("No implementation"); 1578504SN/A } 1588504SN/A 1598504SN/A virtual Tick doAtomicAccess(PacketPtr pkt, bool isCpuSide) 1608504SN/A { 1618521SN/A fatal("No implementation"); 1628504SN/A } 1638504SN/A 1648504SN/A virtual void doFunctionalAccess(PacketPtr pkt, bool isCpuSide) 1658504SN/A { 1668504SN/A fatal("No implementation"); 1678825Snilay@cs.wisc.edu } 1688504SN/A 1698504SN/A void recvStatusChange(Port::Status status, bool isCpuSide) 1708504SN/A { 1718504SN/A if (status == Port::RangeChange){ 1728504SN/A if (!isCpuSide) { 1738963Sgblack@eecs.umich.edu cpuSidePort->sendStatusChange(Port::RangeChange); 1748504SN/A if (!snoopRangesSent) { 1758504SN/A snoopRangesSent = true; 1768504SN/A memSidePort->sendStatusChange(Port::RangeChange); 1778504SN/A } 1788504SN/A } 1798504SN/A else { 1808504SN/A memSidePort->sendStatusChange(Port::RangeChange); 1818504SN/A } 1828504SN/A } 1838835SAli.Saidi@ARM.com } 1848504SN/A 1858504SN/A virtual PacketPtr getPacket() 1868504SN/A { 1878504SN/A fatal("No implementation"); 1888835SAli.Saidi@ARM.com } 1898504SN/A 1908504SN/A virtual PacketPtr getCoherencePacket() 1918504SN/A { 1928504SN/A fatal("No implementation"); 1938504SN/A } 1948963Sgblack@eecs.umich.edu 1958504SN/A virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success) 1968504SN/A { 1978504SN/A 1988504SN/A fatal("No implementation"); 1998504SN/A } 2008504SN/A 2018504SN/A virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success) 2028504SN/A { 2038504SN/A 2048504SN/A fatal("No implementation"); 2058504SN/A } 2068504SN/A 2078504SN/A /** 2088504SN/A * Bit vector of the blocking reasons for the access path. 2098963Sgblack@eecs.umich.edu * @sa #BlockedCause 2108504SN/A */ 2118504SN/A uint8_t blocked; 2128504SN/A 2138504SN/A /** 2148504SN/A * Bit vector for the blocking reasons for the snoop path. 2158504SN/A * @sa #BlockedCause 2168504SN/A */ 2178504SN/A uint8_t blockedSnoop; 2188504SN/A 2198835SAli.Saidi@ARM.com /** 2208504SN/A * Bit vector for the outstanding requests for the master interface. 2218504SN/A */ 2228504SN/A uint8_t masterRequests; 2238504SN/A 2248835SAli.Saidi@ARM.com /** 2258504SN/A * Bit vector for the outstanding requests for the slave interface. 2268504SN/A */ 2278504SN/A uint8_t slaveRequests; 2288504SN/A 2298504SN/A protected: 2308963Sgblack@eecs.umich.edu 2318504SN/A /** Stores time the cache blocked for statistics. */ 2328504SN/A Tick blockedCycle; 2338504SN/A 2348504SN/A /** Block size of this cache */ 2358504SN/A const int blkSize; 2368504SN/A 2378504SN/A /** The number of misses to trigger an exit event. */ 2388504SN/A Counter missCount; 2398504SN/A 2408504SN/A /** The drain event. */ 2418504SN/A Event *drainEvent; 2428504SN/A 2438504SN/A public: 2448504SN/A // Statistics 2458504SN/A /** 2468504SN/A * @addtogroup CacheStatistics 2478504SN/A * @{ 2488504SN/A */ 2498504SN/A 2508504SN/A /** Number of hits per thread for each type of command. @sa Packet::Command */ 2518504SN/A Stats::Vector<> hits[NUM_MEM_CMDS]; 2528504SN/A /** Number of hits for demand accesses. */ 2538504SN/A Stats::Formula demandHits; 2548504SN/A /** Number of hit for all accesses. */ 2558504SN/A Stats::Formula overallHits; 2568504SN/A 2578504SN/A /** Number of misses per thread for each type of command. @sa Packet::Command */ 2588504SN/A Stats::Vector<> misses[NUM_MEM_CMDS]; 2598504SN/A /** Number of misses for demand accesses. */ 2608504SN/A Stats::Formula demandMisses; 2618504SN/A /** Number of misses for all accesses. */ 2628504SN/A Stats::Formula overallMisses; 2638504SN/A 2648504SN/A /** 2658504SN/A * Total number of cycles per thread/command spent waiting for a miss. 2668504SN/A * Used to calculate the average miss latency. 2678504SN/A */ 2688504SN/A Stats::Vector<> missLatency[NUM_MEM_CMDS]; 2698504SN/A /** Total number of cycles spent waiting for demand misses. */ 2708504SN/A Stats::Formula demandMissLatency; 2718504SN/A /** Total number of cycles spent waiting for all misses. */ 2728504SN/A Stats::Formula overallMissLatency; 2738504SN/A 2748504SN/A /** The number of accesses per command and thread. */ 2758504SN/A Stats::Formula accesses[NUM_MEM_CMDS]; 2768504SN/A /** The number of demand accesses. */ 2778504SN/A Stats::Formula demandAccesses; 2788504SN/A /** The number of overall accesses. */ 2798504SN/A Stats::Formula overallAccesses; 2808504SN/A 2818504SN/A /** The miss rate per command and thread. */ 2828504SN/A Stats::Formula missRate[NUM_MEM_CMDS]; 2838504SN/A /** The miss rate of all demand accesses. */ 2848504SN/A Stats::Formula demandMissRate; 2858504SN/A /** The miss rate for all accesses. */ 2868504SN/A Stats::Formula overallMissRate; 2878504SN/A 2888504SN/A /** The average miss latency per command and thread. */ 2898504SN/A Stats::Formula avgMissLatency[NUM_MEM_CMDS]; 2908504SN/A /** The average miss latency for demand misses. */ 2918504SN/A Stats::Formula demandAvgMissLatency; 2928504SN/A /** The average miss latency for all misses. */ 2938504SN/A Stats::Formula overallAvgMissLatency; 2948504SN/A 2958504SN/A /** The total number of cycles blocked for each blocked cause. */ 2968504SN/A Stats::Vector<> blocked_cycles; 2978504SN/A /** The number of times this cache blocked for each blocked cause. */ 2988504SN/A Stats::Vector<> blocked_causes; 2998504SN/A 3008504SN/A /** The average number of cycles blocked for each blocked cause. */ 3018504SN/A Stats::Formula avg_blocked; 3028504SN/A 3038504SN/A /** The number of fast writes (WH64) performed. */ 3048504SN/A Stats::Scalar<> fastWrites; 3058504SN/A 3068504SN/A /** The number of cache copies performed. */ 3078504SN/A Stats::Scalar<> cacheCopies; 3088504SN/A 3098504SN/A /** 3108504SN/A * @} 3118504SN/A */ 3128504SN/A 3138504SN/A /** 3148504SN/A * Register stats for this object. 3158504SN/A */ 3168504SN/A virtual void regStats(); 3178504SN/A 3188504SN/A public: 3198504SN/A 3208504SN/A class Params 3218504SN/A { 3228504SN/A public: 3238504SN/A /** List of address ranges of this cache. */ 3248504SN/A std::vector<Range<Addr> > addrRange; 3258504SN/A /** The hit latency for this cache. */ 3268504SN/A int hitLatency; 3278504SN/A /** The block size of this cache. */ 3288504SN/A int blkSize; 3298504SN/A /** 3308504SN/A * The maximum number of misses this cache should handle before 3318504SN/A * ending the simulation. 3328504SN/A */ 3338504SN/A Counter maxMisses; 3348504SN/A 3358504SN/A /** 3368504SN/A * Construct an instance of this parameter class. 3378504SN/A */ 3388504SN/A Params(std::vector<Range<Addr> > addr_range, 3398504SN/A int hit_latency, int _blkSize, Counter max_misses) 3408504SN/A : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize), 3418504SN/A maxMisses(max_misses) 3428504SN/A { 3438504SN/A } 3448504SN/A }; 3458504SN/A 3468504SN/A /** 3478504SN/A * Create and initialize a basic cache object. 3488504SN/A * @param name The name of this cache. 3498504SN/A * @param hier_params Pointer to the HierParams object for this hierarchy 3508504SN/A * of this cache. 3518504SN/A * @param params The parameter object for this BaseCache. 3528504SN/A */ 3538504SN/A BaseCache(const std::string &name, Params ¶ms) 3548504SN/A : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0), 3558504SN/A slaveRequests(0), blkSize(params.blkSize), 3568504SN/A missCount(params.maxMisses), drainEvent(NULL) 3578504SN/A { 3588504SN/A //Start ports at null if more than one is created we should panic 3598504SN/A cpuSidePort = NULL; 3608504SN/A memSidePort = NULL; 3618504SN/A snoopRangesSent = false; 3628504SN/A } 3638504SN/A 3648504SN/A ~BaseCache() 3658504SN/A { 3668504SN/A delete sendEvent; 3678504SN/A delete memSendEvent; 3688504SN/A } 3698504SN/A 3708504SN/A virtual void init(); 3718504SN/A 3728504SN/A /** 3738504SN/A * Query block size of a cache. 3748504SN/A * @return The block size 3758504SN/A */ 3768504SN/A int getBlockSize() const 3778504SN/A { 3788504SN/A return blkSize; 3798504SN/A } 3808504SN/A 3818504SN/A /** 3828504SN/A * Returns true if the cache is blocked for accesses. 3838504SN/A */ 3848504SN/A bool isBlocked() 3858504SN/A { 3868504SN/A return blocked != 0; 3878504SN/A } 3888504SN/A 3898504SN/A /** 3908504SN/A * Returns true if the cache is blocked for snoops. 3918504SN/A */ 3928504SN/A bool isBlockedForSnoop() 3938504SN/A { 3948504SN/A return blockedSnoop != 0; 3958504SN/A } 3968504SN/A 3978504SN/A /** 3988504SN/A * Marks the access path of the cache as blocked for the given cause. This 3998504SN/A * also sets the blocked flag in the slave interface. 4008504SN/A * @param cause The reason for the cache blocking. 4018504SN/A */ 4028504SN/A void setBlocked(BlockedCause cause) 4038504SN/A { 4048504SN/A uint8_t flag = 1 << cause; 4058504SN/A if (blocked == 0) { 4068504SN/A blocked_causes[cause]++; 4078504SN/A blockedCycle = curTick; 4088504SN/A } 4098504SN/A int old_state = blocked; 4108504SN/A if (!(blocked & flag)) { 4118504SN/A //Wasn't already blocked for this cause 4128504SN/A blocked |= flag; 4138504SN/A DPRINTF(Cache,"Blocking for cause %s\n", cause); 4148504SN/A if (!old_state) 4158504SN/A cpuSidePort->setBlocked(); 4168504SN/A } 4178504SN/A } 4188504SN/A 4198504SN/A /** 4208504SN/A * Marks the snoop path of the cache as blocked for the given cause. This 4218504SN/A * also sets the blocked flag in the master interface. 4228504SN/A * @param cause The reason to block the snoop path. 4238504SN/A */ 4248504SN/A void setBlockedForSnoop(BlockedCause cause) 4258504SN/A { 4268504SN/A uint8_t flag = 1 << cause; 4278504SN/A uint8_t old_state = blockedSnoop; 4288504SN/A if (!(blockedSnoop & flag)) { 4298504SN/A //Wasn't already blocked for this cause 4308504SN/A blockedSnoop |= flag; 4318504SN/A if (!old_state) 4328504SN/A memSidePort->setBlocked(); 4338504SN/A } 4348504SN/A } 4358504SN/A 4368504SN/A /** 4378504SN/A * Marks the cache as unblocked for the given cause. This also clears the 4388504SN/A * blocked flags in the appropriate interfaces. 4398504SN/A * @param cause The newly unblocked cause. 4408504SN/A * @warning Calling this function can cause a blocked request on the bus to 4418504SN/A * access the cache. The cache must be in a state to handle that request. 4428504SN/A */ 4438504SN/A void clearBlocked(BlockedCause cause) 4448504SN/A { 4458504SN/A uint8_t flag = 1 << cause; 4468504SN/A DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n", 4478504SN/A cause, blocked); 4488504SN/A if (blocked & flag) 4498504SN/A { 4508504SN/A blocked &= ~flag; 4518504SN/A if (!isBlocked()) { 4528504SN/A blocked_cycles[cause] += curTick - blockedCycle; 4538504SN/A DPRINTF(Cache,"Unblocking from all causes\n"); 4548504SN/A cpuSidePort->clearBlocked(); 4558504SN/A } 4568504SN/A } 4578504SN/A if (blockedSnoop & flag) 4588504SN/A { 4598504SN/A blockedSnoop &= ~flag; 4608504SN/A if (!isBlockedForSnoop()) { 4618504SN/A memSidePort->clearBlocked(); 4628504SN/A } 4638504SN/A } 4648504SN/A } 4658504SN/A 4668504SN/A /** 4678504SN/A * True if the master bus should be requested. 4688504SN/A * @return True if there are outstanding requests for the master bus. 4698504SN/A */ 4708504SN/A bool doMasterRequest() 4718504SN/A { 4728504SN/A return masterRequests != 0; 4738504SN/A } 4748504SN/A 4758504SN/A /** 4768504SN/A * Request the master bus for the given cause and time. 4778504SN/A * @param cause The reason for the request. 4788504SN/A * @param time The time to make the request. 4798504SN/A */ 4808504SN/A void setMasterRequest(RequestCause cause, Tick time) 4818504SN/A { 4828504SN/A if (!doMasterRequest() && !memSidePort->waitingOnRetry) 4838504SN/A { 4848504SN/A BaseCache::CacheEvent * reqCpu = 4858504SN/A new BaseCache::CacheEvent(memSidePort, false); 4868504SN/A reqCpu->schedule(time); 4878504SN/A } 4888504SN/A uint8_t flag = 1<<cause; 4898504SN/A masterRequests |= flag; 4908504SN/A } 4918504SN/A 4928504SN/A /** 4938504SN/A * Clear the master bus request for the given cause. 4948504SN/A * @param cause The request reason to clear. 4958504SN/A */ 4968504SN/A void clearMasterRequest(RequestCause cause) 4978963Sgblack@eecs.umich.edu { 4988504SN/A uint8_t flag = 1<<cause; 4998504SN/A masterRequests &= ~flag; 5008504SN/A checkDrain(); 5018504SN/A } 5028504SN/A 5038504SN/A /** 5048504SN/A * Return true if the slave bus should be requested. 5058504SN/A * @return True if there are outstanding requests for the slave bus. 5068504SN/A */ 5078835SAli.Saidi@ARM.com bool doSlaveRequest() 5088504SN/A { 5098504SN/A return slaveRequests != 0; 5108504SN/A } 5118504SN/A 5128835SAli.Saidi@ARM.com /** 5138504SN/A * Request the slave bus for the given reason and time. 5148504SN/A * @param cause The reason for the request. 5158504SN/A * @param time The time to make the request. 5168504SN/A */ 5178504SN/A void setSlaveRequest(RequestCause cause, Tick time) 5188963Sgblack@eecs.umich.edu { 5198504SN/A if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry) 5208504SN/A { 5218504SN/A BaseCache::CacheEvent * reqCpu = 5228504SN/A new BaseCache::CacheEvent(cpuSidePort, false); 5238504SN/A reqCpu->schedule(time); 5248504SN/A } 5258504SN/A uint8_t flag = 1<<cause; 5268963Sgblack@eecs.umich.edu slaveRequests |= flag; 5278963Sgblack@eecs.umich.edu } 5288963Sgblack@eecs.umich.edu 5298504SN/A /** 5308504SN/A * Clear the slave bus request for the given reason. 5318504SN/A * @param cause The request reason to clear. 5328504SN/A */ 5338504SN/A void clearSlaveRequest(RequestCause cause) 5348504SN/A { 5358504SN/A uint8_t flag = 1<<cause; 5368504SN/A slaveRequests &= ~flag; 5378504SN/A checkDrain(); 5388504SN/A } 5398504SN/A 5408504SN/A /** 5418504SN/A * Send a response to the slave interface. 5428504SN/A * @param pkt The request being responded to. 5438963Sgblack@eecs.umich.edu * @param time The time the response is ready. 5448504SN/A */ 5458504SN/A void respond(PacketPtr pkt, Tick time) 5468504SN/A { 5478504SN/A assert(time >= curTick); 5488504SN/A if (pkt->needsResponse()) { 5498504SN/A/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 5508504SN/A reqCpu->schedule(time); 5518504SN/A*/ 5528504SN/A if (cpuSidePort->transmitList.empty()) { 5538835SAli.Saidi@ARM.com assert(!sendEvent->scheduled()); 5548504SN/A sendEvent->schedule(time); 5558504SN/A cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 5568504SN/A (time,pkt)); 5578504SN/A return; 5588835SAli.Saidi@ARM.com } 5598504SN/A 5608504SN/A // something is on the list and this belongs at the end 5618504SN/A if (time >= cpuSidePort->transmitList.back().first) { 5628504SN/A cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 5638504SN/A (time,pkt)); 5648963Sgblack@eecs.umich.edu return; 5658504SN/A } 5668504SN/A // Something is on the list and this belongs somewhere else 5678504SN/A std::list<std::pair<Tick,PacketPtr> >::iterator i = 5688504SN/A cpuSidePort->transmitList.begin(); 5698504SN/A std::list<std::pair<Tick,PacketPtr> >::iterator end = 5708504SN/A cpuSidePort->transmitList.end(); 5718504SN/A bool done = false; 5728504SN/A 5738504SN/A while (i != end && !done) { 5748504SN/A if (time < i->first) 5758504SN/A cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr> 5768504SN/A (time,pkt)); 5778504SN/A i++; 5788504SN/A } 5798504SN/A } 5808504SN/A else { 5818504SN/A if (pkt->cmd != Packet::UpgradeReq) 5828504SN/A { 5838504SN/A delete pkt->req; 5848504SN/A delete pkt; 5858504SN/A } 5868504SN/A } 5878504SN/A } 5888504SN/A 5898504SN/A /** 5908504SN/A * Send a reponse to the slave interface and calculate miss latency. 5918504SN/A * @param pkt The request to respond to. 5928504SN/A * @param time The time the response is ready. 5938504SN/A */ 5948504SN/A void respondToMiss(PacketPtr pkt, Tick time) 5958504SN/A { 5968504SN/A assert(time >= curTick); 5978504SN/A if (!pkt->req->isUncacheable()) { 5988504SN/A missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += 5998504SN/A time - pkt->time; 6008504SN/A } 6018504SN/A if (pkt->needsResponse()) { 6028504SN/A/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 6038504SN/A reqCpu->schedule(time); 6048504SN/A*/ 6058504SN/A if (cpuSidePort->transmitList.empty()) { 6068504SN/A assert(!sendEvent->scheduled()); 6078504SN/A sendEvent->schedule(time); 6088504SN/A cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 6098504SN/A (time,pkt)); 6108504SN/A return; 6118504SN/A } 6128504SN/A 6138504SN/A // something is on the list and this belongs at the end 6148504SN/A if (time >= cpuSidePort->transmitList.back().first) { 6158504SN/A cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 6168504SN/A (time,pkt)); 6178504SN/A return; 6188504SN/A } 6198504SN/A // Something is on the list and this belongs somewhere else 6208504SN/A std::list<std::pair<Tick,PacketPtr> >::iterator i = 6218504SN/A cpuSidePort->transmitList.begin(); 6228504SN/A std::list<std::pair<Tick,PacketPtr> >::iterator end = 6238504SN/A cpuSidePort->transmitList.end(); 6248504SN/A bool done = false; 6258504SN/A 6268504SN/A while (i != end && !done) { 6278504SN/A if (time < i->first) 6288504SN/A cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr> 6298504SN/A (time,pkt)); 6308504SN/A i++; 6318504SN/A } 6328504SN/A } 6338504SN/A else { 6348504SN/A if (pkt->cmd != Packet::UpgradeReq) 6358504SN/A { 6368504SN/A delete pkt->req; 6378504SN/A delete pkt; 6388504SN/A } 6398504SN/A } 6408504SN/A } 6418504SN/A 6428504SN/A /** 6438504SN/A * Suppliess the data if cache to cache transfers are enabled. 6448504SN/A * @param pkt The bus transaction to fulfill. 6458504SN/A */ 6468504SN/A void respondToSnoop(PacketPtr pkt, Tick time) 6478504SN/A { 6488504SN/A assert(time >= curTick); 6498504SN/A assert (pkt->needsResponse()); 6508504SN/A/* CacheEvent *reqMem = new CacheEvent(memSidePort, pkt); 6518504SN/A reqMem->schedule(time); 6528504SN/A*/ 6538504SN/A if (memSidePort->transmitList.empty()) { 6548504SN/A assert(!memSendEvent->scheduled()); 6558504SN/A memSendEvent->schedule(time); 6568504SN/A memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 6578504SN/A (time,pkt)); 6588504SN/A return; 6598504SN/A } 6608504SN/A 6618504SN/A // something is on the list and this belongs at the end 6628504SN/A if (time >= memSidePort->transmitList.back().first) { 6638504SN/A memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 6648504SN/A (time,pkt)); 6658504SN/A return; 6668504SN/A } 6678504SN/A // Something is on the list and this belongs somewhere else 6688504SN/A std::list<std::pair<Tick,PacketPtr> >::iterator i = 6698504SN/A memSidePort->transmitList.begin(); 6708504SN/A std::list<std::pair<Tick,PacketPtr> >::iterator end = 6718504SN/A memSidePort->transmitList.end(); 6728504SN/A bool done = false; 6738504SN/A 6748504SN/A while (i != end && !done) { 6758504SN/A if (time < i->first) 6768504SN/A memSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt)); 6778504SN/A i++; 6788504SN/A } 6798504SN/A } 6808504SN/A 6818504SN/A /** 6828504SN/A * Notification from master interface that a address range changed. Nothing 6838504SN/A * to do for a cache. 6848504SN/A */ 6858504SN/A void rangeChange() {} 6868504SN/A 6878504SN/A void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide) 6888504SN/A { 6898504SN/A if (isCpuSide) 6908504SN/A { 6918504SN/A AddrRangeList dummy; 6928504SN/A memSidePort->getPeerAddressRanges(resp, dummy); 6938504SN/A } 6948504SN/A else 6958504SN/A { 6968504SN/A //This is where snoops get updated 6978504SN/A AddrRangeList dummy; 6988504SN/A cpuSidePort->getPeerAddressRanges(dummy, snoop); 6998504SN/A return; 7008504SN/A } 7018504SN/A } 7028504SN/A 7038504SN/A virtual unsigned int drain(Event *de); 7048504SN/A 7058504SN/A void checkDrain() 7068504SN/A { 7078504SN/A if (drainEvent && canDrain()) { 7088504SN/A drainEvent->process(); 7098504SN/A changeState(SimObject::Drained); 7108504SN/A // Clear the drain event 7118504SN/A drainEvent = NULL; 7128504SN/A } 7138504SN/A } 7148504SN/A 7158504SN/A bool canDrain() 7168504SN/A { 7178504SN/A if (doMasterRequest() || doSlaveRequest()) { 7188504SN/A return false; 7198504SN/A } else if (memSidePort && !memSidePort->canDrain()) { 7208504SN/A return false; 7218504SN/A } else if (cpuSidePort && !cpuSidePort->canDrain()) { 7228504SN/A return false; 7238504SN/A } 7248504SN/A return true; 7258504SN/A } 7268504SN/A}; 7278504SN/A 7288504SN/A#endif //__BASE_CACHE_HH__ 7298504SN/A