/*
+ * Copyright (c) 2012-2013 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) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
/**
* Miss Status and handling Register. This class keeps all the information
* needed to handle a cache miss including a list of target requests.
+ * @sa \ref gem5MemorySystem "gem5 Memory System"
*/
class MSHR : public Packet::SenderState, public Printable
{
+ /**
+ * Consider the MSHRQueue a friend to avoid making everything public
+ */
+ friend class MSHRQueue;
+
+ private:
+
+ /** Cycle when ready to issue */
+ Tick readyTime;
+
+ /** True if the request is uncacheable */
+ bool _isUncacheable;
+
+ /** Flag set by downstream caches */
+ bool downstreamPending;
+
+ /** Will we have a dirty copy after this request? */
+ bool pendingDirty;
+
+ /** Did we snoop an invalidate while waiting for data? */
+ bool postInvalidate;
+
+ /** Did we snoop a read while waiting for data? */
+ bool postDowngrade;
+
public:
class Target {
public:
+
+ enum Source {
+ FromCPU,
+ FromSnoop,
+ FromPrefetcher
+ };
+
Tick recvTime; //!< Time when request was received (for stats)
Tick readyTime; //!< Time when request is ready to be serviced
Counter order; //!< Global order (for memory consistency mgmt)
PacketPtr pkt; //!< Pending request packet.
- bool cpuSide; //!< Did request come from cpu side or mem side?
+ Source source; //!< Did request come from cpu, memory, or prefetcher?
bool markedPending; //!< Did we mark upstream MSHR
//!< as downstreamPending?
- bool isCpuSide() const { return cpuSide; }
-
Target(PacketPtr _pkt, Tick _readyTime, Counter _order,
- bool _cpuSide, bool _markedPending)
- : recvTime(curTick), readyTime(_readyTime), order(_order),
- pkt(_pkt), cpuSide(_cpuSide), markedPending(_markedPending)
+ Source _source, bool _markedPending)
+ : recvTime(curTick()), readyTime(_readyTime), order(_order),
+ pkt(_pkt), source(_source), markedPending(_markedPending)
{}
};
void resetFlags() { needsExclusive = hasUpgrade = false; }
bool isReset() { return !needsExclusive && !hasUpgrade; }
void add(PacketPtr pkt, Tick readyTime, Counter order,
- bool cpuSide, bool markPending);
+ Target::Source source, bool markPending);
void replaceUpgrades();
void clearDownstreamPending();
bool checkFunctional(PacketPtr pkt);
/** Pointer to queue containing this MSHR. */
MSHRQueue *queue;
- /** Cycle when ready to issue */
- Tick readyTime;
-
/** Order number assigned by the miss queue. */
Counter order;
/** Size of the request. */
int size;
+ /** True if the request targets the secure memory space. */
+ bool isSecure;
+
/** True if the request has been sent to the bus. */
bool inService;
- /** True if we will be putting the returned block in the cache */
- bool isCacheFill;
+ /** True if the request is just a simple forward from an upper level */
+ bool isForward;
+
+ /** The pending* and post* flags are only valid if inService is
+ * true. Using the accessor functions lets us detect if these
+ * flags are accessed improperly.
+ */
/** True if we need to get an exclusive copy of the block. */
- bool needsExclusive() const { return targets->needsExclusive; }
+ bool needsExclusive() const { return targets.needsExclusive; }
- /** True if the request is uncacheable */
- bool _isUncacheable;
+ bool isPendingDirty() const {
+ assert(inService); return pendingDirty;
+ }
- bool downstreamPending;
+ bool hasPostInvalidate() const {
+ assert(inService); return postInvalidate;
+ }
- bool pendingInvalidate;
- bool pendingShared;
+ bool hasPostDowngrade() const {
+ assert(inService); return postDowngrade;
+ }
/** Thread number of the miss. */
- short threadNum;
- /** The number of currently allocated targets. */
- short ntargets;
+ ThreadID threadNum;
+ private:
/** Data buffer (if needed). Currently used only for pending
* upgrade handling. */
*/
Iterator allocIter;
-private:
/** List of all requests that match the address */
- TargetList *targets;
+ TargetList targets;
- TargetList *deferredTargets;
+ TargetList deferredTargets;
-public:
+ public:
- bool isUncacheable() { return _isUncacheable; }
+ bool isUncacheable() const { return _isUncacheable; }
/**
* Allocate a miss to this MSHR.
void allocate(Addr addr, int size, PacketPtr pkt,
Tick when, Counter _order);
- bool markInService();
+ bool markInService(PacketPtr pkt);
void clearDownstreamPending();
/** A simple constructor. */
MSHR();
- /** A simple destructor. */
- ~MSHR();
/**
* Returns the current number of allocated targets.
* @return The current number of allocated targets.
*/
- int getNumTargets() { return ntargets; }
-
- /**
- * Returns a pointer to the target list.
- * @return a pointer to the target list.
- */
- TargetList *getTargetList() { return targets; }
+ int getNumTargets() const
+ { return targets.size() + deferredTargets.size(); }
/**
* Returns true if there are targets left.
* @return true if there are targets
*/
- bool hasTargets() { return !targets->empty(); }
+ bool hasTargets() const { return !targets.empty(); }
/**
* Returns a reference to the first target.
* @return A pointer to the first target.
*/
- Target *getTarget() { assert(hasTargets()); return &targets->front(); }
+ Target *getTarget()
+ {
+ assert(hasTargets());
+ return &targets.front();
+ }
/**
* Pop first target.
*/
void popTarget()
{
- --ntargets;
- targets->pop_front();
+ targets.pop_front();
}
- bool isSimpleForward()
+ bool isForwardNoResponse() const
{
if (getNumTargets() != 1)
return false;
- Target *tgt = getTarget();
- return tgt->isCpuSide() && !tgt->pkt->needsResponse();
+ const Target *tgt = &targets.front();
+ return tgt->source == Target::FromCPU && !tgt->pkt->needsResponse();
}
bool promoteDeferredTargets();
void print(std::ostream &os,
int verbosity = 0,
const std::string &prefix = "") const;
+ /**
+ * A no-args wrapper of print(std::ostream...) meant to be
+ * invoked from DPRINTFs avoiding string overheads in fast mode
+ *
+ * @return string with mshr fields + [deferred]targets
+ */
+ std::string print() const;
};
#endif //__MSHR_HH__