/*
+ * 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) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Erik Hallnor
+ * Andreas Sandberg
*/
/** @file
* Definition of MSHRQueue class functions.
*/
-#include "mem/cache/miss/mshr_queue.hh"
+#include "mem/cache/mshr_queue.hh"
using namespace std;
MSHRQueue::MSHRQueue(const std::string &_label,
int num_entries, int reserve, int _index)
- : label(_label),
- numEntries(num_entries + reserve - 1), numReserve(reserve),
- index(_index)
+ : label(_label), numEntries(num_entries + reserve - 1),
+ numReserve(reserve), registers(numEntries),
+ drainManager(NULL), allocated(0), inServiceEntries(0), index(_index)
{
- allocated = 0;
- inServiceEntries = 0;
- registers = new MSHR[numEntries];
for (int i = 0; i < numEntries; ++i) {
registers[i].queue = this;
freeList.push_back(®isters[i]);
}
}
-MSHRQueue::~MSHRQueue()
-{
- delete [] registers;
-}
-
MSHR *
-MSHRQueue::findMatch(Addr addr) const
+MSHRQueue::findMatch(Addr addr, bool is_secure) const
{
MSHR::ConstIterator i = allocatedList.begin();
MSHR::ConstIterator end = allocatedList.end();
for (; i != end; ++i) {
MSHR *mshr = *i;
- if (mshr->addr == addr) {
+ if (mshr->addr == addr && mshr->isSecure == is_secure) {
return mshr;
}
}
}
bool
-MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
+MSHRQueue::findMatches(Addr addr, bool is_secure, vector<MSHR*>& matches) const
{
// Need an empty vector
assert(matches.empty());
MSHR::ConstIterator end = allocatedList.end();
for (; i != end; ++i) {
MSHR *mshr = *i;
- if (mshr->addr == addr) {
+ if (mshr->addr == addr && mshr->isSecure == is_secure) {
retval = true;
matches.push_back(mshr);
}
MSHR *
-MSHRQueue::findPending(Addr addr, int size) const
+MSHRQueue::findPending(Addr addr, int size, bool is_secure) const
{
MSHR::ConstIterator i = readyList.begin();
MSHR::ConstIterator end = readyList.end();
for (; i != end; ++i) {
MSHR *mshr = *i;
- if (mshr->addr < addr) {
- if (mshr->addr + mshr->size > addr) {
- return mshr;
- }
- } else {
- if (addr + size > mshr->addr) {
- return mshr;
+ if (mshr->isSecure == is_secure) {
+ if (mshr->addr < addr) {
+ if (mshr->addr + mshr->size > addr)
+ return mshr;
+ } else {
+ if (addr + size > mshr->addr)
+ return mshr;
}
}
}
readyList.erase(mshr->readyIter);
}
mshr->deallocate();
+ if (drainManager && allocated == 0) {
+ // Notify the drain manager that we have completed draining if
+ // there are no other outstanding requests in this MSHR queue.
+ drainManager->signalDrainDone();
+ drainManager = NULL;
+ setDrainState(Drainable::Drained);
+ }
return retval;
}
}
void
-MSHRQueue::markInService(MSHR *mshr)
+MSHRQueue::markInService(MSHR *mshr, PacketPtr pkt)
{
- if (mshr->markInService()) {
+ if (mshr->markInService(pkt)) {
deallocate(mshr);
} else {
readyList.erase(mshr->readyIter);
mshr->readyIter = addToReadyList(mshr);
}
+bool
+MSHRQueue::forceDeallocateTarget(MSHR *mshr)
+{
+ bool was_full = isFull();
+ assert(mshr->hasTargets());
+ // Pop the prefetch off of the target list
+ mshr->popTarget();
+ // Delete mshr if no remaining targets
+ if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
+ deallocateOne(mshr);
+ }
+
+ // Notify if MSHR queue no longer full
+ return was_full && !isFull();
+}
+
void
MSHRQueue::squash(int threadNum)
{
if (mshr->threadNum == threadNum) {
while (mshr->hasTargets()) {
mshr->popTarget();
- assert(0/*target->req->getThreadNum()*/ == threadNum);
+ assert(0/*target->req->threadId()*/ == threadNum);
}
assert(!mshr->hasTargets());
- assert(mshr->ntargets==0);
+ assert(mshr->getNumTargets()==0);
if (!mshr->inService) {
i = deallocateOne(mshr);
} else {
}
}
}
+
+unsigned int
+MSHRQueue::drain(DrainManager *dm)
+{
+ if (allocated == 0) {
+ setDrainState(Drainable::Drained);
+ return 0;
+ } else {
+ drainManager = dm;
+ setDrainState(Drainable::Draining);
+ return 1;
+ }
+}