X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Fcache%2Fbase.hh;h=47cbaf7a0c0fc3dbf3700799e5ceb4beb281f5f0;hb=f9d403a7b95c50a8b75f8442101eb87ca465f967;hp=601e9bd485b7de40691f02c95cb64b7bcdfb866e;hpb=dd99ff23c6a71f7173014b5008d0cf12b7ef223a;p=gem5.git diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index 601e9bd48..47cbaf7a0 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2012 ARM Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2003-2005 The Regents of The University of Michigan * All rights reserved. * @@ -38,23 +50,27 @@ #ifndef __BASE_CACHE_HH__ #define __BASE_CACHE_HH__ -#include -#include -#include #include -#include +#include +#include +#include #include "base/misc.hh" #include "base/statistics.hh" #include "base/trace.hh" +#include "base/types.hh" +#include "debug/Cache.hh" +#include "debug/CachePort.hh" #include "mem/cache/mshr_queue.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" -#include "mem/tport.hh" +#include "mem/qport.hh" #include "mem/request.hh" #include "params/BaseCache.hh" #include "sim/eventq.hh" +#include "sim/full_system.hh" #include "sim/sim_exit.hh" +#include "sim/system.hh" class MSHR; /** @@ -70,6 +86,7 @@ class BaseCache : public MemObject MSHRQueue_WriteBuffer }; + public: /** * Reasons for caches to be blocked. */ @@ -80,7 +97,6 @@ class BaseCache : public MemObject NUM_BLOCKED_CAUSES }; - public: /** * Reasons for cache to request a bus. */ @@ -91,63 +107,109 @@ class BaseCache : public MemObject NUM_REQUEST_CAUSES }; - private: + protected: - class CachePort : public SimpleTimingPort + /** + * A cache master port is used for the memory-side port of the + * cache, and in addition to the basic timing port that only sends + * response packets through a transmit list, it also offers the + * ability to schedule and send request packets (requests & + * writebacks). The send event is scheduled through requestBus, + * and the sendDeferredPacket of the timing port is modified to + * consider both the transmit list and the requests from the MSHR. + */ + class CacheMasterPort : public QueuedMasterPort { - public: - BaseCache *cache; - protected: - CachePort(const std::string &_name, BaseCache *_cache, - const std::string &_label, - std::vector > filter_ranges); + public: - virtual void recvStatusChange(Status status); + /** + * Schedule a send of a request packet (from the MSHR). Note + * that we could already have a retry or a transmit list of + * responses outstanding. + */ + void requestBus(RequestCause cause, Tick time) + { + DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause); + queue.schedSendEvent(time); + } - virtual int deviceBlockSize(); + /** + * Schedule the transmissions of a response packet at a given + * point in time. + * + * @param pkt response packet + * @param when time to send the response + */ + void respond(PacketPtr pkt, Tick time) { + queue.schedSendTiming(pkt, time); + } - bool recvRetryCommon(); + protected: - typedef EventWrapper - SendRetryEvent; + CacheMasterPort(const std::string &_name, BaseCache *_cache, + PacketQueue &_queue) : + QueuedMasterPort(_name, _cache, _queue) + { } + + /** + * Memory-side port always snoops. + * + * @return always true + */ + virtual bool isSnooping() const { return true; } + }; - const std::string label; + /** + * A cache slave port is used for the CPU-side port of the cache, + * and it is basically a simple timing port that uses a transmit + * list for responses to the CPU (or connected master). In + * addition, it has the functionality to block the port for + * incoming requests. If blocked, the port will issue a retry once + * unblocked. + */ + class CacheSlavePort : public QueuedSlavePort + { public: - void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; } + /** Do not accept any new requests. */ void setBlocked(); + /** Return to normal operation and accept new requests. */ void clearBlocked(); - bool checkFunctional(PacketPtr pkt); + /** + * Schedule the transmissions of a response packet at a given + * point in time. + * + * @param pkt response packet + * @param when time to send the response + */ + void respond(PacketPtr pkt, Tick time) { + queue.schedSendTiming(pkt, time); + } + + protected: - CachePort *otherPort; + CacheSlavePort(const std::string &_name, BaseCache *_cache, + const std::string &_label); + + /** A normal packet queue used to store responses. */ + PacketQueue queue; bool blocked; bool mustSendRetry; - /** filter ranges */ - std::vector > filterRanges; + private: - void requestBus(RequestCause cause, Tick time) - { - DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause); - if (!waitingOnRetry) { - schedSendEvent(time); - } - } + EventWrapper sendRetryEvent; - void respond(PacketPtr pkt, Tick time) { - schedSendTiming(pkt, time); - } }; - public: //Made public so coherence can get at it. - CachePort *cpuSidePort; - CachePort *memSidePort; + CacheSlavePort *cpuSidePort; + CacheMasterPort *memSidePort; protected: @@ -173,18 +235,18 @@ class BaseCache : public MemObject return mshr; } - void markInServiceInternal(MSHR *mshr) + void markInServiceInternal(MSHR *mshr, PacketPtr pkt) { MSHRQueue *mq = mshr->queue; bool wasFull = mq->isFull(); - mq->markInService(mshr); + mq->markInService(mshr, pkt); if (wasFull && !mq->isFull()) { clearBlocked((BlockedCause)mq->index); } } /** Block size of this cache */ - const int blkSize; + const unsigned blkSize; /** * The latency of a hit in this device. @@ -194,8 +256,13 @@ class BaseCache : public MemObject /** The number of targets for each MSHR. */ const int numTarget; - /** Increasing order number assigned to each incoming request. */ - uint64_t order; + /** Do we forward snoops from mem side port through to cpu side port? */ + bool forwardSnoops; + + /** Is this cache a toplevel cache (e.g. L1, I/O cache). If so we should + * never try to forward ownership and similar optimizations to the cpu + * side */ + bool isTopLevel; /** * Bit vector of the blocking reasons for the access path. @@ -203,6 +270,9 @@ class BaseCache : public MemObject */ uint8_t blocked; + /** Increasing order number assigned to each incoming request. */ + uint64_t order; + /** Stores time the cache blocked for statistics. */ Tick blockedCycle; @@ -215,7 +285,15 @@ class BaseCache : public MemObject /** The drain event. */ Event *drainEvent; + /** + * The address range to which the cache responds on the CPU side. + * Normally this is all possible memory addresses. */ + AddrRangeList addrRanges; + public: + /** System we are currently operating in. */ + System *system; + // Statistics /** * @addtogroup CacheStatistics @@ -223,14 +301,14 @@ class BaseCache : public MemObject */ /** Number of hits per thread for each type of command. @sa Packet::Command */ - Stats::Vector<> hits[MemCmd::NUM_MEM_CMDS]; + Stats::Vector hits[MemCmd::NUM_MEM_CMDS]; /** Number of hits for demand accesses. */ Stats::Formula demandHits; /** Number of hit for all accesses. */ Stats::Formula overallHits; /** Number of misses per thread for each type of command. @sa Packet::Command */ - Stats::Vector<> misses[MemCmd::NUM_MEM_CMDS]; + Stats::Vector misses[MemCmd::NUM_MEM_CMDS]; /** Number of misses for demand accesses. */ Stats::Formula demandMisses; /** Number of misses for all accesses. */ @@ -240,7 +318,7 @@ class BaseCache : public MemObject * Total number of cycles per thread/command spent waiting for a miss. * Used to calculate the average miss latency. */ - Stats::Vector<> missLatency[MemCmd::NUM_MEM_CMDS]; + Stats::Vector missLatency[MemCmd::NUM_MEM_CMDS]; /** Total number of cycles spent waiting for demand misses. */ Stats::Formula demandMissLatency; /** Total number of cycles spent waiting for all misses. */ @@ -268,59 +346,61 @@ class BaseCache : public MemObject Stats::Formula overallAvgMissLatency; /** The total number of cycles blocked for each blocked cause. */ - Stats::Vector<> blocked_cycles; + Stats::Vector blocked_cycles; /** The number of times this cache blocked for each blocked cause. */ - Stats::Vector<> blocked_causes; + Stats::Vector blocked_causes; /** The average number of cycles blocked for each blocked cause. */ Stats::Formula avg_blocked; /** The number of fast writes (WH64) performed. */ - Stats::Scalar<> fastWrites; + Stats::Scalar fastWrites; /** The number of cache copies performed. */ - Stats::Scalar<> cacheCopies; + Stats::Scalar cacheCopies; /** Number of blocks written back per thread. */ - Stats::Vector<> writebacks; + Stats::Vector writebacks; /** Number of misses that hit in the MSHRs per command and thread. */ - Stats::Vector<> mshr_hits[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_hits[MemCmd::NUM_MEM_CMDS]; /** Demand misses that hit in the MSHRs. */ Stats::Formula demandMshrHits; /** Total number of misses that hit in the MSHRs. */ Stats::Formula overallMshrHits; /** Number of misses that miss in the MSHRs, per command and thread. */ - Stats::Vector<> mshr_misses[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_misses[MemCmd::NUM_MEM_CMDS]; /** Demand misses that miss in the MSHRs. */ Stats::Formula demandMshrMisses; /** Total number of misses that miss in the MSHRs. */ Stats::Formula overallMshrMisses; /** Number of misses that miss in the MSHRs, per command and thread. */ - Stats::Vector<> mshr_uncacheable[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_uncacheable[MemCmd::NUM_MEM_CMDS]; /** Total number of misses that miss in the MSHRs. */ Stats::Formula overallMshrUncacheable; /** Total cycle latency of each MSHR miss, per command and thread. */ - Stats::Vector<> mshr_miss_latency[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_miss_latency[MemCmd::NUM_MEM_CMDS]; /** Total cycle latency of demand MSHR misses. */ Stats::Formula demandMshrMissLatency; /** Total cycle latency of overall MSHR misses. */ Stats::Formula overallMshrMissLatency; /** Total cycle latency of each MSHR miss, per command and thread. */ - Stats::Vector<> mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS]; /** Total cycle latency of overall MSHR misses. */ Stats::Formula overallMshrUncacheableLatency; +#if 0 /** The total number of MSHR accesses per command and thread. */ Stats::Formula mshrAccesses[MemCmd::NUM_MEM_CMDS]; /** The total number of demand MSHR accesses. */ Stats::Formula demandMshrAccesses; /** The total number of MSHR accesses. */ Stats::Formula overallMshrAccesses; +#endif /** The miss rate in the MSHRs pre command and thread. */ Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS]; @@ -342,11 +422,11 @@ class BaseCache : public MemObject Stats::Formula overallAvgMshrUncacheableLatency; /** The number of times a thread hit its MSHR cap. */ - Stats::Vector<> mshr_cap_events; + Stats::Vector mshr_cap_events; /** The number of times software prefetches caused the MSHR to block. */ - Stats::Vector<> soft_prefetch_mshr_full; + Stats::Vector soft_prefetch_mshr_full; - Stats::Scalar<> mshr_no_allocate_misses; + Stats::Scalar mshr_no_allocate_misses; /** * @} @@ -364,19 +444,25 @@ class BaseCache : public MemObject virtual void init(); + virtual MasterPort &getMasterPort(const std::string &if_name, int idx = -1); + virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1); + /** * Query block size of a cache. * @return The block size */ - int getBlockSize() const + unsigned + getBlockSize() const { return blkSize; } - Addr blockAlign(Addr addr) const { return (addr & ~(blkSize - 1)); } + Addr blockAlign(Addr addr) const { return (addr & ~(Addr(blkSize - 1))); } + const AddrRangeList &getAddrRanges() const { return addrRanges; } + MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool requestBus) { assert(!pkt->req->isUncacheable()); @@ -420,7 +506,7 @@ class BaseCache : public MemObject uint8_t flag = 1 << cause; if (blocked == 0) { blocked_causes[cause]++; - blockedCycle = curTick; + blockedCycle = curTick(); cpuSidePort->setBlocked(); } blocked |= flag; @@ -440,17 +526,11 @@ class BaseCache : public MemObject blocked &= ~flag; DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked); if (blocked == 0) { - blocked_cycles[cause] += curTick - blockedCycle; + blocked_cycles[cause] += curTick() - blockedCycle; cpuSidePort->clearBlocked(); } } - Tick nextMSHRReadyTime() - { - return std::min(mshrQueue.nextMSHRReadyTime(), - writeBuffer.nextMSHRReadyTime()); - } - /** * Request the master bus for the given cause and time. * @param cause The reason for the request. @@ -467,10 +547,11 @@ class BaseCache : public MemObject */ void deassertMemSideBusRequest(RequestCause cause) { - // obsolete!! - assert(false); - // memSidePort->deassertBusRequest(cause); - // checkDrain(); + // Obsolete... we no longer signal bus requests explicitly so + // we can't deassert them. Leaving this in as a no-op since + // the prefetcher calls it to indicate that it no longer wants + // to request a prefetch, and someday that might be + // interesting again. } virtual unsigned int drain(Event *de); @@ -481,7 +562,8 @@ class BaseCache : public MemObject void incMissCount(PacketPtr pkt) { - misses[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; + assert(pkt->req->masterId() < system->maxMasters()); + misses[pkt->cmdToIndex()][pkt->req->masterId()]++; if (missCount) { --missCount; @@ -489,6 +571,12 @@ class BaseCache : public MemObject exitSimLoop("A cache reached the maximum miss count"); } } + void incHitCount(PacketPtr pkt) + { + assert(pkt->req->masterId() < system->maxMasters()); + hits[pkt->cmdToIndex()][pkt->req->masterId()]++; + + } };