base.hh revision 3738
15703SN/A/* 25703SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 35703SN/A * All rights reserved. 48825Snilay@cs.wisc.edu * 57935SN/A * Redistribution and use in source and binary forms, with or without 67935SN/A * modification, are permitted provided that the following conditions are 77935SN/A * met: redistributions of source code must retain the above copyright 85703SN/A * notice, this list of conditions and the following disclaimer; 95703SN/A * redistributions in binary form must reproduce the above copyright 105703SN/A * notice, this list of conditions and the following disclaimer in the 115703SN/A * documentation and/or other materials provided with the distribution; 125703SN/A * neither the name of the copyright holders nor the names of its 135703SN/A * contributors may be used to endorse or promote products derived from 148835SAli.Saidi@ARM.com * this software without specific prior written permission. 155703SN/A * 168835SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177670SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185703SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 198464SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 208721SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 218835SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225703SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235703SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245703SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255703SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265703SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277935SN/A * 287935SN/A * Authors: Erik Hallnor 297935SN/A */ 307935SN/A 317935SN/A/** 327935SN/A * @file 337935SN/A * Declares a basic cache interface BaseCache. 348721SN/A */ 355703SN/A 365703SN/A#ifndef __BASE_CACHE_HH__ 375703SN/A#define __BASE_CACHE_HH__ 385703SN/A 395703SN/A#include <vector> 408721SN/A#include <string> 418721SN/A#include <list> 428721SN/A#include <inttypes.h> 435703SN/A 448721SN/A#include "base/misc.hh" 458721SN/A#include "base/statistics.hh" 465703SN/A#include "base/trace.hh" 475703SN/A#include "mem/mem_object.hh" 485703SN/A#include "mem/packet.hh" 495703SN/A#include "mem/port.hh" 505703SN/A#include "mem/request.hh" 515703SN/A#include "sim/eventq.hh" 525703SN/A 535703SN/A/** 548241SN/A * Reasons for Caches to be Blocked. 558241SN/A */ 565703SN/Aenum BlockedCause{ 575703SN/A Blocked_NoMSHRs, 585703SN/A Blocked_NoTargets, 595703SN/A Blocked_NoWBBuffers, 605703SN/A Blocked_Coherence, 615703SN/A NUM_BLOCKED_CAUSES 625876SN/A}; 635703SN/A 645703SN/A/** 655703SN/A * Reasons for cache to request a bus. 665703SN/A */ 675703SN/Aenum RequestCause{ 685703SN/A Request_MSHR, 695703SN/A Request_WB, 705703SN/A Request_Coherence, 715703SN/A Request_PF 725703SN/A}; 735703SN/A 745703SN/Aclass MSHR; 755703SN/A/** 765703SN/A * A basic cache interface. Implements some common functions for speed. 775703SN/A */ 785703SN/Aclass BaseCache : public MemObject 795703SN/A{ 805703SN/A class CachePort : public Port 815703SN/A { 825703SN/A public: 835703SN/A BaseCache *cache; 845703SN/A 855703SN/A protected: 865703SN/A CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide); 875703SN/A virtual void recvStatusChange(Status status); 885703SN/A 895703SN/A virtual void getDeviceAddressRanges(AddrRangeList &resp, 905703SN/A AddrRangeList &snoop); 915703SN/A 925703SN/A virtual int deviceBlockSize(); 935703SN/A 945703SN/A virtual void recvRetry(); 955703SN/A 965703SN/A public: 975703SN/A void setBlocked(); 985703SN/A 995703SN/A void clearBlocked(); 1005703SN/A 1015703SN/A bool checkFunctional(PacketPtr pkt); 1025703SN/A 1035703SN/A void checkAndSendFunctional(PacketPtr pkt); 1045703SN/A 1055703SN/A bool canDrain() { return drainList.empty() && transmitList.empty(); } 1065703SN/A 1075703SN/A bool blocked; 1088825Snilay@cs.wisc.edu 1095703SN/A bool mustSendRetry; 1105703SN/A 1115703SN/A bool isCpuSide; 1125703SN/A 1135703SN/A bool waitingOnRetry; 1145703SN/A 1155703SN/A std::list<PacketPtr> drainList; 1165703SN/A 1175703SN/A std::list<std::pair<Tick,PacketPtr> > transmitList; 1185703SN/A }; 1195703SN/A 1205703SN/A struct CacheEvent : public Event 1215703SN/A { 1225703SN/A CachePort *cachePort; 1235703SN/A PacketPtr pkt; 1245703SN/A bool newResponse; 1255703SN/A 1265703SN/A CacheEvent(CachePort *_cachePort, bool response); 1275703SN/A void process(); 1285703SN/A const char *description(); 1295703SN/A }; 1305703SN/A 1315703SN/A public: //Made public so coherence can get at it. 1325703SN/A CachePort *cpuSidePort; 1335703SN/A CachePort *memSidePort; 1348521SN/A 1355703SN/A CacheEvent *sendEvent; 1365703SN/A CacheEvent *memSendEvent; 1375703SN/A 1385703SN/A private: 1395703SN/A void recvStatusChange(Port::Status status, bool isCpuSide) 1408825Snilay@cs.wisc.edu { 1415703SN/A if (status == Port::RangeChange){ 1425703SN/A if (!isCpuSide) { 1435703SN/A cpuSidePort->sendStatusChange(Port::RangeChange); 1445703SN/A } 1455703SN/A else { 1465703SN/A memSidePort->sendStatusChange(Port::RangeChange); 1475703SN/A } 1485703SN/A } 1496123SN/A } 1505703SN/A 1518135SN/A virtual PacketPtr getPacket() = 0; 1525703SN/A 1535703SN/A virtual PacketPtr getCoherencePacket() = 0; 1545703SN/A 1555876SN/A virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0; 1568835SAli.Saidi@ARM.com 1575703SN/A virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0; 1585703SN/A 1595703SN/A /** 1605703SN/A * Bit vector of the blocking reasons for the access path. 1618835SAli.Saidi@ARM.com * @sa #BlockedCause 1625703SN/A */ 1635703SN/A uint8_t blocked; 1645703SN/A 1655703SN/A /** 1665703SN/A * Bit vector for the blocking reasons for the snoop path. 1675703SN/A * @sa #BlockedCause 1685703SN/A */ 1695703SN/A uint8_t blockedSnoop; 1706024SN/A 1715703SN/A /** 1725703SN/A * Bit vector for the outstanding requests for the master interface. 1735703SN/A */ 1745703SN/A uint8_t masterRequests; 1757761SN/A 1767761SN/A /** 1775703SN/A * Bit vector for the outstanding requests for the slave interface. 1785703SN/A */ 1795703SN/A uint8_t slaveRequests; 1805703SN/A 1815703SN/A protected: 1825703SN/A 1835703SN/A /** Stores time the cache blocked for statistics. */ 1845703SN/A Tick blockedCycle; 1855703SN/A 1865703SN/A /** Block size of this cache */ 1875703SN/A const int blkSize; 1885703SN/A 1895703SN/A /** The number of misses to trigger an exit event. */ 1905703SN/A Counter missCount; 1915703SN/A 1925703SN/A /** The drain event. */ 1935703SN/A Event *drainEvent; 1945703SN/A 1955703SN/A public: 1965703SN/A // Statistics 1975703SN/A /** 1985703SN/A * @addtogroup CacheStatistics 1995703SN/A * @{ 2005703SN/A */ 2015703SN/A 2025703SN/A /** Number of hits per thread for each type of command. @sa Packet::Command */ 2035703SN/A Stats::Vector<> hits[NUM_MEM_CMDS]; 2045703SN/A /** Number of hits for demand accesses. */ 2055703SN/A Stats::Formula demandHits; 2065703SN/A /** Number of hit for all accesses. */ 2075703SN/A Stats::Formula overallHits; 2085703SN/A 2095703SN/A /** Number of misses per thread for each type of command. @sa Packet::Command */ 2105703SN/A Stats::Vector<> misses[NUM_MEM_CMDS]; 2115703SN/A /** Number of misses for demand accesses. */ 2125703SN/A Stats::Formula demandMisses; 2135703SN/A /** Number of misses for all accesses. */ 2145703SN/A Stats::Formula overallMisses; 2155703SN/A 2165703SN/A /** 2175703SN/A * Total number of cycles per thread/command spent waiting for a miss. 2185703SN/A * Used to calculate the average miss latency. 2195703SN/A */ 2205703SN/A Stats::Vector<> missLatency[NUM_MEM_CMDS]; 2215703SN/A /** Total number of cycles spent waiting for demand misses. */ 2225703SN/A Stats::Formula demandMissLatency; 2235703SN/A /** Total number of cycles spent waiting for all misses. */ 2245703SN/A Stats::Formula overallMissLatency; 2255703SN/A 2265703SN/A /** The number of accesses per command and thread. */ 2275703SN/A Stats::Formula accesses[NUM_MEM_CMDS]; 2285703SN/A /** The number of demand accesses. */ 2295703SN/A Stats::Formula demandAccesses; 2305703SN/A /** The number of overall accesses. */ 2315703SN/A Stats::Formula overallAccesses; 2325703SN/A 2335703SN/A /** The miss rate per command and thread. */ 2345703SN/A Stats::Formula missRate[NUM_MEM_CMDS]; 2355703SN/A /** The miss rate of all demand accesses. */ 2365703SN/A Stats::Formula demandMissRate; 2375703SN/A /** The miss rate for all accesses. */ 2385703SN/A Stats::Formula overallMissRate; 2395703SN/A 2405703SN/A /** The average miss latency per command and thread. */ 2415703SN/A Stats::Formula avgMissLatency[NUM_MEM_CMDS]; 2425703SN/A /** The average miss latency for demand misses. */ 2435703SN/A Stats::Formula demandAvgMissLatency; 2445703SN/A /** The average miss latency for all misses. */ 2455703SN/A Stats::Formula overallAvgMissLatency; 2465703SN/A 2475703SN/A /** The total number of cycles blocked for each blocked cause. */ 2485703SN/A Stats::Vector<> blocked_cycles; 2495703SN/A /** The number of times this cache blocked for each blocked cause. */ 2505703SN/A Stats::Vector<> blocked_causes; 2515703SN/A 2525703SN/A /** The average number of cycles blocked for each blocked cause. */ 2535703SN/A Stats::Formula avg_blocked; 2545703SN/A 2555703SN/A /** The number of fast writes (WH64) performed. */ 2565703SN/A Stats::Scalar<> fastWrites; 2575703SN/A 2585703SN/A /** The number of cache copies performed. */ 2595703SN/A Stats::Scalar<> cacheCopies; 2605703SN/A 2615703SN/A /** 2625703SN/A * @} 2635703SN/A */ 2645703SN/A 2655703SN/A /** 2665703SN/A * Register stats for this object. 2675703SN/A */ 2685703SN/A virtual void regStats(); 2695703SN/A 2707761SN/A public: 2717761SN/A 2727761SN/A class Params 2735703SN/A { 2747761SN/A public: 2755703SN/A /** List of address ranges of this cache. */ 2765703SN/A std::vector<Range<Addr> > addrRange; 2777761SN/A /** The hit latency for this cache. */ 2787761SN/A int hitLatency; 2797761SN/A /** The block size of this cache. */ 2807761SN/A int blkSize; 2817761SN/A /** 2827761SN/A * The maximum number of misses this cache should handle before 2837761SN/A * ending the simulation. 2847761SN/A */ 2857761SN/A Counter maxMisses; 2867761SN/A 2877761SN/A /** 2887761SN/A * Construct an instance of this parameter class. 2897761SN/A */ 2907761SN/A Params(std::vector<Range<Addr> > addr_range, 2917761SN/A int hit_latency, int _blkSize, Counter max_misses) 2927761SN/A : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize), 2937761SN/A maxMisses(max_misses) 2947761SN/A { 2957761SN/A } 2967761SN/A }; 2977761SN/A 2987761SN/A /** 2997761SN/A * Create and initialize a basic cache object. 3007761SN/A * @param name The name of this cache. 3017761SN/A * @param hier_params Pointer to the HierParams object for this hierarchy 3027761SN/A * of this cache. 3037761SN/A * @param params The parameter object for this BaseCache. 3047761SN/A */ 3057761SN/A BaseCache(const std::string &name, Params ¶ms) 3067761SN/A : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0), 3077761SN/A slaveRequests(0), blkSize(params.blkSize), 3087761SN/A missCount(params.maxMisses), drainEvent(NULL) 3097761SN/A { 3107761SN/A //Start ports at null if more than one is created we should panic 3117761SN/A cpuSidePort = NULL; 3127761SN/A memSidePort = NULL; 3137761SN/A } 3147761SN/A 3157761SN/A ~BaseCache() 3167761SN/A { 3177761SN/A delete sendEvent; 3187761SN/A delete memSendEvent; 3197761SN/A } 3207761SN/A 3217761SN/A virtual void init(); 3227761SN/A 3237761SN/A /** 3247761SN/A * Query block size of a cache. 3257761SN/A * @return The block size 3267761SN/A */ 3277761SN/A int getBlockSize() const 3287761SN/A { 3297761SN/A return blkSize; 3307761SN/A } 3317761SN/A 3327761SN/A /** 3337761SN/A * Returns true if the cache is blocked for accesses. 3347761SN/A */ 3357761SN/A bool isBlocked() 3367761SN/A { 3377761SN/A return blocked != 0; 3387761SN/A } 3397761SN/A 3407761SN/A /** 3417761SN/A * Returns true if the cache is blocked for snoops. 3427761SN/A */ 3437761SN/A bool isBlockedForSnoop() 3447761SN/A { 3457761SN/A return blockedSnoop != 0; 3467761SN/A } 3477761SN/A 3487761SN/A /** 3497761SN/A * Marks the access path of the cache as blocked for the given cause. This 3507761SN/A * also sets the blocked flag in the slave interface. 3517761SN/A * @param cause The reason for the cache blocking. 3527761SN/A */ 3537761SN/A void setBlocked(BlockedCause cause) 3547761SN/A { 3557761SN/A uint8_t flag = 1 << cause; 3567761SN/A if (blocked == 0) { 3577761SN/A blocked_causes[cause]++; 3587761SN/A blockedCycle = curTick; 3597761SN/A } 3607761SN/A int old_state = blocked; 3617761SN/A if (!(blocked & flag)) { 3627761SN/A //Wasn't already blocked for this cause 3637761SN/A blocked |= flag; 3647761SN/A DPRINTF(Cache,"Blocking for cause %s\n", cause); 3657761SN/A if (!old_state) 3667761SN/A cpuSidePort->setBlocked(); 3677761SN/A } 3687761SN/A } 3697761SN/A 3707761SN/A /** 3717761SN/A * Marks the snoop path of the cache as blocked for the given cause. This 3727761SN/A * also sets the blocked flag in the master interface. 3737761SN/A * @param cause The reason to block the snoop path. 3747761SN/A */ 3757761SN/A void setBlockedForSnoop(BlockedCause cause) 3767761SN/A { 3777761SN/A uint8_t flag = 1 << cause; 3787761SN/A uint8_t old_state = blockedSnoop; 3797761SN/A if (!(blockedSnoop & flag)) { 3807761SN/A //Wasn't already blocked for this cause 3817761SN/A blockedSnoop |= flag; 3827761SN/A if (!old_state) 3837761SN/A memSidePort->setBlocked(); 3847761SN/A } 3857761SN/A } 3867761SN/A 3877761SN/A /** 3887761SN/A * Marks the cache as unblocked for the given cause. This also clears the 3897761SN/A * blocked flags in the appropriate interfaces. 3907761SN/A * @param cause The newly unblocked cause. 3917761SN/A * @warning Calling this function can cause a blocked request on the bus to 3925703SN/A * access the cache. The cache must be in a state to handle that request. 3935703SN/A */ 3945703SN/A void clearBlocked(BlockedCause cause) 3955703SN/A { 3967761SN/A uint8_t flag = 1 << cause; 3977761SN/A DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n", 3987761SN/A cause, blocked); 3995703SN/A if (blocked & flag) 4007761SN/A { 4015703SN/A blocked &= ~flag; 4025703SN/A if (!isBlocked()) { 4035703SN/A blocked_cycles[cause] += curTick - blockedCycle; 4045703SN/A DPRINTF(Cache,"Unblocking from all causes\n"); 4055703SN/A cpuSidePort->clearBlocked(); 4065703SN/A } 4075703SN/A } 4087761SN/A if (blockedSnoop & flag) 4097761SN/A { 4107761SN/A blockedSnoop &= ~flag; 4117761SN/A if (!isBlockedForSnoop()) { 4127761SN/A memSidePort->clearBlocked(); 4137761SN/A } 4147761SN/A } 4157761SN/A } 4167761SN/A 4177761SN/A /** 4187761SN/A * True if the master bus should be requested. 4197761SN/A * @return True if there are outstanding requests for the master bus. 4207761SN/A */ 4217761SN/A bool doMasterRequest() 4227761SN/A { 4237761SN/A return masterRequests != 0; 4247761SN/A } 4257761SN/A 4265703SN/A /** 4275703SN/A * Request the master bus for the given cause and time. 4287761SN/A * @param cause The reason for the request. 4295703SN/A * @param time The time to make the request. 4307761SN/A */ 4315703SN/A void setMasterRequest(RequestCause cause, Tick time) 4325703SN/A { 4335703SN/A if (!doMasterRequest() && !memSidePort->waitingOnRetry) 4345703SN/A { 4355703SN/A BaseCache::CacheEvent * reqCpu = 4365703SN/A new BaseCache::CacheEvent(memSidePort, false); 4375703SN/A reqCpu->schedule(time); 4385703SN/A } 4395703SN/A uint8_t flag = 1<<cause; 4405703SN/A masterRequests |= flag; 4416123SN/A } 4425703SN/A 4438135SN/A /** 4445703SN/A * Clear the master bus request for the given cause. 4455703SN/A * @param cause The request reason to clear. 4465703SN/A */ 4475876SN/A void clearMasterRequest(RequestCause cause) 4488835SAli.Saidi@ARM.com { 4495703SN/A uint8_t flag = 1<<cause; 4505703SN/A masterRequests &= ~flag; 4515703SN/A checkDrain(); 4525703SN/A } 4538835SAli.Saidi@ARM.com 4545703SN/A /** 4555703SN/A * Return true if the slave bus should be requested. 4565703SN/A * @return True if there are outstanding requests for the slave bus. 4575703SN/A */ 4585703SN/A bool doSlaveRequest() 4595703SN/A { 4605703SN/A return slaveRequests != 0; 4615703SN/A } 4625703SN/A 4635703SN/A /** 4645703SN/A * Request the slave bus for the given reason and time. 4656024SN/A * @param cause The reason for the request. 4665703SN/A * @param time The time to make the request. 4675703SN/A */ 4685703SN/A void setSlaveRequest(RequestCause cause, Tick time) 4695703SN/A { 4705703SN/A if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry) 4715703SN/A { 4725703SN/A BaseCache::CacheEvent * reqCpu = 4735703SN/A new BaseCache::CacheEvent(cpuSidePort, false); 4745703SN/A reqCpu->schedule(time); 4755703SN/A } 4765703SN/A uint8_t flag = 1<<cause; 4775703SN/A slaveRequests |= flag; 4788241SN/A } 4798241SN/A 4805703SN/A /** 4815703SN/A * Clear the slave bus request for the given reason. 4825703SN/A * @param cause The request reason to clear. 4835703SN/A */ 4845703SN/A void clearSlaveRequest(RequestCause cause) 4855703SN/A { 4865876SN/A uint8_t flag = 1<<cause; 4875703SN/A slaveRequests &= ~flag; 4885703SN/A checkDrain(); 4895703SN/A } 4905703SN/A 4915703SN/A /** 4925703SN/A * Send a response to the slave interface. 4935703SN/A * @param pkt The request being responded to. 4945703SN/A * @param time The time the response is ready. 4955703SN/A */ 4965703SN/A void respond(PacketPtr pkt, Tick time) 4975703SN/A { 4985703SN/A assert(time >= curTick); 4995703SN/A if (pkt->needsResponse()) { 5005703SN/A/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 5015703SN/A reqCpu->schedule(time); 5025703SN/A*/ 5035703SN/A if (cpuSidePort->transmitList.empty()) { 5045703SN/A assert(!sendEvent->scheduled()); 5055703SN/A sendEvent->schedule(time); 5065703SN/A cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 5075703SN/A (time,pkt)); 5085703SN/A return; 5095703SN/A } 5105703SN/A 5115703SN/A // something is on the list and this belongs at the end 5125703SN/A if (time >= cpuSidePort->transmitList.back().first) { 5135703SN/A cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 5145703SN/A (time,pkt)); 5155703SN/A return; 5165703SN/A } 5175703SN/A // Something is on the list and this belongs somewhere else 5185703SN/A std::list<std::pair<Tick,PacketPtr> >::iterator i = 5195703SN/A cpuSidePort->transmitList.begin(); 5205703SN/A std::list<std::pair<Tick,PacketPtr> >::iterator end = 5215703SN/A cpuSidePort->transmitList.end(); 5225703SN/A bool done = false; 5235703SN/A 5245703SN/A while (i != end && !done) { 5255703SN/A if (time < i->first) { 5265703SN/A if (i == cpuSidePort->transmitList.begin()) { 5275703SN/A //Inserting at begining, reschedule 5285703SN/A sendEvent->reschedule(time); 5295703SN/A } 5305703SN/A cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr> 5315703SN/A (time,pkt)); 5328825Snilay@cs.wisc.edu done = true; 5335703SN/A } 5345703SN/A i++; 5355703SN/A } 5365703SN/A } 5375703SN/A else { 5385703SN/A if (pkt->cmd != Packet::UpgradeReq) 5395703SN/A { 5405703SN/A delete pkt->req; 5415703SN/A delete pkt; 5425703SN/A } 5435703SN/A } 5445703SN/A } 5455703SN/A 5465703SN/A /** 5475703SN/A * Send a reponse to the slave interface and calculate miss latency. 5485703SN/A * @param pkt The request to respond to. 5495703SN/A * @param time The time the response is ready. 5505703SN/A */ 5515703SN/A void respondToMiss(PacketPtr pkt, Tick time) 5525703SN/A { 5535703SN/A assert(time >= curTick); 5545703SN/A if (!pkt->req->isUncacheable()) { 5555703SN/A missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += 5565703SN/A time - pkt->time; 5575703SN/A } 5588521SN/A if (pkt->needsResponse()) { 5595703SN/A/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 5605703SN/A reqCpu->schedule(time); 5615703SN/A*/ 5625703SN/A if (cpuSidePort->transmitList.empty()) { 5635703SN/A assert(!sendEvent->scheduled()); 5648825Snilay@cs.wisc.edu sendEvent->schedule(time); 5655703SN/A cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 5665703SN/A (time,pkt)); 5675703SN/A return; 5685703SN/A } 5695703SN/A 5705703SN/A // something is on the list and this belongs at the end 5715703SN/A if (time >= cpuSidePort->transmitList.back().first) { 5725703SN/A cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 5736123SN/A (time,pkt)); 5745703SN/A return; 5758135SN/A } 5765703SN/A // Something is on the list and this belongs somewhere else 5775703SN/A std::list<std::pair<Tick,PacketPtr> >::iterator i = 5785703SN/A cpuSidePort->transmitList.begin(); 5795876SN/A std::list<std::pair<Tick,PacketPtr> >::iterator end = 5808835SAli.Saidi@ARM.com cpuSidePort->transmitList.end(); 5815703SN/A bool done = false; 5825703SN/A 5835703SN/A while (i != end && !done) { 5845703SN/A if (time < i->first) { 5858835SAli.Saidi@ARM.com if (i == cpuSidePort->transmitList.begin()) { 5865703SN/A //Inserting at begining, reschedule 5875703SN/A sendEvent->reschedule(time); 5885703SN/A } 5895703SN/A cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr> 5905703SN/A (time,pkt)); 5915703SN/A done = true; 5925703SN/A } 5935703SN/A i++; 5946024SN/A } 5955703SN/A } 5965703SN/A else { 5975703SN/A if (pkt->cmd != Packet::UpgradeReq) 5985703SN/A { 5997761SN/A delete pkt->req; 6007761SN/A delete pkt; 6015703SN/A } 6025703SN/A } 6035703SN/A } 6045703SN/A 6055703SN/A /** 6065703SN/A * Suppliess the data if cache to cache transfers are enabled. 6075703SN/A * @param pkt The bus transaction to fulfill. 6085703SN/A */ 6095703SN/A void respondToSnoop(PacketPtr pkt, Tick time) 6105703SN/A { 6115703SN/A assert(time >= curTick); 6125703SN/A assert (pkt->needsResponse()); 6135703SN/A/* CacheEvent *reqMem = new CacheEvent(memSidePort, pkt); 6145703SN/A reqMem->schedule(time); 6155703SN/A*/ 6165703SN/A if (memSidePort->transmitList.empty()) { 6175703SN/A assert(!memSendEvent->scheduled()); 6185703SN/A memSendEvent->schedule(time); 6195703SN/A memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 6205703SN/A (time,pkt)); 6215703SN/A return; 6225703SN/A } 6235703SN/A 6245703SN/A // something is on the list and this belongs at the end 6255703SN/A if (time >= memSidePort->transmitList.back().first) { 6265703SN/A memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 6275703SN/A (time,pkt)); 6285703SN/A return; 6295703SN/A } 6305703SN/A // Something is on the list and this belongs somewhere else 6315703SN/A std::list<std::pair<Tick,PacketPtr> >::iterator i = 6325703SN/A memSidePort->transmitList.begin(); 6335703SN/A std::list<std::pair<Tick,PacketPtr> >::iterator end = 6345703SN/A memSidePort->transmitList.end(); 6355703SN/A bool done = false; 6365703SN/A 6375703SN/A while (i != end && !done) { 6385703SN/A if (time < i->first) { 6395703SN/A if (i == memSidePort->transmitList.begin()) { 6405703SN/A //Inserting at begining, reschedule 6415703SN/A memSendEvent->reschedule(time); 6425703SN/A } 6435703SN/A memSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt)); 6445703SN/A done = true; 6455703SN/A } 6465703SN/A i++; 6475703SN/A } 6485703SN/A } 6495703SN/A 6505703SN/A /** 6515703SN/A * Notification from master interface that a address range changed. Nothing 6525703SN/A * to do for a cache. 6535703SN/A */ 6545703SN/A void rangeChange() {} 6555703SN/A 6565703SN/A void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide) 6575703SN/A { 6585703SN/A if (isCpuSide) 6595703SN/A { 6605703SN/A AddrRangeList dummy; 6615703SN/A memSidePort->getPeerAddressRanges(resp, dummy); 6625703SN/A } 6635703SN/A else 6645703SN/A { 6655703SN/A //This is where snoops get updated 6665703SN/A AddrRangeList dummy; 6675703SN/A cpuSidePort->getPeerAddressRanges(dummy, snoop); 6685703SN/A return; 6695703SN/A } 6705703SN/A } 6715703SN/A 6725703SN/A virtual unsigned int drain(Event *de); 6735703SN/A 6745703SN/A void checkDrain() 6755703SN/A { 6765703SN/A if (drainEvent && canDrain()) { 6775703SN/A drainEvent->process(); 6785703SN/A changeState(SimObject::Drained); 6795703SN/A // Clear the drain event 6805703SN/A drainEvent = NULL; 6815703SN/A } 6825703SN/A } 6835703SN/A 6845703SN/A bool canDrain() 6855703SN/A { 6865703SN/A if (doMasterRequest() || doSlaveRequest()) { 6875703SN/A return false; 6885703SN/A } else if (memSidePort && !memSidePort->canDrain()) { 6895703SN/A return false; 6905703SN/A } else if (cpuSidePort && !cpuSidePort->canDrain()) { 6915703SN/A return false; 6925703SN/A } 6935703SN/A return true; 6947761SN/A } 6957761SN/A}; 6967761SN/A 6975703SN/A#endif //__BASE_CACHE_HH__ 6987761SN/A