base.hh revision 4022
16019Shines@cs.fsu.edu/* 210037SARM gem5 Developers * Copyright (c) 2003-2005 The Regents of The University of Michigan 37414SAli.Saidi@ARM.com * All rights reserved. 47414SAli.Saidi@ARM.com * 57414SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67414SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77414SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87414SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97414SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107414SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117414SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127414SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137414SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 146019Shines@cs.fsu.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * Authors: Erik Hallnor 296019Shines@cs.fsu.edu */ 306019Shines@cs.fsu.edu 316019Shines@cs.fsu.edu/** 326019Shines@cs.fsu.edu * @file 336019Shines@cs.fsu.edu * Declares a basic cache interface BaseCache. 346019Shines@cs.fsu.edu */ 356019Shines@cs.fsu.edu 366019Shines@cs.fsu.edu#ifndef __BASE_CACHE_HH__ 376019Shines@cs.fsu.edu#define __BASE_CACHE_HH__ 386019Shines@cs.fsu.edu 396019Shines@cs.fsu.edu#include <vector> 406019Shines@cs.fsu.edu#include <string> 417414SAli.Saidi@ARM.com#include <list> 426019Shines@cs.fsu.edu#include <inttypes.h> 436019Shines@cs.fsu.edu 4411793Sbrandon.potter@amd.com#include "base/misc.hh" 4511793Sbrandon.potter@amd.com#include "base/statistics.hh" 466019Shines@cs.fsu.edu#include "base/trace.hh" 476019Shines@cs.fsu.edu#include "mem/mem_object.hh" 486019Shines@cs.fsu.edu#include "mem/packet.hh" 496019Shines@cs.fsu.edu#include "mem/port.hh" 5012334Sgabeblack@google.com#include "mem/request.hh" 516019Shines@cs.fsu.edu#include "sim/eventq.hh" 528232Snate@binkert.org 536019Shines@cs.fsu.edu/** 5412431Sgabeblack@google.com * Reasons for Caches to be Blocked. 5511854Sbrandon.potter@amd.com */ 567678Sgblack@eecs.umich.eduenum BlockedCause{ 576019Shines@cs.fsu.edu Blocked_NoMSHRs, 5811800Sbrandon.potter@amd.com Blocked_NoTargets, 596019Shines@cs.fsu.edu Blocked_NoWBBuffers, 606019Shines@cs.fsu.edu Blocked_Coherence, 616019Shines@cs.fsu.edu NUM_BLOCKED_CAUSES 626019Shines@cs.fsu.edu}; 636019Shines@cs.fsu.edu 6411851Sbrandon.potter@amd.com/** 6511851Sbrandon.potter@amd.com * Reasons for cache to request a bus. 6612448Sgabeblack@google.com */ 6712448Sgabeblack@google.comenum RequestCause{ 6812432Sgabeblack@google.com Request_MSHR, 6912448Sgabeblack@google.com Request_WB, 706019Shines@cs.fsu.edu Request_Coherence, 7112441Sgabeblack@google.com Request_PF 7210037SARM gem5 Developers}; 7310037SARM gem5 Developers 7411851Sbrandon.potter@amd.comclass MSHR; 7511851Sbrandon.potter@amd.com/** 7611851Sbrandon.potter@amd.com * A basic cache interface. Implements some common functions for speed. 7710037SARM gem5 Developers */ 7811905SBrandon.Potter@amd.comclass BaseCache : public MemObject 7911905SBrandon.Potter@amd.com{ 8011905SBrandon.Potter@amd.com class CachePort : public Port 8111905SBrandon.Potter@amd.com { 8211905SBrandon.Potter@amd.com public: 8311905SBrandon.Potter@amd.com BaseCache *cache; 846019Shines@cs.fsu.edu 8511905SBrandon.Potter@amd.com protected: 8611905SBrandon.Potter@amd.com CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide); 876019Shines@cs.fsu.edu virtual void recvStatusChange(Status status); 886019Shines@cs.fsu.edu 8911851Sbrandon.potter@amd.com virtual void getDeviceAddressRanges(AddrRangeList &resp, 9011851Sbrandon.potter@amd.com AddrRangeList &snoop); 9111851Sbrandon.potter@amd.com 9210037SARM gem5 Developers virtual int deviceBlockSize(); 9311905SBrandon.Potter@amd.com 9411905SBrandon.Potter@amd.com virtual void recvRetry(); 9511905SBrandon.Potter@amd.com 9611905SBrandon.Potter@amd.com public: 9711905SBrandon.Potter@amd.com void setBlocked(); 9811905SBrandon.Potter@amd.com 9910037SARM gem5 Developers void clearBlocked(); 10011905SBrandon.Potter@amd.com 10111905SBrandon.Potter@amd.com bool checkFunctional(PacketPtr pkt); 10210037SARM gem5 Developers 10310037SARM gem5 Developers void checkAndSendFunctional(PacketPtr pkt); 1046019Shines@cs.fsu.edu 10511851Sbrandon.potter@amd.com bool canDrain() { return drainList.empty() && transmitList.empty(); } 1066019Shines@cs.fsu.edu 10711851Sbrandon.potter@amd.com bool blocked; 10810318Sandreas.hansson@arm.com 1097640Sgblack@eecs.umich.edu bool mustSendRetry; 1107640Sgblack@eecs.umich.edu 1117640Sgblack@eecs.umich.edu bool isCpuSide; 1127640Sgblack@eecs.umich.edu 1137640Sgblack@eecs.umich.edu bool waitingOnRetry; 1147640Sgblack@eecs.umich.edu 1157640Sgblack@eecs.umich.edu std::list<PacketPtr> drainList; 1167640Sgblack@eecs.umich.edu 1177640Sgblack@eecs.umich.edu std::list<std::pair<Tick,PacketPtr> > transmitList; 1187640Sgblack@eecs.umich.edu }; 1197640Sgblack@eecs.umich.edu 1207640Sgblack@eecs.umich.edu struct CacheEvent : public Event 1216019Shines@cs.fsu.edu { 1226019Shines@cs.fsu.edu CachePort *cachePort; 1236019Shines@cs.fsu.edu PacketPtr pkt; 12411851Sbrandon.potter@amd.com bool newResponse; 1256019Shines@cs.fsu.edu 12611851Sbrandon.potter@amd.com CacheEvent(CachePort *_cachePort, bool response); 12710318Sandreas.hansson@arm.com void process(); 12810037SARM gem5 Developers const char *description(); 12910037SARM gem5 Developers }; 13010037SARM gem5 Developers 13110037SARM gem5 Developers public: //Made public so coherence can get at it. 13210037SARM gem5 Developers CachePort *cpuSidePort; 13310037SARM gem5 Developers CachePort *memSidePort; 13410037SARM gem5 Developers 13510037SARM gem5 Developers CacheEvent *sendEvent; 13610037SARM gem5 Developers CacheEvent *memSendEvent; 13710037SARM gem5 Developers 13810037SARM gem5 Developers private: 13910037SARM gem5 Developers void recvStatusChange(Port::Status status, bool isCpuSide) 14010037SARM gem5 Developers { 14110037SARM gem5 Developers if (status == Port::RangeChange){ 14210037SARM gem5 Developers if (!isCpuSide) { 14310037SARM gem5 Developers cpuSidePort->sendStatusChange(Port::RangeChange); 14410037SARM gem5 Developers } 14510037SARM gem5 Developers else { 14610037SARM gem5 Developers memSidePort->sendStatusChange(Port::RangeChange); 14711851Sbrandon.potter@amd.com } 14810037SARM gem5 Developers } 14910037SARM gem5 Developers } 15010037SARM gem5 Developers 15110037SARM gem5 Developers virtual PacketPtr getPacket() = 0; 1526400Sgblack@eecs.umich.edu 1536400Sgblack@eecs.umich.edu virtual PacketPtr getCoherencePacket() = 0; 1546400Sgblack@eecs.umich.edu 1556400Sgblack@eecs.umich.edu virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0; 1566400Sgblack@eecs.umich.edu 1576400Sgblack@eecs.umich.edu virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0; 1586400Sgblack@eecs.umich.edu 1596400Sgblack@eecs.umich.edu /** 1606400Sgblack@eecs.umich.edu * Bit vector of the blocking reasons for the access path. 1616400Sgblack@eecs.umich.edu * @sa #BlockedCause 1626400Sgblack@eecs.umich.edu */ 16311389Sbrandon.potter@amd.com uint8_t blocked; 16411389Sbrandon.potter@amd.com 16511389Sbrandon.potter@amd.com /** 1666019Shines@cs.fsu.edu * Bit vector for the blocking reasons for the snoop path. 1676019Shines@cs.fsu.edu * @sa #BlockedCause 1686019Shines@cs.fsu.edu */ 1696400Sgblack@eecs.umich.edu uint8_t blockedSnoop; 1706400Sgblack@eecs.umich.edu 1716400Sgblack@eecs.umich.edu /** 1726400Sgblack@eecs.umich.edu * Bit vector for the outstanding requests for the master interface. 1736400Sgblack@eecs.umich.edu */ 1746400Sgblack@eecs.umich.edu uint8_t masterRequests; 1756400Sgblack@eecs.umich.edu 1766400Sgblack@eecs.umich.edu /** 1776400Sgblack@eecs.umich.edu * Bit vector for the outstanding requests for the slave interface. 1786400Sgblack@eecs.umich.edu */ 1796400Sgblack@eecs.umich.edu uint8_t slaveRequests; 1807414SAli.Saidi@ARM.com 1817414SAli.Saidi@ARM.com protected: 1827414SAli.Saidi@ARM.com 1837414SAli.Saidi@ARM.com /** Stores time the cache blocked for statistics. */ 1847414SAli.Saidi@ARM.com Tick blockedCycle; 1856400Sgblack@eecs.umich.edu 1866400Sgblack@eecs.umich.edu /** Block size of this cache */ 1876400Sgblack@eecs.umich.edu const int blkSize; 1886400Sgblack@eecs.umich.edu 1896400Sgblack@eecs.umich.edu /** The number of misses to trigger an exit event. */ 1906400Sgblack@eecs.umich.edu Counter missCount; 1916400Sgblack@eecs.umich.edu 19210810Sbr@bsdpad.com /** The drain event. */ 19310810Sbr@bsdpad.com Event *drainEvent; 19410810Sbr@bsdpad.com 19510810Sbr@bsdpad.com public: 19610810Sbr@bsdpad.com // Statistics 19710810Sbr@bsdpad.com /** 19810810Sbr@bsdpad.com * @addtogroup CacheStatistics 19910810Sbr@bsdpad.com * @{ 20010810Sbr@bsdpad.com */ 20110810Sbr@bsdpad.com 20210810Sbr@bsdpad.com /** Number of hits per thread for each type of command. @sa Packet::Command */ 20310810Sbr@bsdpad.com Stats::Vector<> hits[MemCmd::NUM_MEM_CMDS]; 20410810Sbr@bsdpad.com /** Number of hits for demand accesses. */ 20510810Sbr@bsdpad.com Stats::Formula demandHits; 20610810Sbr@bsdpad.com /** Number of hit for all accesses. */ 20710810Sbr@bsdpad.com Stats::Formula overallHits; 20810810Sbr@bsdpad.com 20910810Sbr@bsdpad.com /** Number of misses per thread for each type of command. @sa Packet::Command */ 21010810Sbr@bsdpad.com Stats::Vector<> misses[MemCmd::NUM_MEM_CMDS]; 21110810Sbr@bsdpad.com /** Number of misses for demand accesses. */ 21210810Sbr@bsdpad.com Stats::Formula demandMisses; 21310810Sbr@bsdpad.com /** Number of misses for all accesses. */ 21410810Sbr@bsdpad.com Stats::Formula overallMisses; 21510810Sbr@bsdpad.com 21610810Sbr@bsdpad.com /** 21710810Sbr@bsdpad.com * Total number of cycles per thread/command spent waiting for a miss. 21810810Sbr@bsdpad.com * Used to calculate the average miss latency. 21910810Sbr@bsdpad.com */ 22010810Sbr@bsdpad.com Stats::Vector<> missLatency[MemCmd::NUM_MEM_CMDS]; 22110810Sbr@bsdpad.com /** Total number of cycles spent waiting for demand misses. */ 22210810Sbr@bsdpad.com Stats::Formula demandMissLatency; 22310810Sbr@bsdpad.com /** Total number of cycles spent waiting for all misses. */ 22410810Sbr@bsdpad.com Stats::Formula overallMissLatency; 22510810Sbr@bsdpad.com 2266400Sgblack@eecs.umich.edu /** The number of accesses per command and thread. */ 22710318Sandreas.hansson@arm.com Stats::Formula accesses[MemCmd::NUM_MEM_CMDS]; 2286400Sgblack@eecs.umich.edu /** The number of demand accesses. */ 2296400Sgblack@eecs.umich.edu Stats::Formula demandAccesses; 2306400Sgblack@eecs.umich.edu /** The number of overall accesses. */ 2316400Sgblack@eecs.umich.edu Stats::Formula overallAccesses; 2326400Sgblack@eecs.umich.edu 2336400Sgblack@eecs.umich.edu /** The miss rate per command and thread. */ 2346400Sgblack@eecs.umich.edu Stats::Formula missRate[MemCmd::NUM_MEM_CMDS]; 23511389Sbrandon.potter@amd.com /** The miss rate of all demand accesses. */ 23611389Sbrandon.potter@amd.com Stats::Formula demandMissRate; 23711389Sbrandon.potter@amd.com /** The miss rate for all accesses. */ 23811389Sbrandon.potter@amd.com Stats::Formula overallMissRate; 2396400Sgblack@eecs.umich.edu 2406400Sgblack@eecs.umich.edu /** The average miss latency per command and thread. */ 2416400Sgblack@eecs.umich.edu Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS]; 2426400Sgblack@eecs.umich.edu /** The average miss latency for demand misses. */ 2436400Sgblack@eecs.umich.edu Stats::Formula demandAvgMissLatency; 2446400Sgblack@eecs.umich.edu /** The average miss latency for all misses. */ 2456400Sgblack@eecs.umich.edu Stats::Formula overallAvgMissLatency; 2466400Sgblack@eecs.umich.edu 2476400Sgblack@eecs.umich.edu /** The total number of cycles blocked for each blocked cause. */ 2486400Sgblack@eecs.umich.edu Stats::Vector<> blocked_cycles; 2496400Sgblack@eecs.umich.edu /** The number of times this cache blocked for each blocked cause. */ 2506400Sgblack@eecs.umich.edu Stats::Vector<> blocked_causes; 2516400Sgblack@eecs.umich.edu 2526400Sgblack@eecs.umich.edu /** The average number of cycles blocked for each blocked cause. */ 2536400Sgblack@eecs.umich.edu Stats::Formula avg_blocked; 2546400Sgblack@eecs.umich.edu 2557414SAli.Saidi@ARM.com /** The number of fast writes (WH64) performed. */ 2566400Sgblack@eecs.umich.edu Stats::Scalar<> fastWrites; 2576400Sgblack@eecs.umich.edu 2587414SAli.Saidi@ARM.com /** The number of cache copies performed. */ 2597414SAli.Saidi@ARM.com Stats::Scalar<> cacheCopies; 2607414SAli.Saidi@ARM.com 2616400Sgblack@eecs.umich.edu /** 2626400Sgblack@eecs.umich.edu * @} 2636400Sgblack@eecs.umich.edu */ 2646400Sgblack@eecs.umich.edu 2656400Sgblack@eecs.umich.edu /** 2666400Sgblack@eecs.umich.edu * Register stats for this object. 2676400Sgblack@eecs.umich.edu */ 2686400Sgblack@eecs.umich.edu virtual void regStats(); 2696400Sgblack@eecs.umich.edu 2706400Sgblack@eecs.umich.edu public: 2716019Shines@cs.fsu.edu 2726019Shines@cs.fsu.edu class Params 2736019Shines@cs.fsu.edu { 2746019Shines@cs.fsu.edu public: 2756400Sgblack@eecs.umich.edu /** List of address ranges of this cache. */ 2766400Sgblack@eecs.umich.edu std::vector<Range<Addr> > addrRange; 2776400Sgblack@eecs.umich.edu /** The hit latency for this cache. */ 2787414SAli.Saidi@ARM.com int hitLatency; 2796400Sgblack@eecs.umich.edu /** The block size of this cache. */ 2806400Sgblack@eecs.umich.edu int blkSize; 2816400Sgblack@eecs.umich.edu /** 2826400Sgblack@eecs.umich.edu * The maximum number of misses this cache should handle before 2836400Sgblack@eecs.umich.edu * ending the simulation. 2846400Sgblack@eecs.umich.edu */ 2856400Sgblack@eecs.umich.edu Counter maxMisses; 2866400Sgblack@eecs.umich.edu 2876400Sgblack@eecs.umich.edu /** 2886400Sgblack@eecs.umich.edu * Construct an instance of this parameter class. 2896400Sgblack@eecs.umich.edu */ 2906400Sgblack@eecs.umich.edu Params(std::vector<Range<Addr> > addr_range, 2916400Sgblack@eecs.umich.edu int hit_latency, int _blkSize, Counter max_misses) 2926400Sgblack@eecs.umich.edu : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize), 2936400Sgblack@eecs.umich.edu maxMisses(max_misses) 2946400Sgblack@eecs.umich.edu { 2956400Sgblack@eecs.umich.edu } 2966400Sgblack@eecs.umich.edu }; 2976400Sgblack@eecs.umich.edu 2986400Sgblack@eecs.umich.edu /** 2996400Sgblack@eecs.umich.edu * Create and initialize a basic cache object. 3006400Sgblack@eecs.umich.edu * @param name The name of this cache. 3016400Sgblack@eecs.umich.edu * @param hier_params Pointer to the HierParams object for this hierarchy 3026400Sgblack@eecs.umich.edu * of this cache. 3036400Sgblack@eecs.umich.edu * @param params The parameter object for this BaseCache. 30411905SBrandon.Potter@amd.com */ 30511905SBrandon.Potter@amd.com BaseCache(const std::string &name, Params ¶ms) 30611905SBrandon.Potter@amd.com : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0), 3076400Sgblack@eecs.umich.edu slaveRequests(0), blkSize(params.blkSize), 3086400Sgblack@eecs.umich.edu missCount(params.maxMisses), drainEvent(NULL) 30911905SBrandon.Potter@amd.com { 31011905SBrandon.Potter@amd.com //Start ports at null if more than one is created we should panic 3116400Sgblack@eecs.umich.edu cpuSidePort = NULL; 3126400Sgblack@eecs.umich.edu memSidePort = NULL; 31311905SBrandon.Potter@amd.com } 31410037SARM gem5 Developers 31510037SARM gem5 Developers ~BaseCache() 31610037SARM gem5 Developers { 31710037SARM gem5 Developers delete sendEvent; 31810037SARM gem5 Developers delete memSendEvent; 31910037SARM gem5 Developers } 32010037SARM gem5 Developers 32110037SARM gem5 Developers virtual void init(); 32210037SARM gem5 Developers 3236400Sgblack@eecs.umich.edu /** 3246400Sgblack@eecs.umich.edu * Query block size of a cache. 3256400Sgblack@eecs.umich.edu * @return The block size 3266400Sgblack@eecs.umich.edu */ 3276400Sgblack@eecs.umich.edu int getBlockSize() const 3287414SAli.Saidi@ARM.com { 3296400Sgblack@eecs.umich.edu return blkSize; 3306400Sgblack@eecs.umich.edu } 3316400Sgblack@eecs.umich.edu 3326400Sgblack@eecs.umich.edu /** 3336400Sgblack@eecs.umich.edu * Returns true if the cache is blocked for accesses. 33411905SBrandon.Potter@amd.com */ 3356400Sgblack@eecs.umich.edu bool isBlocked() 3366400Sgblack@eecs.umich.edu { 3376400Sgblack@eecs.umich.edu return blocked != 0; 3386400Sgblack@eecs.umich.edu } 33910037SARM gem5 Developers 34010037SARM gem5 Developers /** 3416400Sgblack@eecs.umich.edu * Returns true if the cache is blocked for snoops. 3426400Sgblack@eecs.umich.edu */ 34310037SARM gem5 Developers bool isBlockedForSnoop() 3448852Sandreas.hansson@arm.com { 3456400Sgblack@eecs.umich.edu return blockedSnoop != 0; 3466400Sgblack@eecs.umich.edu } 3476400Sgblack@eecs.umich.edu 3486400Sgblack@eecs.umich.edu /** 3496400Sgblack@eecs.umich.edu * Marks the access path of the cache as blocked for the given cause. This 3506400Sgblack@eecs.umich.edu * also sets the blocked flag in the slave interface. 3518852Sandreas.hansson@arm.com * @param cause The reason for the cache blocking. 3526400Sgblack@eecs.umich.edu */ 3536400Sgblack@eecs.umich.edu void setBlocked(BlockedCause cause) 3548852Sandreas.hansson@arm.com { 3557414SAli.Saidi@ARM.com uint8_t flag = 1 << cause; 3567414SAli.Saidi@ARM.com if (blocked == 0) { 3577414SAli.Saidi@ARM.com blocked_causes[cause]++; 3586400Sgblack@eecs.umich.edu blockedCycle = curTick; 3596019Shines@cs.fsu.edu } 3606019Shines@cs.fsu.edu int old_state = blocked; 3616400Sgblack@eecs.umich.edu if (!(blocked & flag)) { 36210037SARM gem5 Developers //Wasn't already blocked for this cause 3638852Sandreas.hansson@arm.com blocked |= flag; 3646400Sgblack@eecs.umich.edu DPRINTF(Cache,"Blocking for cause %s\n", cause); 3658852Sandreas.hansson@arm.com if (!old_state) 3666400Sgblack@eecs.umich.edu cpuSidePort->setBlocked(); 3676400Sgblack@eecs.umich.edu } 3686400Sgblack@eecs.umich.edu } 3696400Sgblack@eecs.umich.edu 3708852Sandreas.hansson@arm.com /** 3716400Sgblack@eecs.umich.edu * Marks the snoop path of the cache as blocked for the given cause. This 3726019Shines@cs.fsu.edu * also sets the blocked flag in the master interface. 3736400Sgblack@eecs.umich.edu * @param cause The reason to block the snoop path. 3746400Sgblack@eecs.umich.edu */ 3756019Shines@cs.fsu.edu void setBlockedForSnoop(BlockedCause cause) 3768852Sandreas.hansson@arm.com { 3776019Shines@cs.fsu.edu uint8_t flag = 1 << cause; 3786020Sgblack@eecs.umich.edu uint8_t old_state = blockedSnoop; 3796400Sgblack@eecs.umich.edu if (!(blockedSnoop & flag)) { 38011905SBrandon.Potter@amd.com //Wasn't already blocked for this cause 3816400Sgblack@eecs.umich.edu blockedSnoop |= flag; 3826400Sgblack@eecs.umich.edu if (!old_state) 3836400Sgblack@eecs.umich.edu memSidePort->setBlocked(); 3846400Sgblack@eecs.umich.edu } 3856400Sgblack@eecs.umich.edu } 3866400Sgblack@eecs.umich.edu 3876400Sgblack@eecs.umich.edu /** 3886400Sgblack@eecs.umich.edu * Marks the cache as unblocked for the given cause. This also clears the 3896400Sgblack@eecs.umich.edu * blocked flags in the appropriate interfaces. 3906400Sgblack@eecs.umich.edu * @param cause The newly unblocked cause. 3916400Sgblack@eecs.umich.edu * @warning Calling this function can cause a blocked request on the bus to 3926400Sgblack@eecs.umich.edu * access the cache. The cache must be in a state to handle that request. 3936400Sgblack@eecs.umich.edu */ 3946400Sgblack@eecs.umich.edu void clearBlocked(BlockedCause cause) 3956400Sgblack@eecs.umich.edu { 3966400Sgblack@eecs.umich.edu uint8_t flag = 1 << cause; 3976019Shines@cs.fsu.edu DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n", 3987720Sgblack@eecs.umich.edu cause, blocked); 3997720Sgblack@eecs.umich.edu if (blocked & flag) 4007720Sgblack@eecs.umich.edu { 40110037SARM gem5 Developers blocked &= ~flag; 40210037SARM gem5 Developers if (!isBlocked()) { 40311389Sbrandon.potter@amd.com blocked_cycles[cause] += curTick - blockedCycle; 4047720Sgblack@eecs.umich.edu DPRINTF(Cache,"Unblocking from all causes\n"); 4056400Sgblack@eecs.umich.edu cpuSidePort->clearBlocked(); 40611886Sbrandon.potter@amd.com } 40711905SBrandon.Potter@amd.com } 4086019Shines@cs.fsu.edu if (blockedSnoop & flag) 4096019Shines@cs.fsu.edu { 4106020Sgblack@eecs.umich.edu blockedSnoop &= ~flag; 41111851Sbrandon.potter@amd.com if (!isBlockedForSnoop()) { 4126020Sgblack@eecs.umich.edu memSidePort->clearBlocked(); 4137441SAli.Saidi@ARM.com } 4146701Sgblack@eecs.umich.edu } 4156020Sgblack@eecs.umich.edu } 4166020Sgblack@eecs.umich.edu 41710037SARM gem5 Developers /** 41811851Sbrandon.potter@amd.com * True if the master bus should be requested. 41910037SARM gem5 Developers * @return True if there are outstanding requests for the master bus. 42010037SARM gem5 Developers */ 42110037SARM gem5 Developers bool doMasterRequest() 42210037SARM gem5 Developers { 42310037SARM gem5 Developers return masterRequests != 0; 42410037SARM gem5 Developers } 42511851Sbrandon.potter@amd.com 4267441SAli.Saidi@ARM.com /** 4277441SAli.Saidi@ARM.com * Request the master bus for the given cause and time. 4287441SAli.Saidi@ARM.com * @param cause The reason for the request. 4297441SAli.Saidi@ARM.com * @param time The time to make the request. 4307441SAli.Saidi@ARM.com */ 4317441SAli.Saidi@ARM.com void setMasterRequest(RequestCause cause, Tick time) 4327441SAli.Saidi@ARM.com { 4337441SAli.Saidi@ARM.com if (!doMasterRequest() && !memSidePort->waitingOnRetry) 4347441SAli.Saidi@ARM.com { 4357441SAli.Saidi@ARM.com BaseCache::CacheEvent * reqCpu = 4367441SAli.Saidi@ARM.com new BaseCache::CacheEvent(memSidePort, false); 4377441SAli.Saidi@ARM.com reqCpu->schedule(time); 4387441SAli.Saidi@ARM.com } 4397441SAli.Saidi@ARM.com uint8_t flag = 1<<cause; 4407441SAli.Saidi@ARM.com masterRequests |= flag; 4417441SAli.Saidi@ARM.com } 4427441SAli.Saidi@ARM.com 44310037SARM gem5 Developers /** 44411851Sbrandon.potter@amd.com * Clear the master bus request for the given cause. 44510037SARM gem5 Developers * @param cause The request reason to clear. 44610037SARM gem5 Developers */ 44710037SARM gem5 Developers void clearMasterRequest(RequestCause cause) 44810037SARM gem5 Developers { 4497441SAli.Saidi@ARM.com uint8_t flag = 1<<cause; 4506020Sgblack@eecs.umich.edu masterRequests &= ~flag; 45111851Sbrandon.potter@amd.com checkDrain(); 4526020Sgblack@eecs.umich.edu } 45310037SARM gem5 Developers 4546020Sgblack@eecs.umich.edu /** 4556020Sgblack@eecs.umich.edu * Return true if the slave bus should be requested. 4566020Sgblack@eecs.umich.edu * @return True if there are outstanding requests for the slave bus. 4576020Sgblack@eecs.umich.edu */ 45811851Sbrandon.potter@amd.com bool doSlaveRequest() 45910037SARM gem5 Developers { 46010037SARM gem5 Developers return slaveRequests != 0; 46110037SARM gem5 Developers } 46210037SARM gem5 Developers 46310037SARM gem5 Developers /** 46410037SARM gem5 Developers * Request the slave bus for the given reason and time. 46511851Sbrandon.potter@amd.com * @param cause The reason for the request. 4666020Sgblack@eecs.umich.edu * @param time The time to make the request. 46710810Sbr@bsdpad.com */ 46810810Sbr@bsdpad.com void setSlaveRequest(RequestCause cause, Tick time) 46910810Sbr@bsdpad.com { 47010810Sbr@bsdpad.com if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry) 47110810Sbr@bsdpad.com { 47210810Sbr@bsdpad.com BaseCache::CacheEvent * reqCpu = 47310810Sbr@bsdpad.com new BaseCache::CacheEvent(cpuSidePort, false); 47410810Sbr@bsdpad.com reqCpu->schedule(time); 47510810Sbr@bsdpad.com } 47610810Sbr@bsdpad.com uint8_t flag = 1<<cause; 47710810Sbr@bsdpad.com slaveRequests |= flag; 47810223Ssteve.reinhardt@amd.com } 4796020Sgblack@eecs.umich.edu 48010037SARM gem5 Developers /** 48110037SARM gem5 Developers * Clear the slave bus request for the given reason. 48211851Sbrandon.potter@amd.com * @param cause The request reason to clear. 48310037SARM gem5 Developers */ 48410810Sbr@bsdpad.com void clearSlaveRequest(RequestCause cause) 48510810Sbr@bsdpad.com { 48610810Sbr@bsdpad.com uint8_t flag = 1<<cause; 48710810Sbr@bsdpad.com slaveRequests &= ~flag; 48810810Sbr@bsdpad.com checkDrain(); 48910810Sbr@bsdpad.com } 49010810Sbr@bsdpad.com 49110810Sbr@bsdpad.com /** 49210810Sbr@bsdpad.com * Send a response to the slave interface. 49310810Sbr@bsdpad.com * @param pkt The request being responded to. 49410810Sbr@bsdpad.com * @param time The time the response is ready. 49510223Ssteve.reinhardt@amd.com */ 49610037SARM gem5 Developers void respond(PacketPtr pkt, Tick time) 497 { 498 assert(time >= curTick); 499 if (pkt->needsResponse()) { 500/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 501 reqCpu->schedule(time); 502*/ 503 if (cpuSidePort->transmitList.empty()) { 504 assert(!sendEvent->scheduled()); 505 sendEvent->schedule(time); 506 cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 507 (time,pkt)); 508 return; 509 } 510 511 // something is on the list and this belongs at the end 512 if (time >= cpuSidePort->transmitList.back().first) { 513 cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 514 (time,pkt)); 515 return; 516 } 517 // Something is on the list and this belongs somewhere else 518 std::list<std::pair<Tick,PacketPtr> >::iterator i = 519 cpuSidePort->transmitList.begin(); 520 std::list<std::pair<Tick,PacketPtr> >::iterator end = 521 cpuSidePort->transmitList.end(); 522 bool done = false; 523 524 while (i != end && !done) { 525 if (time < i->first) { 526 if (i == cpuSidePort->transmitList.begin()) { 527 //Inserting at begining, reschedule 528 sendEvent->reschedule(time); 529 } 530 cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr> 531 (time,pkt)); 532 done = true; 533 } 534 i++; 535 } 536 } 537 else { 538 if (pkt->cmd != MemCmd::UpgradeReq) 539 { 540 delete pkt->req; 541 delete pkt; 542 } 543 } 544 } 545 546 /** 547 * Send a reponse to the slave interface and calculate miss latency. 548 * @param pkt The request to respond to. 549 * @param time The time the response is ready. 550 */ 551 void respondToMiss(PacketPtr pkt, Tick time) 552 { 553 assert(time >= curTick); 554 if (!pkt->req->isUncacheable()) { 555 missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += 556 time - pkt->time; 557 } 558 if (pkt->needsResponse()) { 559/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); 560 reqCpu->schedule(time); 561*/ 562 if (cpuSidePort->transmitList.empty()) { 563 assert(!sendEvent->scheduled()); 564 sendEvent->schedule(time); 565 cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 566 (time,pkt)); 567 return; 568 } 569 570 // something is on the list and this belongs at the end 571 if (time >= cpuSidePort->transmitList.back().first) { 572 cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 573 (time,pkt)); 574 return; 575 } 576 // Something is on the list and this belongs somewhere else 577 std::list<std::pair<Tick,PacketPtr> >::iterator i = 578 cpuSidePort->transmitList.begin(); 579 std::list<std::pair<Tick,PacketPtr> >::iterator end = 580 cpuSidePort->transmitList.end(); 581 bool done = false; 582 583 while (i != end && !done) { 584 if (time < i->first) { 585 if (i == cpuSidePort->transmitList.begin()) { 586 //Inserting at begining, reschedule 587 sendEvent->reschedule(time); 588 } 589 cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr> 590 (time,pkt)); 591 done = true; 592 } 593 i++; 594 } 595 } 596 else { 597 if (pkt->cmd != MemCmd::UpgradeReq) 598 { 599 delete pkt->req; 600 delete pkt; 601 } 602 } 603 } 604 605 /** 606 * Suppliess the data if cache to cache transfers are enabled. 607 * @param pkt The bus transaction to fulfill. 608 */ 609 void respondToSnoop(PacketPtr pkt, Tick time) 610 { 611 assert(time >= curTick); 612 assert (pkt->needsResponse()); 613/* CacheEvent *reqMem = new CacheEvent(memSidePort, pkt); 614 reqMem->schedule(time); 615*/ 616 if (memSidePort->transmitList.empty()) { 617 assert(!memSendEvent->scheduled()); 618 memSendEvent->schedule(time); 619 memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 620 (time,pkt)); 621 return; 622 } 623 624 // something is on the list and this belongs at the end 625 if (time >= memSidePort->transmitList.back().first) { 626 memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr> 627 (time,pkt)); 628 return; 629 } 630 // Something is on the list and this belongs somewhere else 631 std::list<std::pair<Tick,PacketPtr> >::iterator i = 632 memSidePort->transmitList.begin(); 633 std::list<std::pair<Tick,PacketPtr> >::iterator end = 634 memSidePort->transmitList.end(); 635 bool done = false; 636 637 while (i != end && !done) { 638 if (time < i->first) { 639 if (i == memSidePort->transmitList.begin()) { 640 //Inserting at begining, reschedule 641 memSendEvent->reschedule(time); 642 } 643 memSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt)); 644 done = true; 645 } 646 i++; 647 } 648 } 649 650 /** 651 * Notification from master interface that a address range changed. Nothing 652 * to do for a cache. 653 */ 654 void rangeChange() {} 655 656 void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide) 657 { 658 if (isCpuSide) 659 { 660 AddrRangeList dummy; 661 memSidePort->getPeerAddressRanges(resp, dummy); 662 } 663 else 664 { 665 //This is where snoops get updated 666 AddrRangeList dummy; 667 cpuSidePort->getPeerAddressRanges(dummy, snoop); 668 return; 669 } 670 } 671 672 virtual unsigned int drain(Event *de); 673 674 void checkDrain() 675 { 676 if (drainEvent && canDrain()) { 677 drainEvent->process(); 678 changeState(SimObject::Drained); 679 // Clear the drain event 680 drainEvent = NULL; 681 } 682 } 683 684 bool canDrain() 685 { 686 if (doMasterRequest() || doSlaveRequest()) { 687 return false; 688 } else if (memSidePort && !memSidePort->canDrain()) { 689 return false; 690 } else if (cpuSidePort && !cpuSidePort->canDrain()) { 691 return false; 692 } 693 return true; 694 } 695 696 virtual bool inCache(Addr addr) = 0; 697 698 virtual bool inMissQueue(Addr addr) = 0; 699}; 700 701#endif //__BASE_CACHE_HH__ 702