/*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2013 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
#include "mem/cache/mshr_queue.hh"
#include "mem/mem_object.hh"
#include "mem/packet.hh"
+#include "mem/qport.hh"
#include "mem/request.hh"
-#include "mem/tport.hh"
#include "params/BaseCache.hh"
#include "sim/eventq.hh"
#include "sim/full_system.hh"
Blocked_NoMSHRs = MSHRQueue_MSHRs,
Blocked_NoWBBuffers = MSHRQueue_WriteBuffer,
Blocked_NoTargets,
+ Blocked_PendingWriteInvalidate,
NUM_BLOCKED_CAUSES
};
* and the sendDeferredPacket of the timing port is modified to
* consider both the transmit list and the requests from the MSHR.
*/
- class CacheMasterPort : public SimpleTimingPort
+ class CacheMasterPort : public QueuedMasterPort
{
public:
void requestBus(RequestCause cause, Tick time)
{
DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause);
- schedSendEvent(time);
- }
-
- void respond(PacketPtr pkt, Tick time) {
- schedSendTiming(pkt, time);
+ queue.schedSendEvent(time);
}
protected:
CacheMasterPort(const std::string &_name, BaseCache *_cache,
- const std::string &_label);
+ MasterPacketQueue &_queue) :
+ QueuedMasterPort(_name, _cache, _queue)
+ { }
/**
* Memory-side port always snoops.
*
- * return always true
+ * @return always true
*/
- virtual bool isSnooping() { return true; }
+ virtual bool isSnooping() const { return true; }
};
/**
* incoming requests. If blocked, the port will issue a retry once
* unblocked.
*/
- class CacheSlavePort : public SimpleTimingPort
+ class CacheSlavePort : public QueuedSlavePort
{
public:
/** Return to normal operation and accept new requests. */
void clearBlocked();
- void respond(PacketPtr pkt, Tick time) {
- schedSendTiming(pkt, time);
- }
+ bool isBlocked() const { return blocked; }
protected:
CacheSlavePort(const std::string &_name, BaseCache *_cache,
const std::string &_label);
+ /** A normal packet queue used to store responses. */
+ SlavePacketQueue queue;
+
bool blocked;
bool mustSendRetry;
private:
- EventWrapper<Port, &Port::sendRetry> sendRetryEvent;
+ void processSendRetry();
+
+ EventWrapper<CacheSlavePort,
+ &CacheSlavePort::processSendRetry> sendRetryEvent;
};
}
}
+ /**
+ * Write back dirty blocks in the cache using functional accesses.
+ */
+ virtual void memWriteback() = 0;
+ /**
+ * Invalidates all blocks in the cache.
+ *
+ * @warn Dirty cache lines will not be written back to
+ * memory. Make sure to call functionalWriteback() first if you
+ * want the to write them to memory.
+ */
+ virtual void memInvalidate() = 0;
+ /**
+ * Determine if there are any dirty blocks in the cache.
+ *
+ * \return true if at least one block is dirty, false otherwise.
+ */
+ virtual bool isDirty() const = 0;
+
/** Block size of this cache */
const unsigned blkSize;
/**
* The latency of a hit in this device.
*/
- int hitLatency;
+ const Cycles hitLatency;
+
+ /**
+ * The latency of sending reponse to its upper level cache/core on a
+ * linefill. In most contemporary processors, the return path on a cache
+ * miss is much quicker that the hit latency. The responseLatency parameter
+ * tries to capture this latency.
+ */
+ const Cycles responseLatency;
/** The number of targets for each MSHR. */
const int numTarget;
/** Do we forward snoops from mem side port through to cpu side port? */
- bool forwardSnoops;
+ const 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;
+ const bool isTopLevel;
/**
* Bit vector of the blocking reasons for the access path.
uint64_t order;
/** Stores time the cache blocked for statistics. */
- Tick blockedCycle;
+ Cycles blockedCycle;
/** Pointer to the MSHR that has no targets. */
MSHR *noTargetMSHR;
/** The number of misses to trigger an exit event. */
Counter missCount;
- /** The drain event. */
- Event *drainEvent;
-
/**
* The address range to which the cache responds on the CPU side.
* Normally this is all possible memory addresses. */
- Range<Addr> addrRange;
+ const AddrRangeList addrRanges;
public:
/** System we are currently operating in. */
virtual void init();
+ virtual BaseMasterPort &getMasterPort(const std::string &if_name,
+ PortID idx = InvalidPortID);
+ virtual BaseSlavePort &getSlavePort(const std::string &if_name,
+ PortID idx = InvalidPortID);
+
/**
* Query block size of a cache.
* @return The block size
Addr blockAlign(Addr addr) const { return (addr & ~(Addr(blkSize - 1))); }
- const Range<Addr> &getAddrRange() const { return addrRange; }
+ const AddrRangeList &getAddrRanges() const { return addrRanges; }
MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool requestBus)
{
/**
* Returns true if the cache is blocked for accesses.
*/
- bool isBlocked()
+ bool isBlocked() const
{
return blocked != 0;
}
uint8_t flag = 1 << cause;
if (blocked == 0) {
blocked_causes[cause]++;
- blockedCycle = curTick();
+ blockedCycle = curCycle();
cpuSidePort->setBlocked();
}
blocked |= flag;
blocked &= ~flag;
DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked);
if (blocked == 0) {
- blocked_cycles[cause] += curTick() - blockedCycle;
+ blocked_cycles[cause] += curCycle() - blockedCycle;
cpuSidePort->clearBlocked();
}
}
// interesting again.
}
- virtual unsigned int drain(Event *de);
+ virtual unsigned int drain(DrainManager *dm);
- virtual bool inCache(Addr addr) = 0;
+ virtual bool inCache(Addr addr, bool is_secure) const = 0;
- virtual bool inMissQueue(Addr addr) = 0;
+ virtual bool inMissQueue(Addr addr, bool is_secure) const = 0;
void incMissCount(PacketPtr pkt)
{
assert(pkt->req->masterId() < system->maxMasters());
misses[pkt->cmdToIndex()][pkt->req->masterId()]++;
-
+ pkt->req->incAccessDepth();
if (missCount) {
--missCount;
if (missCount == 0)