summaryrefslogtreecommitdiff
path: root/src/mem/cache/miss
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/cache/miss')
-rw-r--r--src/mem/cache/miss/SConscript3
-rw-r--r--src/mem/cache/miss/blocking_buffer.cc245
-rw-r--r--src/mem/cache/miss/blocking_buffer.hh209
-rw-r--r--src/mem/cache/miss/miss_buffer.cc62
-rw-r--r--src/mem/cache/miss/miss_buffer.hh223
-rw-r--r--src/mem/cache/miss/miss_queue.cc752
-rw-r--r--src/mem/cache/miss/miss_queue.hh327
-rw-r--r--src/mem/cache/miss/mshr.cc308
-rw-r--r--src/mem/cache/miss/mshr.hh152
-rw-r--r--src/mem/cache/miss/mshr_queue.cc132
-rw-r--r--src/mem/cache/miss/mshr_queue.hh151
11 files changed, 455 insertions, 2109 deletions
diff --git a/src/mem/cache/miss/SConscript b/src/mem/cache/miss/SConscript
index 0f81a2570..376d670cd 100644
--- a/src/mem/cache/miss/SConscript
+++ b/src/mem/cache/miss/SConscript
@@ -30,8 +30,5 @@
Import('*')
-Source('blocking_buffer.cc')
-Source('miss_buffer.cc')
-Source('miss_queue.cc')
Source('mshr.cc')
Source('mshr_queue.cc')
diff --git a/src/mem/cache/miss/blocking_buffer.cc b/src/mem/cache/miss/blocking_buffer.cc
deleted file mode 100644
index e8ff26880..000000000
--- a/src/mem/cache/miss/blocking_buffer.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Erik Hallnor
- */
-
-/**
- * @file
- * Definitions of a simple buffer for a blocking cache.
- */
-#include <cstring>
-
-#include "mem/cache/base_cache.hh"
-#include "mem/cache/miss/blocking_buffer.hh"
-#include "mem/cache/prefetch/base_prefetcher.hh"
-#include "mem/request.hh"
-
-/**
- * @todo Move writebacks into shared BaseBuffer class.
- */
-void
-BlockingBuffer::regStats(const std::string &name)
-{
- MissBuffer::regStats(name);
-}
-
-
-void
-BlockingBuffer::handleMiss(PacketPtr &pkt, int blk_size, Tick time)
-{
- Addr blk_addr = pkt->getAddr() & ~(Addr)(blk_size - 1);
- if (pkt->isWrite() && (pkt->req->isUncacheable() || !writeAllocate ||
- !pkt->needsResponse())) {
- if (!pkt->needsResponse()) {
- wb.allocateAsBuffer(pkt);
- } else {
- wb.allocate(pkt->cmd, blk_addr, blk_size, pkt);
- }
-
- std::memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), blk_size);
-
- cache->setBlocked(Blocked_NoWBBuffers);
- cache->setMasterRequest(Request_WB, time);
- return;
- }
-
- if (!pkt->needsResponse()) {
- miss.allocateAsBuffer(pkt);
- } else {
- miss.allocate(pkt->cmd, blk_addr, blk_size, pkt);
- }
- if (!pkt->req->isUncacheable()) {
- miss.pkt->flags |= CACHE_LINE_FILL;
- }
- cache->setBlocked(Blocked_NoMSHRs);
- cache->setMasterRequest(Request_MSHR, time);
-}
-
-PacketPtr
-BlockingBuffer::getPacket()
-{
- if (miss.pkt && !miss.inService) {
- return miss.pkt;
- }
- return wb.pkt;
-}
-
-void
-BlockingBuffer::setBusCmd(PacketPtr &pkt, MemCmd cmd)
-{
- MSHR *mshr = (MSHR*) pkt->senderState;
- mshr->originalCmd = pkt->cmd;
- if (pkt->isCacheFill())
- pkt->cmdOverride(cmd);
-}
-
-void
-BlockingBuffer::restoreOrigCmd(PacketPtr &pkt)
-{
- pkt->cmdOverride(((MSHR*)(pkt->senderState))->originalCmd);
-}
-
-void
-BlockingBuffer::markInService(PacketPtr &pkt, MSHR* mshr)
-{
- if (!pkt->isCacheFill() && pkt->isWrite()) {
- // Forwarding a write/ writeback, don't need to change
- // the command
- assert(mshr == &wb);
- cache->clearMasterRequest(Request_WB);
- if (!pkt->needsResponse()) {
- assert(wb.getNumTargets() == 0);
- wb.deallocate();
- cache->clearBlocked(Blocked_NoWBBuffers);
- } else {
- wb.inService = true;
- }
- } else {
- assert(mshr == &miss);
- cache->clearMasterRequest(Request_MSHR);
- if (!pkt->needsResponse()) {
- assert(miss.getNumTargets() == 0);
- miss.deallocate();
- cache->clearBlocked(Blocked_NoMSHRs);
- } else {
- //mark in service
- miss.inService = true;
- }
- }
-}
-
-void
-BlockingBuffer::handleResponse(PacketPtr &pkt, Tick time)
-{
- if (pkt->isCacheFill()) {
- // targets were handled in the cache tags
- assert((MSHR*)pkt->senderState == &miss);
- miss.deallocate();
- cache->clearBlocked(Blocked_NoMSHRs);
- } else {
- if (((MSHR*)(pkt->senderState))->hasTargets()) {
- // Should only have 1 target if we had any
- assert(((MSHR*)(pkt->senderState))->getNumTargets() == 1);
- PacketPtr target = ((MSHR*)(pkt->senderState))->getTarget();
- ((MSHR*)(pkt->senderState))->popTarget();
- if (pkt->isRead()) {
- std::memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), target->getSize());
- }
- cache->respond(target, time);
- assert(!((MSHR*)(pkt->senderState))->hasTargets());
- }
-
- if (pkt->isWrite()) {
- assert(((MSHR*)(pkt->senderState)) == &wb);
- wb.deallocate();
- cache->clearBlocked(Blocked_NoWBBuffers);
- } else {
- miss.deallocate();
- cache->clearBlocked(Blocked_NoMSHRs);
- }
- }
-}
-
-void
-BlockingBuffer::squash(int threadNum)
-{
- if (miss.threadNum == threadNum) {
- PacketPtr target = miss.getTarget();
- miss.popTarget();
- assert(0/*target->req->getThreadNum()*/ == threadNum);
- target = NULL;
- assert(!miss.hasTargets());
- miss.ntargets=0;
- if (!miss.inService) {
- miss.deallocate();
- cache->clearBlocked(Blocked_NoMSHRs);
- cache->clearMasterRequest(Request_MSHR);
- }
- }
-}
-
-void
-BlockingBuffer::doWriteback(Addr addr,
- int size, uint8_t *data, bool compressed)
-{
- // Generate request
- Request * req = new Request(addr, size, 0);
- PacketPtr pkt = new Packet(req, MemCmd::Writeback, -1);
- pkt->allocate();
- if (data) {
- std::memcpy(pkt->getPtr<uint8_t>(), data, size);
- }
-
- if (compressed) {
- pkt->flags |= COMPRESSED;
- }
-
- ///All writebacks charged to same thread @todo figure this out
- writebacks[0/*pkt->req->getThreadNum()*/]++;
-
- wb.allocateAsBuffer(pkt);
- cache->setMasterRequest(Request_WB, curTick);
- cache->setBlocked(Blocked_NoWBBuffers);
-}
-
-
-
-void
-BlockingBuffer::doWriteback(PacketPtr &pkt)
-{
- writebacks[0/*pkt->req->getThreadNum()*/]++;
-
- wb.allocateAsBuffer(pkt);
-
- // Since allocate as buffer copies the request,
- // need to copy data here.
- std::memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), pkt->getSize());
-
- cache->setBlocked(Blocked_NoWBBuffers);
- cache->setMasterRequest(Request_WB, curTick);
-}
-
-
-MSHR *
-BlockingBuffer::findMSHR(Addr addr)
-{
- if (miss.addr == addr && miss.pkt)
- return &miss;
- return NULL;
-}
-
-
-bool
-BlockingBuffer::findWrites(Addr addr, std::vector<MSHR*>& writes)
-{
- if (wb.addr == addr && wb.pkt) {
- writes.push_back(&wb);
- return true;
- }
- return false;
-}
diff --git a/src/mem/cache/miss/blocking_buffer.hh b/src/mem/cache/miss/blocking_buffer.hh
deleted file mode 100644
index 86b24d539..000000000
--- a/src/mem/cache/miss/blocking_buffer.hh
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Erik Hallnor
- */
-
-/**
- * @file
- * Declaration of a simple buffer for a blocking cache.
- */
-
-#ifndef __BLOCKING_BUFFER_HH__
-#define __BLOCKING_BUFFER_HH__
-
-#include <vector>
-
-#include "base/misc.hh" // for fatal()
-#include "mem/cache/miss/miss_buffer.hh"
-#include "mem/cache/miss/mshr.hh"
-
-/**
- * Miss and writeback storage for a blocking cache.
- */
-class BlockingBuffer : public MissBuffer
-{
-protected:
- /** Miss storage. */
- MSHR miss;
- /** WB storage. */
- MSHR wb;
-
-public:
- /**
- * Builds and initializes this buffer.
- * @param write_allocate If true, treat write misses the same as reads.
- */
- BlockingBuffer(bool write_allocate)
- : MissBuffer(write_allocate)
- {
- }
-
- /**
- * Register statistics for this object.
- * @param name The name of the parent cache.
- */
- void regStats(const std::string &name);
-
- /**
- * Handle a cache miss properly. Requests the bus and marks the cache as
- * blocked.
- * @param pkt The request that missed in the cache.
- * @param blk_size The block size of the cache.
- * @param time The time the miss is detected.
- */
- void handleMiss(PacketPtr &pkt, int blk_size, Tick time);
-
- /**
- * Fetch the block for the given address and buffer the given target.
- * @param addr The address to fetch.
- * @param asid The address space of the address.
- * @param blk_size The block size of the cache.
- * @param time The time the miss is detected.
- * @param target The target for the fetch.
- */
- MSHR* fetchBlock(Addr addr, int blk_size, Tick time,
- PacketPtr &target)
- {
- fatal("Unimplemented");
- M5_DUMMY_RETURN
- }
-
- /**
- * Selects a outstanding request to service.
- * @return The request to service, NULL if none found.
- */
- PacketPtr getPacket();
-
- /**
- * Set the command to the given bus command.
- * @param pkt The request to update.
- * @param cmd The bus command to use.
- */
- void setBusCmd(PacketPtr &pkt, MemCmd cmd);
-
- /**
- * Restore the original command in case of a bus transmission error.
- * @param pkt The request to reset.
- */
- void restoreOrigCmd(PacketPtr &pkt);
-
- /**
- * Marks a request as in service (sent on the bus). This can have side
- * effect since storage for no response commands is deallocated once they
- * are successfully sent.
- * @param pkt The request that was sent on the bus.
- */
- void markInService(PacketPtr &pkt, MSHR* mshr);
-
- /**
- * Frees the resources of the request and unblock the cache.
- * @param pkt The request that has been satisfied.
- * @param time The time when the request is satisfied.
- */
- void handleResponse(PacketPtr &pkt, Tick time);
-
- /**
- * Removes all outstanding requests for a given thread number. If a request
- * has been sent to the bus, this function removes all of its targets.
- * @param threadNum The thread number of the requests to squash.
- */
- void squash(int threadNum);
-
- /**
- * Return the current number of outstanding misses.
- * @return the number of outstanding misses.
- */
- int getMisses()
- {
- return miss.getNumTargets();
- }
-
- /**
- * Searches for the supplied address in the miss "queue".
- * @param addr The address to look for.
- * @param asid The address space id.
- * @return A pointer to miss if it matches.
- */
- MSHR* findMSHR(Addr addr);
-
- /**
- * Searches for the supplied address in the write buffer.
- * @param addr The address to look for.
- * @param asid The address space id.
- * @param writes List of pointers to the matching writes.
- * @return True if there is a matching write.
- */
- bool findWrites(Addr addr, std::vector<MSHR*>& writes);
-
- /**
- * Perform a writeback of dirty data to the given address.
- * @param addr The address to write to.
- * @param asid The address space id.
- * @param size The number of bytes to write.
- * @param data The data to write, can be NULL.
- * @param compressed True if the data is compressed.
- */
- void doWriteback(Addr addr,
- int size, uint8_t *data, bool compressed);
-
- /**
- * Perform a writeback request.
- * @param pkt The writeback request.
- */
- void doWriteback(PacketPtr &pkt);
-
- /**
- * Returns true if there are outstanding requests.
- * @return True if there are outstanding requests.
- */
- bool havePending()
- {
- return !miss.inService || !wb.inService;
- }
-
- /**
- * Add a target to the given MSHR. This assumes it is in the miss queue.
- * @param mshr The mshr to add a target to.
- * @param pkt The target to add.
- */
- void addTarget(MSHR *mshr, PacketPtr &pkt)
- {
- fatal("Shouldn't call this on a blocking buffer.");
- }
-
- /**
- * Dummy implmentation.
- */
- MSHR* allocateTargetList(Addr addr)
- {
- fatal("Unimplemented");
- M5_DUMMY_RETURN
- }
-};
-
-#endif // __BLOCKING_BUFFER_HH__
diff --git a/src/mem/cache/miss/miss_buffer.cc b/src/mem/cache/miss/miss_buffer.cc
deleted file mode 100644
index 4d9cd0958..000000000
--- a/src/mem/cache/miss/miss_buffer.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2003-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Erik Hallnor
- */
-
-#include "cpu/smt.hh" //for maxThreadsPerCPU
-#include "mem/cache/base_cache.hh"
-#include "mem/cache/miss/miss_buffer.hh"
-#include "mem/cache/prefetch/base_prefetcher.hh"
-
-/**
- * @todo Move writebacks into shared BaseBuffer class.
- */
-void
-MissBuffer::regStats(const std::string &name)
-{
- using namespace Stats;
- writebacks
- .init(maxThreadsPerCPU)
- .name(name + ".writebacks")
- .desc("number of writebacks")
- .flags(total)
- ;
-}
-
-void
-MissBuffer::setCache(BaseCache *_cache)
-{
- cache = _cache;
- blkSize = cache->getBlockSize();
-}
-
-void
-MissBuffer::setPrefetcher(BasePrefetcher *_prefetcher)
-{
- prefetcher = _prefetcher;
-}
diff --git a/src/mem/cache/miss/miss_buffer.hh b/src/mem/cache/miss/miss_buffer.hh
deleted file mode 100644
index 9a86db304..000000000
--- a/src/mem/cache/miss/miss_buffer.hh
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (c) 2003-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Steve Reinhardt
- */
-
-/**
- * @file
- * MissBuffer declaration.
- */
-
-#ifndef __MISS_BUFFER_HH__
-#define __MISS_BUFFER_HH__
-
-class BaseCache;
-class BasePrefetcher;
-class MSHR;
-
-/**
- * Abstract base class for cache miss buffering.
- */
-class MissBuffer
-{
- protected:
- /** True if the cache should allocate on a write miss. */
- const bool writeAllocate;
-
- /** Pointer to the parent cache. */
- BaseCache *cache;
-
- /** The Prefetcher */
- BasePrefetcher *prefetcher;
-
- /** Block size of the parent cache. */
- int blkSize;
-
- // Statistics
- /**
- * @addtogroup CacheStatistics
- * @{
- */
- /** Number of blocks written back per thread. */
- Stats::Vector<> writebacks;
-
- /**
- * @}
- */
-
- public:
- MissBuffer(bool write_allocate)
- : writeAllocate(write_allocate)
- {
- }
-
- virtual ~MissBuffer() {}
-
- /**
- * Called by the parent cache to set the back pointer.
- * @param _cache A pointer to the parent cache.
- */
- void setCache(BaseCache *_cache);
-
- void setPrefetcher(BasePrefetcher *_prefetcher);
-
- /**
- * Register statistics for this object.
- * @param name The name of the parent cache.
- */
- virtual void regStats(const std::string &name);
-
- /**
- * Handle a cache miss properly. Either allocate an MSHR for the request,
- * or forward it through the write buffer.
- * @param pkt The request that missed in the cache.
- * @param blk_size The block size of the cache.
- * @param time The time the miss is detected.
- */
- virtual void handleMiss(PacketPtr &pkt, int blk_size, Tick time) = 0;
-
- /**
- * Fetch the block for the given address and buffer the given target.
- * @param addr The address to fetch.
- * @param asid The address space of the address.
- * @param blk_size The block size of the cache.
- * @param time The time the miss is detected.
- * @param target The target for the fetch.
- */
- virtual MSHR *fetchBlock(Addr addr, int blk_size, Tick time,
- PacketPtr &target) = 0;
-
- /**
- * Selects a outstanding request to service.
- * @return The request to service, NULL if none found.
- */
- virtual PacketPtr getPacket() = 0;
-
- /**
- * Set the command to the given bus command.
- * @param pkt The request to update.
- * @param cmd The bus command to use.
- */
- virtual void setBusCmd(PacketPtr &pkt, MemCmd cmd) = 0;
-
- /**
- * Restore the original command in case of a bus transmission error.
- * @param pkt The request to reset.
- */
- virtual void restoreOrigCmd(PacketPtr &pkt) = 0;
-
- /**
- * Marks a request as in service (sent on the bus). This can have side
- * effect since storage for no response commands is deallocated once they
- * are successfully sent.
- * @param pkt The request that was sent on the bus.
- */
- virtual void markInService(PacketPtr &pkt, MSHR* mshr) = 0;
-
- /**
- * Collect statistics and free resources of a satisfied request.
- * @param pkt The request that has been satisfied.
- * @param time The time when the request is satisfied.
- */
- virtual void handleResponse(PacketPtr &pkt, Tick time) = 0;
-
- /**
- * Removes all outstanding requests for a given thread number. If a request
- * has been sent to the bus, this function removes all of its targets.
- * @param threadNum The thread number of the requests to squash.
- */
- virtual void squash(int threadNum) = 0;
-
- /**
- * Return the current number of outstanding misses.
- * @return the number of outstanding misses.
- */
- virtual int getMisses() = 0;
-
- /**
- * Searches for the supplied address in the miss queue.
- * @param addr The address to look for.
- * @param asid The address space id.
- * @return The MSHR that contains the address, NULL if not found.
- * @warning Currently only searches the miss queue. If non write allocate
- * might need to search the write buffer for coherence.
- */
- virtual MSHR* findMSHR(Addr addr) = 0;
-
- /**
- * Searches for the supplied address in the write buffer.
- * @param addr The address to look for.
- * @param asid The address space id.
- * @param writes The list of writes that match the address.
- * @return True if any writes are found
- */
- virtual bool findWrites(Addr addr, std::vector<MSHR*>& writes) = 0;
-
- /**
- * Perform a writeback of dirty data to the given address.
- * @param addr The address to write to.
- * @param asid The address space id.
- * @param xc The execution context of the address space.
- * @param size The number of bytes to write.
- * @param data The data to write, can be NULL.
- * @param compressed True if the data is compressed.
- */
- virtual void doWriteback(Addr addr, int size, uint8_t *data,
- bool compressed) = 0;
-
- /**
- * Perform the given writeback request.
- * @param pkt The writeback request.
- */
- virtual void doWriteback(PacketPtr &pkt) = 0;
-
- /**
- * Returns true if there are outstanding requests.
- * @return True if there are outstanding requests.
- */
- virtual bool havePending() = 0;
-
- /**
- * Add a target to the given MSHR. This assumes it is in the miss queue.
- * @param mshr The mshr to add a target to.
- * @param pkt The target to add.
- */
- virtual void addTarget(MSHR *mshr, PacketPtr &pkt) = 0;
-
- /**
- * Allocate a MSHR to hold a list of targets to a block involved in a copy.
- * If the block is marked done then the MSHR already holds the data to
- * fill the block. Otherwise the block needs to be fetched.
- * @param addr The address to buffer.
- * @param asid The address space ID.
- * @return A pointer to the allocated MSHR.
- */
- virtual MSHR* allocateTargetList(Addr addr) = 0;
-};
-
-#endif //__MISS_BUFFER_HH__
diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc
deleted file mode 100644
index 24ca9cfa2..000000000
--- a/src/mem/cache/miss/miss_queue.cc
+++ /dev/null
@@ -1,752 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Erik Hallnor
- * Ron Dreslinski
- */
-
-/**
- * @file
- * Miss and writeback queue definitions.
- */
-
-#include "cpu/smt.hh" //for maxThreadsPerCPU
-#include "mem/cache/base_cache.hh"
-#include "mem/cache/miss/miss_queue.hh"
-#include "mem/cache/prefetch/base_prefetcher.hh"
-
-using namespace std;
-
-// simple constructor
-/**
- * @todo Remove the +16 from the write buffer constructor once we handle
- * stalling on writebacks do to compression writes.
- */
-MissQueue::MissQueue(int numMSHRs, int numTargets, int write_buffers,
- bool write_allocate, bool prefetch_miss)
- : MissBuffer(write_allocate),
- mq(numMSHRs, 4), wb(write_buffers,numMSHRs+1000), numMSHR(numMSHRs),
- numTarget(numTargets), writeBuffers(write_buffers),
- order(0), prefetchMiss(prefetch_miss)
-{
- noTargetMSHR = NULL;
-}
-
-
-MissQueue::~MissQueue()
-{
-}
-
-
-void
-MissQueue::regStats(const string &name)
-{
- MissBuffer::regStats(name);
-
- using namespace Stats;
-
- // MSHR hit statistics
- for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
- MemCmd cmd(access_idx);
- const string &cstr = cmd.toString();
-
- mshr_hits[access_idx]
- .init(maxThreadsPerCPU)
- .name(name + "." + cstr + "_mshr_hits")
- .desc("number of " + cstr + " MSHR hits")
- .flags(total | nozero | nonan)
- ;
- }
-
- demandMshrHits
- .name(name + ".demand_mshr_hits")
- .desc("number of demand (read+write) MSHR hits")
- .flags(total)
- ;
- demandMshrHits = mshr_hits[MemCmd::ReadReq] + mshr_hits[MemCmd::WriteReq];
-
- overallMshrHits
- .name(name + ".overall_mshr_hits")
- .desc("number of overall MSHR hits")
- .flags(total)
- ;
- overallMshrHits = demandMshrHits + mshr_hits[MemCmd::SoftPFReq] +
- mshr_hits[MemCmd::HardPFReq];
-
- // MSHR miss statistics
- for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
- MemCmd cmd(access_idx);
- const string &cstr = cmd.toString();
-
- mshr_misses[access_idx]
- .init(maxThreadsPerCPU)
- .name(name + "." + cstr + "_mshr_misses")
- .desc("number of " + cstr + " MSHR misses")
- .flags(total | nozero | nonan)
- ;
- }
-
- demandMshrMisses
- .name(name + ".demand_mshr_misses")
- .desc("number of demand (read+write) MSHR misses")
- .flags(total)
- ;
- demandMshrMisses = mshr_misses[MemCmd::ReadReq] + mshr_misses[MemCmd::WriteReq];
-
- overallMshrMisses
- .name(name + ".overall_mshr_misses")
- .desc("number of overall MSHR misses")
- .flags(total)
- ;
- overallMshrMisses = demandMshrMisses + mshr_misses[MemCmd::SoftPFReq] +
- mshr_misses[MemCmd::HardPFReq];
-
- // MSHR miss latency statistics
- for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
- MemCmd cmd(access_idx);
- const string &cstr = cmd.toString();
-
- mshr_miss_latency[access_idx]
- .init(maxThreadsPerCPU)
- .name(name + "." + cstr + "_mshr_miss_latency")
- .desc("number of " + cstr + " MSHR miss cycles")
- .flags(total | nozero | nonan)
- ;
- }
-
- demandMshrMissLatency
- .name(name + ".demand_mshr_miss_latency")
- .desc("number of demand (read+write) MSHR miss cycles")
- .flags(total)
- ;
- demandMshrMissLatency = mshr_miss_latency[MemCmd::ReadReq]
- + mshr_miss_latency[MemCmd::WriteReq];
-
- overallMshrMissLatency
- .name(name + ".overall_mshr_miss_latency")
- .desc("number of overall MSHR miss cycles")
- .flags(total)
- ;
- overallMshrMissLatency = demandMshrMissLatency +
- mshr_miss_latency[MemCmd::SoftPFReq] + mshr_miss_latency[MemCmd::HardPFReq];
-
- // MSHR uncacheable statistics
- for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
- MemCmd cmd(access_idx);
- const string &cstr = cmd.toString();
-
- mshr_uncacheable[access_idx]
- .init(maxThreadsPerCPU)
- .name(name + "." + cstr + "_mshr_uncacheable")
- .desc("number of " + cstr + " MSHR uncacheable")
- .flags(total | nozero | nonan)
- ;
- }
-
- overallMshrUncacheable
- .name(name + ".overall_mshr_uncacheable_misses")
- .desc("number of overall MSHR uncacheable misses")
- .flags(total)
- ;
- overallMshrUncacheable = mshr_uncacheable[MemCmd::ReadReq]
- + mshr_uncacheable[MemCmd::WriteReq] + mshr_uncacheable[MemCmd::SoftPFReq]
- + mshr_uncacheable[MemCmd::HardPFReq];
-
- // MSHR miss latency statistics
- for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
- MemCmd cmd(access_idx);
- const string &cstr = cmd.toString();
-
- mshr_uncacheable_lat[access_idx]
- .init(maxThreadsPerCPU)
- .name(name + "." + cstr + "_mshr_uncacheable_latency")
- .desc("number of " + cstr + " MSHR uncacheable cycles")
- .flags(total | nozero | nonan)
- ;
- }
-
- overallMshrUncacheableLatency
- .name(name + ".overall_mshr_uncacheable_latency")
- .desc("number of overall MSHR uncacheable cycles")
- .flags(total)
- ;
- overallMshrUncacheableLatency = mshr_uncacheable_lat[MemCmd::ReadReq]
- + mshr_uncacheable_lat[MemCmd::WriteReq]
- + mshr_uncacheable_lat[MemCmd::SoftPFReq]
- + mshr_uncacheable_lat[MemCmd::HardPFReq];
-
-#if 0
- // MSHR access formulas
- for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
- MemCmd cmd(access_idx);
- const string &cstr = cmd.toString();
-
- mshrAccesses[access_idx]
- .name(name + "." + cstr + "_mshr_accesses")
- .desc("number of " + cstr + " mshr accesses(hits+misses)")
- .flags(total | nozero | nonan)
- ;
- mshrAccesses[access_idx] =
- mshr_hits[access_idx] + mshr_misses[access_idx]
- + mshr_uncacheable[access_idx];
- }
-
- demandMshrAccesses
- .name(name + ".demand_mshr_accesses")
- .desc("number of demand (read+write) mshr accesses")
- .flags(total | nozero | nonan)
- ;
- demandMshrAccesses = demandMshrHits + demandMshrMisses;
-
- overallMshrAccesses
- .name(name + ".overall_mshr_accesses")
- .desc("number of overall (read+write) mshr accesses")
- .flags(total | nozero | nonan)
- ;
- overallMshrAccesses = overallMshrHits + overallMshrMisses
- + overallMshrUncacheable;
-#endif
-
- // MSHR miss rate formulas
- for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
- MemCmd cmd(access_idx);
- const string &cstr = cmd.toString();
-
- mshrMissRate[access_idx]
- .name(name + "." + cstr + "_mshr_miss_rate")
- .desc("mshr miss rate for " + cstr + " accesses")
- .flags(total | nozero | nonan)
- ;
-
- mshrMissRate[access_idx] =
- mshr_misses[access_idx] / cache->accesses[access_idx];
- }
-
- demandMshrMissRate
- .name(name + ".demand_mshr_miss_rate")
- .desc("mshr miss rate for demand accesses")
- .flags(total)
- ;
- demandMshrMissRate = demandMshrMisses / cache->demandAccesses;
-
- overallMshrMissRate
- .name(name + ".overall_mshr_miss_rate")
- .desc("mshr miss rate for overall accesses")
- .flags(total)
- ;
- overallMshrMissRate = overallMshrMisses / cache->overallAccesses;
-
- // mshrMiss latency formulas
- for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
- MemCmd cmd(access_idx);
- const string &cstr = cmd.toString();
-
- avgMshrMissLatency[access_idx]
- .name(name + "." + cstr + "_avg_mshr_miss_latency")
- .desc("average " + cstr + " mshr miss latency")
- .flags(total | nozero | nonan)
- ;
-
- avgMshrMissLatency[access_idx] =
- mshr_miss_latency[access_idx] / mshr_misses[access_idx];
- }
-
- demandAvgMshrMissLatency
- .name(name + ".demand_avg_mshr_miss_latency")
- .desc("average overall mshr miss latency")
- .flags(total)
- ;
- demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
-
- overallAvgMshrMissLatency
- .name(name + ".overall_avg_mshr_miss_latency")
- .desc("average overall mshr miss latency")
- .flags(total)
- ;
- overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
-
- // mshrUncacheable latency formulas
- for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
- MemCmd cmd(access_idx);
- const string &cstr = cmd.toString();
-
- avgMshrUncacheableLatency[access_idx]
- .name(name + "." + cstr + "_avg_mshr_uncacheable_latency")
- .desc("average " + cstr + " mshr uncacheable latency")
- .flags(total | nozero | nonan)
- ;
-
- avgMshrUncacheableLatency[access_idx] =
- mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
- }
-
- overallAvgMshrUncacheableLatency
- .name(name + ".overall_avg_mshr_uncacheable_latency")
- .desc("average overall mshr uncacheable latency")
- .flags(total)
- ;
- overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
-
- mshr_cap_events
- .init(maxThreadsPerCPU)
- .name(name + ".mshr_cap_events")
- .desc("number of times MSHR cap was activated")
- .flags(total)
- ;
-
- //software prefetching stats
- soft_prefetch_mshr_full
- .init(maxThreadsPerCPU)
- .name(name + ".soft_prefetch_mshr_full")
- .desc("number of mshr full events for SW prefetching instrutions")
- .flags(total)
- ;
-
- mshr_no_allocate_misses
- .name(name +".no_allocate_misses")
- .desc("Number of misses that were no-allocate")
- ;
-
-}
-
-
-MSHR*
-MissQueue::allocateMiss(PacketPtr &pkt, int size, Tick time)
-{
- MSHR* mshr = mq.allocate(pkt, size);
- mshr->order = order++;
- if (!pkt->req->isUncacheable() ){//&& !pkt->isNoAllocate()) {
- // Mark this as a cache line fill
- mshr->pkt->flags |= CACHE_LINE_FILL;
- }
- if (mq.isFull()) {
- cache->setBlocked(Blocked_NoMSHRs);
- }
- if (pkt->cmd != MemCmd::HardPFReq) {
- //If we need to request the bus (not on HW prefetch), do so
- cache->setMasterRequest(Request_MSHR, time);
- }
- return mshr;
-}
-
-
-MSHR*
-MissQueue::allocateWrite(PacketPtr &pkt, int size, Tick time)
-{
- MSHR* mshr = wb.allocate(pkt,size);
- mshr->order = order++;
-
-//REMOVING COMPRESSION FOR NOW
-#if 0
- if (pkt->isCompressed()) {
- mshr->pkt->deleteData();
- mshr->pkt->actualSize = pkt->actualSize;
- mshr->pkt->data = new uint8_t[pkt->actualSize];
- memcpy(mshr->pkt->data, pkt->data, pkt->actualSize);
- } else {
-#endif
- memcpy(mshr->pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), pkt->getSize());
- //{
-
- if (wb.isFull()) {
- cache->setBlocked(Blocked_NoWBBuffers);
- }
-
- cache->setMasterRequest(Request_WB, time);
-
- return mshr;
-}
-
-
-/**
- * @todo Remove SW prefetches on mshr hits.
- */
-void
-MissQueue::handleMiss(PacketPtr &pkt, int blkSize, Tick time)
-{
-// if (!cache->isTopLevel())
- if (prefetchMiss) prefetcher->handleMiss(pkt, time);
-
- int size = blkSize;
- Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1);
- MSHR* mshr = NULL;
- if (!pkt->req->isUncacheable()) {
- mshr = mq.findMatch(blkAddr);
- if (mshr) {
- //@todo remove hw_pf here
- mshr_hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
- if (mshr->threadNum != 0/*pkt->req->getThreadNum()*/) {
- mshr->threadNum = -1;
- }
- mq.allocateTarget(mshr, pkt);
- if (mshr->pkt->isNoAllocate() && !pkt->isNoAllocate()) {
- //We are adding an allocate after a no-allocate
- mshr->pkt->flags &= ~NO_ALLOCATE;
- }
- if (mshr->getNumTargets() == numTarget) {
- noTargetMSHR = mshr;
- cache->setBlocked(Blocked_NoTargets);
- mq.moveToFront(mshr);
- }
- return;
- }
- if (pkt->isNoAllocate()) {
- //Count no-allocate requests differently
- mshr_no_allocate_misses++;
- }
- else {
- mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
- }
- } else {
- //Count uncacheable accesses
- mshr_uncacheable[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
- size = pkt->getSize();
- }
- if (pkt->isWrite() && (pkt->req->isUncacheable() || !writeAllocate ||
- !pkt->needsResponse())) {
- /**
- * @todo Add write merging here.
- */
- mshr = allocateWrite(pkt, pkt->getSize(), time);
- return;
- }
-
- mshr = allocateMiss(pkt, blkSize, time);
-}
-
-MSHR*
-MissQueue::fetchBlock(Addr addr, int blk_size, Tick time,
- PacketPtr &target)
-{
- Addr blkAddr = addr & ~(Addr)(blk_size - 1);
- assert(mq.findMatch(addr) == NULL);
- MSHR *mshr = mq.allocateFetch(blkAddr, blk_size, target);
- mshr->order = order++;
- mshr->pkt->flags |= CACHE_LINE_FILL;
- if (mq.isFull()) {
- cache->setBlocked(Blocked_NoMSHRs);
- }
- cache->setMasterRequest(Request_MSHR, time);
- return mshr;
-}
-
-PacketPtr
-MissQueue::getPacket()
-{
- PacketPtr pkt = mq.getReq();
- if (((wb.isFull() && wb.inServiceMSHRs == 0) || !pkt ||
- pkt->time > curTick) && wb.havePending()) {
- pkt = wb.getReq();
- // Need to search for earlier miss.
- MSHR *mshr = mq.findPending(pkt);
- if (mshr && mshr->order < ((MSHR*)(pkt->senderState))->order) {
- // Service misses in order until conflict is cleared.
- return mq.getReq();
- }
- }
- if (pkt) {
- MSHR* mshr = wb.findPending(pkt);
- if (mshr /*&& mshr->order < pkt->senderState->order*/) {
- // The only way this happens is if we are
- // doing a write and we didn't have permissions
- // then subsequently saw a writeback(owned got evicted)
- // We need to make sure to perform the writeback first
- // To preserve the dirty data, then we can issue the write
- return wb.getReq();
- }
- }
- else if (!mq.isFull()){
- //If we have a miss queue slot, we can try a prefetch
- pkt = prefetcher->getPacket();
- if (pkt) {
- //Update statistic on number of prefetches issued (hwpf_mshr_misses)
- mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
- //It will request the bus for the future, but should clear that immedieatley
- allocateMiss(pkt, pkt->getSize(), curTick);
- pkt = mq.getReq();
- assert(pkt); //We should get back a req b/c we just put one in
- }
- }
- return pkt;
-}
-
-void
-MissQueue::setBusCmd(PacketPtr &pkt, MemCmd cmd)
-{
- assert(pkt->senderState != 0);
- MSHR * mshr = (MSHR*)pkt->senderState;
- mshr->originalCmd = pkt->cmd;
- if (cmd == MemCmd::UpgradeReq || cmd == MemCmd::InvalidateReq) {
- pkt->flags |= NO_ALLOCATE;
- pkt->flags &= ~CACHE_LINE_FILL;
- }
- else if (!pkt->req->isUncacheable() && !pkt->isNoAllocate() &&
- cmd.needsResponse()) {
- pkt->flags |= CACHE_LINE_FILL;
- }
- if (pkt->isCacheFill() || pkt->isNoAllocate())
- pkt->cmd = cmd;
-}
-
-void
-MissQueue::restoreOrigCmd(PacketPtr &pkt)
-{
- pkt->cmd = ((MSHR*)(pkt->senderState))->originalCmd;
-}
-
-void
-MissQueue::markInService(PacketPtr &pkt, MSHR* mshr)
-{
- bool unblock = false;
- BlockedCause cause = NUM_BLOCKED_CAUSES;
-
- /**
- * @todo Should include MSHRQueue pointer in MSHR to select the correct
- * one.
- */
- if ((!pkt->isCacheFill() && pkt->isWrite())) {
- // Forwarding a write/ writeback, don't need to change
- // the command
- unblock = wb.isFull();
- wb.markInService(mshr);
- if (!wb.havePending()){
- cache->clearMasterRequest(Request_WB);
- }
- if (unblock) {
- // Do we really unblock?
- unblock = !wb.isFull();
- cause = Blocked_NoWBBuffers;
- }
- } else {
- unblock = mq.isFull();
- mq.markInService(mshr);
- if (!mq.havePending()){
- cache->clearMasterRequest(Request_MSHR);
- }
- if (mshr->originalCmd == MemCmd::HardPFReq) {
- DPRINTF(HWPrefetch, "%s:Marking a HW_PF in service\n",
- cache->name());
- //Also clear pending if need be
- if (!prefetcher->havePending())
- {
- cache->clearMasterRequest(Request_PF);
- }
- }
- if (unblock) {
- unblock = !mq.isFull();
- cause = Blocked_NoMSHRs;
- }
- }
- if (unblock) {
- cache->clearBlocked(cause);
- }
-}
-
-
-void
-MissQueue::handleResponse(PacketPtr &pkt, Tick time)
-{
- MSHR* mshr = (MSHR*)pkt->senderState;
- if (((MSHR*)(pkt->senderState))->originalCmd == MemCmd::HardPFReq) {
- DPRINTF(HWPrefetch, "%s:Handling the response to a HW_PF\n",
- cache->name());
- }
-#ifndef NDEBUG
- int num_targets = mshr->getNumTargets();
-#endif
-
- bool unblock = false;
- bool unblock_target = false;
- BlockedCause cause = NUM_BLOCKED_CAUSES;
-
- if (pkt->isCacheFill() && !pkt->isNoAllocate()) {
- mshr_miss_latency[mshr->originalCmd.toInt()][0/*pkt->req->getThreadNum()*/] +=
- curTick - pkt->time;
- // targets were handled in the cache tags
- if (mshr == noTargetMSHR) {
- // we always clear at least one target
- unblock_target = true;
- cause = Blocked_NoTargets;
- noTargetMSHR = NULL;
- }
-
- if (mshr->hasTargets()) {
- // Didn't satisfy all the targets, need to resend
- MemCmd cmd = mshr->getTarget()->cmd;
- mshr->pkt->setDest(Packet::Broadcast);
- mshr->pkt->result = Packet::Unknown;
- mshr->pkt->req = mshr->getTarget()->req;
- mq.markPending(mshr, cmd);
- mshr->order = order++;
- cache->setMasterRequest(Request_MSHR, time);
- }
- else {
- unblock = mq.isFull();
- mq.deallocate(mshr);
- if (unblock) {
- unblock = !mq.isFull();
- cause = Blocked_NoMSHRs;
- }
- }
- } else {
- if (pkt->req->isUncacheable()) {
- mshr_uncacheable_lat[pkt->cmd.toInt()][0/*pkt->req->getThreadNum()*/] +=
- curTick - pkt->time;
- }
- if (mshr->hasTargets() && pkt->req->isUncacheable()) {
- // Should only have 1 target if we had any
- assert(num_targets == 1);
- PacketPtr target = mshr->getTarget();
- mshr->popTarget();
- if (pkt->isRead()) {
- memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(),
- target->getSize());
- }
- cache->respond(target, time);
- assert(!mshr->hasTargets());
- }
- else if (mshr->hasTargets()) {
- //Must be a no_allocate with possibly more than one target
- assert(mshr->pkt->isNoAllocate());
- while (mshr->hasTargets()) {
- PacketPtr target = mshr->getTarget();
- mshr->popTarget();
- if (pkt->isRead()) {
- memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(),
- target->getSize());
- }
- cache->respond(target, time);
- }
- }
-
- if (pkt->isWrite()) {
- // If the wrtie buffer is full, we might unblock now
- unblock = wb.isFull();
- wb.deallocate(mshr);
- if (unblock) {
- // Did we really unblock?
- unblock = !wb.isFull();
- cause = Blocked_NoWBBuffers;
- }
- } else {
- unblock = mq.isFull();
- mq.deallocate(mshr);
- if (unblock) {
- unblock = !mq.isFull();
- cause = Blocked_NoMSHRs;
- }
- }
- }
- if (unblock || unblock_target) {
- cache->clearBlocked(cause);
- }
-}
-
-void
-MissQueue::squash(int threadNum)
-{
- bool unblock = false;
- BlockedCause cause = NUM_BLOCKED_CAUSES;
-
- if (noTargetMSHR && noTargetMSHR->threadNum == threadNum) {
- noTargetMSHR = NULL;
- unblock = true;
- cause = Blocked_NoTargets;
- }
- if (mq.isFull()) {
- unblock = true;
- cause = Blocked_NoMSHRs;
- }
- mq.squash(threadNum);
- if (!mq.havePending()) {
- cache->clearMasterRequest(Request_MSHR);
- }
- if (unblock && !mq.isFull()) {
- cache->clearBlocked(cause);
- }
-
-}
-
-MSHR*
-MissQueue::findMSHR(Addr addr)
-{
- return mq.findMatch(addr);
-}
-
-bool
-MissQueue::findWrites(Addr addr, vector<MSHR*> &writes)
-{
- return wb.findMatches(addr,writes);
-}
-
-void
-MissQueue::doWriteback(Addr addr,
- int size, uint8_t *data, bool compressed)
-{
- // Generate request
- Request * req = new Request(addr, size, 0);
- PacketPtr pkt = new Packet(req, MemCmd::Writeback, -1);
- pkt->allocate();
- if (data) {
- memcpy(pkt->getPtr<uint8_t>(), data, size);
- }
-
- if (compressed) {
- pkt->flags |= COMPRESSED;
- }
-
- ///All writebacks charged to same thread @todo figure this out
- writebacks[0/*pkt->req->getThreadNum()*/]++;
-
- allocateWrite(pkt, 0, curTick);
-}
-
-
-void
-MissQueue::doWriteback(PacketPtr &pkt)
-{
- writebacks[0/*pkt->req->getThreadNum()*/]++;
- allocateWrite(pkt, 0, curTick);
-}
-
-
-MSHR*
-MissQueue::allocateTargetList(Addr addr)
-{
- MSHR* mshr = mq.allocateTargetList(addr, blkSize);
- mshr->pkt->flags |= CACHE_LINE_FILL;
- if (mq.isFull()) {
- cache->setBlocked(Blocked_NoMSHRs);
- }
- return mshr;
-}
-
-bool
-MissQueue::havePending()
-{
- return mq.havePending() || wb.havePending() || prefetcher->havePending();
-}
diff --git a/src/mem/cache/miss/miss_queue.hh b/src/mem/cache/miss/miss_queue.hh
deleted file mode 100644
index d3560ff36..000000000
--- a/src/mem/cache/miss/miss_queue.hh
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Erik Hallnor
- */
-
-/**
- * @file
- * Miss and writeback queue declarations.
- */
-
-#ifndef __MISS_QUEUE_HH__
-#define __MISS_QUEUE_HH__
-
-#include <vector>
-
-#include "mem/cache/miss/miss_buffer.hh"
-#include "mem/cache/miss/mshr.hh"
-#include "mem/cache/miss/mshr_queue.hh"
-#include "base/statistics.hh"
-
-/**
- * Manages cache misses and writebacks. Contains MSHRs to store miss data
- * and the writebuffer for writes/writebacks.
- * @todo need to handle data on writes better (encapsulate).
- * @todo need to make replacements/writebacks happen in Cache::access
- */
-class MissQueue : public MissBuffer
-{
- protected:
- /** The MSHRs. */
- MSHRQueue mq;
- /** Write Buffer. */
- MSHRQueue wb;
-
- // PARAMTERS
-
- /** The number of MSHRs in the miss queue. */
- const int numMSHR;
- /** The number of targets for each MSHR. */
- const int numTarget;
- /** The number of write buffers. */
- const int writeBuffers;
-
- /** Increasing order number assigned to each incoming request. */
- uint64_t order;
-
- bool prefetchMiss;
-
- // Statistics
- /**
- * @addtogroup CacheStatistics
- * @{
- */
- /** Number of misses that hit in the MSHRs per command and thread. */
- 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];
- /** 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];
- /** 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];
- /** 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];
- /** Total cycle latency of overall MSHR misses. */
- Stats::Formula overallMshrUncacheableLatency;
-
- /** 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;
-
- /** The miss rate in the MSHRs pre command and thread. */
- Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS];
- /** The demand miss rate in the MSHRs. */
- Stats::Formula demandMshrMissRate;
- /** The overall miss rate in the MSHRs. */
- Stats::Formula overallMshrMissRate;
-
- /** The average latency of an MSHR miss, per command and thread. */
- Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS];
- /** The average latency of a demand MSHR miss. */
- Stats::Formula demandAvgMshrMissLatency;
- /** The average overall latency of an MSHR miss. */
- Stats::Formula overallAvgMshrMissLatency;
-
- /** The average latency of an MSHR miss, per command and thread. */
- Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS];
- /** The average overall latency of an MSHR miss. */
- Stats::Formula overallAvgMshrUncacheableLatency;
-
- /** The number of times a thread hit its MSHR cap. */
- Stats::Vector<> mshr_cap_events;
- /** The number of times software prefetches caused the MSHR to block. */
- Stats::Vector<> soft_prefetch_mshr_full;
-
- Stats::Scalar<> mshr_no_allocate_misses;
-
- /**
- * @}
- */
-
- private:
- /** Pointer to the MSHR that has no targets. */
- MSHR* noTargetMSHR;
-
- /**
- * Allocate a new MSHR to handle the provided miss.
- * @param pkt The miss to buffer.
- * @param size The number of bytes to fetch.
- * @param time The time the miss occurs.
- * @return A pointer to the new MSHR.
- */
- MSHR* allocateMiss(PacketPtr &pkt, int size, Tick time);
-
- /**
- * Allocate a new WriteBuffer to handle the provided write.
- * @param pkt The write to handle.
- * @param size The number of bytes to write.
- * @param time The time the write occurs.
- * @return A pointer to the new write buffer.
- */
- MSHR* allocateWrite(PacketPtr &pkt, int size, Tick time);
-
- public:
- /**
- * Simple Constructor. Initializes all needed internal storage and sets
- * parameters.
- * @param numMSHRs The number of outstanding misses to handle.
- * @param numTargets The number of outstanding targets to each miss.
- * @param write_buffers The number of outstanding writes to handle.
- * @param write_allocate If true, treat write misses the same as reads.
- */
- MissQueue(int numMSHRs, int numTargets, int write_buffers,
- bool write_allocate, bool prefetch_miss);
-
- /**
- * Deletes all allocated internal storage.
- */
- ~MissQueue();
-
- /**
- * Register statistics for this object.
- * @param name The name of the parent cache.
- */
- void regStats(const std::string &name);
-
- /**
- * Handle a cache miss properly. Either allocate an MSHR for the request,
- * or forward it through the write buffer.
- * @param pkt The request that missed in the cache.
- * @param blk_size The block size of the cache.
- * @param time The time the miss is detected.
- */
- void handleMiss(PacketPtr &pkt, int blk_size, Tick time);
-
- /**
- * Fetch the block for the given address and buffer the given target.
- * @param addr The address to fetch.
- * @param asid The address space of the address.
- * @param blk_size The block size of the cache.
- * @param time The time the miss is detected.
- * @param target The target for the fetch.
- */
- MSHR* fetchBlock(Addr addr, int blk_size, Tick time,
- PacketPtr &target);
-
- /**
- * Selects a outstanding request to service.
- * @return The request to service, NULL if none found.
- */
- PacketPtr getPacket();
-
- /**
- * Set the command to the given bus command.
- * @param pkt The request to update.
- * @param cmd The bus command to use.
- */
- void setBusCmd(PacketPtr &pkt, MemCmd cmd);
-
- /**
- * Restore the original command in case of a bus transmission error.
- * @param pkt The request to reset.
- */
- void restoreOrigCmd(PacketPtr &pkt);
-
- /**
- * Marks a request as in service (sent on the bus). This can have side
- * effect since storage for no response commands is deallocated once they
- * are successfully sent.
- * @param pkt The request that was sent on the bus.
- */
- void markInService(PacketPtr &pkt, MSHR* mshr);
-
- /**
- * Collect statistics and free resources of a satisfied request.
- * @param pkt The request that has been satisfied.
- * @param time The time when the request is satisfied.
- */
- void handleResponse(PacketPtr &pkt, Tick time);
-
- /**
- * Removes all outstanding requests for a given thread number. If a request
- * has been sent to the bus, this function removes all of its targets.
- * @param threadNum The thread number of the requests to squash.
- */
- void squash(int threadNum);
-
- /**
- * Return the current number of outstanding misses.
- * @return the number of outstanding misses.
- */
- int getMisses()
- {
- return mq.getAllocatedTargets();
- }
-
- /**
- * Searches for the supplied address in the miss queue.
- * @param addr The address to look for.
- * @param asid The address space id.
- * @return The MSHR that contains the address, NULL if not found.
- * @warning Currently only searches the miss queue. If non write allocate
- * might need to search the write buffer for coherence.
- */
- MSHR* findMSHR(Addr addr);
-
- /**
- * Searches for the supplied address in the write buffer.
- * @param addr The address to look for.
- * @param asid The address space id.
- * @param writes The list of writes that match the address.
- * @return True if any writes are found
- */
- bool findWrites(Addr addr, std::vector<MSHR*>& writes);
-
- /**
- * Perform a writeback of dirty data to the given address.
- * @param addr The address to write to.
- * @param asid The address space id.
- * @param xc The execution context of the address space.
- * @param size The number of bytes to write.
- * @param data The data to write, can be NULL.
- * @param compressed True if the data is compressed.
- */
- void doWriteback(Addr addr,
- int size, uint8_t *data, bool compressed);
-
- /**
- * Perform the given writeback request.
- * @param pkt The writeback request.
- */
- void doWriteback(PacketPtr &pkt);
-
- /**
- * Returns true if there are outstanding requests.
- * @return True if there are outstanding requests.
- */
- bool havePending();
-
- /**
- * Add a target to the given MSHR. This assumes it is in the miss queue.
- * @param mshr The mshr to add a target to.
- * @param pkt The target to add.
- */
- void addTarget(MSHR *mshr, PacketPtr &pkt)
- {
- mq.allocateTarget(mshr, pkt);
- }
-
- /**
- * Allocate a MSHR to hold a list of targets to a block involved in a copy.
- * If the block is marked done then the MSHR already holds the data to
- * fill the block. Otherwise the block needs to be fetched.
- * @param addr The address to buffer.
- * @param asid The address space ID.
- * @return A pointer to the allocated MSHR.
- */
- MSHR* allocateTargetList(Addr addr);
-
-};
-
-#endif //__MISS_QUEUE_HH__
diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc
index 74dad658b..5ba3d1ec5 100644
--- a/src/mem/cache/miss/mshr.cc
+++ b/src/mem/cache/miss/mshr.cc
@@ -37,6 +37,7 @@
#include <assert.h>
#include <string>
#include <vector>
+#include <algorithm>
#include "mem/cache/miss/mshr.hh"
#include "sim/core.hh" // for curTick
@@ -51,57 +52,126 @@ MSHR::MSHR()
inService = false;
ntargets = 0;
threadNum = -1;
+ targets = new TargetList();
+ deferredTargets = new TargetList();
}
+
+MSHR::TargetList::TargetList()
+ : needsExclusive(false), hasUpgrade(false)
+{}
+
+
+inline void
+MSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
+ Counter order, bool cpuSide)
+{
+ if (cpuSide) {
+ if (pkt->needsExclusive()) {
+ needsExclusive = true;
+ }
+
+ if (pkt->cmd == MemCmd::UpgradeReq) {
+ hasUpgrade = true;
+ }
+
+ MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
+ if (mshr != NULL) {
+ assert(!mshr->downstreamPending);
+ mshr->downstreamPending = true;
+ }
+ }
+
+ push_back(Target(pkt, readyTime, order, cpuSide));
+}
+
+
void
-MSHR::allocate(MemCmd cmd, Addr _addr, int size,
- PacketPtr &target)
+MSHR::TargetList::replaceUpgrades()
{
- addr = _addr;
- if (target)
- {
- //Have a request, just use it
- pkt = new Packet(target->req, cmd, Packet::Broadcast, size);
- pkt->time = curTick;
- pkt->allocate();
- pkt->senderState = (Packet::SenderState *)this;
- allocateTarget(target);
+ if (!hasUpgrade)
+ return;
+
+ Iterator end_i = end();
+ for (Iterator i = begin(); i != end_i; ++i) {
+ if (i->pkt->cmd == MemCmd::UpgradeReq) {
+ i->pkt->cmd = MemCmd::ReadExReq;
+ DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
+ }
}
- else
- {
- //need a request first
- Request * req = new Request();
- req->setPhys(addr, size, 0);
- //Thread context??
- pkt = new Packet(req, cmd, Packet::Broadcast, size);
- pkt->time = curTick;
- pkt->allocate();
- pkt->senderState = (Packet::SenderState *)this;
+
+ hasUpgrade = false;
+}
+
+
+void
+MSHR::TargetList::clearDownstreamPending()
+{
+ Iterator end_i = end();
+ for (Iterator i = begin(); i != end_i; ++i) {
+ MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState);
+ if (mshr != NULL) {
+ assert(mshr->downstreamPending);
+ mshr->downstreamPending = false;
+ }
}
}
-// Since we aren't sure if data is being used, don't copy here.
-/**
- * @todo When we have a "global" data flag, might want to copy data here.
- */
+
void
-MSHR::allocateAsBuffer(PacketPtr &target)
+MSHR::allocate(Addr _addr, int _size, PacketPtr target,
+ Tick whenReady, Counter _order)
{
- addr = target->getAddr();
- threadNum = 0/*target->req->getThreadNum()*/;
- pkt = new Packet(target->req, target->cmd, -1);
- pkt->allocate();
- pkt->senderState = (Packet::SenderState*)this;
- pkt->time = curTick;
+ addr = _addr;
+ size = _size;
+ readyTime = whenReady;
+ order = _order;
+ assert(target);
+ isCacheFill = false;
+ _isUncacheable = target->req->isUncacheable();
+ inService = false;
+ downstreamPending = false;
+ threadNum = 0;
+ ntargets = 1;
+ // Don't know of a case where we would allocate a new MSHR for a
+ // snoop (mem-side request), so set cpuSide to true here.
+ assert(targets->isReset());
+ targets->add(target, whenReady, _order, true);
+ assert(deferredTargets->isReset());
+ pendingInvalidate = false;
+ pendingShared = false;
+ data = NULL;
}
+
+bool
+MSHR::markInService()
+{
+ assert(!inService);
+ if (isSimpleForward()) {
+ // we just forwarded the request packet & don't expect a
+ // response, so get rid of it
+ assert(getNumTargets() == 1);
+ popTarget();
+ return true;
+ }
+ inService = true;
+ if (!downstreamPending) {
+ // let upstream caches know that the request has made it to a
+ // level where it's going to get a response
+ targets->clearDownstreamPending();
+ }
+ return false;
+}
+
+
void
MSHR::deallocate()
{
- assert(targets.empty());
+ assert(targets->empty());
+ targets->resetFlags();
+ assert(deferredTargets->isReset());
assert(ntargets == 0);
- delete pkt;
- pkt = NULL;
inService = false;
//allocIter = NULL;
//readyIter = NULL;
@@ -111,48 +181,143 @@ MSHR::deallocate()
* Adds a target to an MSHR
*/
void
-MSHR::allocateTarget(PacketPtr &target)
+MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
{
- //If we append an invalidate and we issued a read to the bus,
- //but now have some pending writes, we need to move
- //the invalidate to before the first non-read
- if (inService && pkt->isRead() && target->isInvalidate()) {
- std::list<PacketPtr> temp;
-
- while (!targets.empty()) {
- if (!targets.front()->isRead()) break;
- //Place on top of temp stack
- temp.push_front(targets.front());
- //Remove from targets
- targets.pop_front();
- }
+ // if there's a request already in service for this MSHR, we will
+ // have to defer the new target until after the response if any of
+ // the following are true:
+ // - there are other targets already deferred
+ // - there's a pending invalidate to be applied after the response
+ // comes back (but before this target is processed)
+ // - the outstanding request is for a non-exclusive block and this
+ // target requires an exclusive block
+ if (inService &&
+ (!deferredTargets->empty() || pendingInvalidate ||
+ (!targets->needsExclusive && pkt->needsExclusive()))) {
+ // need to put on deferred list
+ deferredTargets->add(pkt, whenReady, _order, true);
+ } else {
+ // no request outstanding, or still OK to append to
+ // outstanding request
+ targets->add(pkt, whenReady, _order, true);
+ }
- //Now that we have all the reads off until first non-read, we can
- //place the invalidate on
- targets.push_front(target);
+ ++ntargets;
+}
- //Now we pop off the temp_stack and put them back
- while (!temp.empty()) {
- targets.push_front(temp.front());
- temp.pop_front();
+bool
+MSHR::handleSnoop(PacketPtr pkt, Counter _order)
+{
+ if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
+ // Request has not been issued yet, or it's been issued
+ // locally but is buffered unissued at some downstream cache
+ // which is forwarding us this snoop. Either way, the packet
+ // we're snooping logically precedes this MSHR's request, so
+ // the snoop has no impact on the MSHR, but must be processed
+ // in the standard way by the cache. The only exception is
+ // that if we're an L2+ cache buffering an UpgradeReq from a
+ // higher-level cache, and the snoop is invalidating, then our
+ // buffered upgrades must be converted to read exclusives,
+ // since the upper-level cache no longer has a valid copy.
+ // That is, even though the upper-level cache got out on its
+ // local bus first, some other invalidating transaction
+ // reached the global bus before the upgrade did.
+ if (pkt->needsExclusive()) {
+ targets->replaceUpgrades();
+ deferredTargets->replaceUpgrades();
}
+
+ return false;
}
- else {
- targets.push_back(target);
+
+ // From here on down, the request issued by this MSHR logically
+ // precedes the request we're snooping.
+
+ if (pkt->needsExclusive()) {
+ // snooped request still precedes the re-request we'll have to
+ // issue for deferred targets, if any...
+ deferredTargets->replaceUpgrades();
}
- ++ntargets;
- assert(targets.size() == ntargets);
- /**
- * @todo really prioritize the target commands.
- */
+ if (pendingInvalidate) {
+ // a prior snoop has already appended an invalidation, so
+ // logically we don't have the block anymore; no need for
+ // further snooping.
+ return true;
+ }
+
+ if (targets->needsExclusive || pkt->needsExclusive()) {
+ // actual target device (typ. PhysicalMemory) will delete the
+ // packet on reception, so we need to save a copy here
+ PacketPtr cp_pkt = new Packet(pkt);
+ targets->add(cp_pkt, curTick, _order, false);
+ ++ntargets;
- if (!inService && target->isWrite()) {
- pkt->cmd = MemCmd::WriteReq;
+ if (targets->needsExclusive) {
+ // We're awaiting an exclusive copy, so ownership is pending.
+ // It's up to us to respond once the data arrives.
+ pkt->assertMemInhibit();
+ pkt->setSupplyExclusive();
+ } else {
+ // Someone else may respond before we get around to
+ // processing this snoop, which means the copied request
+ // pointer will no longer be valid
+ cp_pkt->req = NULL;
+ }
+
+ if (pkt->needsExclusive()) {
+ // This transaction will take away our pending copy
+ pendingInvalidate = true;
+ }
+ } else {
+ // Read to a read: no conflict, so no need to record as
+ // target, but make sure neither reader thinks he's getting an
+ // exclusive copy
+ pendingShared = true;
+ pkt->assertShared();
}
+
+ return true;
}
+bool
+MSHR::promoteDeferredTargets()
+{
+ assert(targets->empty());
+ if (deferredTargets->empty()) {
+ return false;
+ }
+
+ // swap targets & deferredTargets lists
+ TargetList *tmp = targets;
+ targets = deferredTargets;
+ deferredTargets = tmp;
+
+ assert(targets->size() == ntargets);
+
+ // clear deferredTargets flags
+ deferredTargets->resetFlags();
+
+ pendingInvalidate = false;
+ pendingShared = false;
+ order = targets->front().order;
+ readyTime = std::max(curTick, targets->front().readyTime);
+
+ return true;
+}
+
+
+void
+MSHR::handleFill(Packet *pkt, CacheBlk *blk)
+{
+ if (pendingShared) {
+ // we snooped another read while this read was in
+ // service... assert shared line on its behalf
+ pkt->assertShared();
+ }
+}
+
void
MSHR::dump()
@@ -162,21 +327,20 @@ MSHR::dump()
"Addr: %x ntargets %d\n"
"Targets:\n",
inService, threadNum, addr, ntargets);
-
- TargetListIterator tar_it = targets.begin();
+#if 0
+ TargetListIterator tar_it = targets->begin();
for (int i = 0; i < ntargets; i++) {
- assert(tar_it != targets.end());
+ assert(tar_it != targets->end());
- ccprintf(cerr, "\t%d: Addr: %x cmd: %d\n",
- i, (*tar_it)->getAddr(), (*tar_it)->cmdToIndex());
+ ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n",
+ i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString());
tar_it++;
}
+#endif
ccprintf(cerr, "\n");
}
MSHR::~MSHR()
{
- if (pkt)
- pkt = NULL;
}
diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh
index d0410acda..e850a8633 100644
--- a/src/mem/cache/miss/mshr.hh
+++ b/src/mem/cache/miss/mshr.hh
@@ -36,22 +36,54 @@
#ifndef __MSHR_HH__
#define __MSHR_HH__
-#include "mem/packet.hh"
#include <list>
-#include <deque>
-class MSHR;
+#include "mem/packet.hh"
+
+class CacheBlk;
+class MSHRQueue;
/**
* Miss Status and handling Register. This class keeps all the information
* needed to handle a cache miss including a list of target requests.
*/
-class MSHR {
+class MSHR : public Packet::SenderState
+{
+
public:
- /** Defines the Data structure of the MSHR targetlist. */
- typedef std::list<PacketPtr> TargetList;
- /** Target list iterator. */
- typedef std::list<PacketPtr>::iterator TargetListIterator;
+
+ class Target {
+ public:
+ 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?
+
+ bool isCpuSide() { return cpuSide; }
+
+ Target(PacketPtr _pkt, Tick _readyTime, Counter _order, bool _cpuSide)
+ : recvTime(curTick), readyTime(_readyTime), order(_order),
+ pkt(_pkt), cpuSide(_cpuSide)
+ {}
+ };
+
+ class TargetList : public std::list<Target> {
+ /** Target list iterator. */
+ typedef std::list<Target>::iterator Iterator;
+
+ public:
+ bool needsExclusive;
+ bool hasUpgrade;
+
+ TargetList();
+ void resetFlags() { needsExclusive = hasUpgrade = false; }
+ bool isReset() { return !needsExclusive && !hasUpgrade; }
+ void add(PacketPtr pkt, Tick readyTime, Counter order, bool cpuSide);
+ void replaceUpgrades();
+ void clearDownstreamPending();
+ };
+
/** A list of MSHRs. */
typedef std::list<MSHR *> List;
/** MSHR list iterator. */
@@ -59,28 +91,54 @@ class MSHR {
/** MSHR list const_iterator. */
typedef List::const_iterator ConstIterator;
- /** Address of the miss. */
+ /** Pointer to queue containing this MSHR. */
+ MSHRQueue *queue;
+
+ /** Cycle when ready to issue */
+ Tick readyTime;
+
+ /** Order number assigned by the miss queue. */
+ Counter order;
+
+ /** Address of the request. */
Addr addr;
- /** Adress space id of the miss. */
- short asid;
+
+ /** Size of the request. */
+ int size;
+
/** 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 we need to get an exclusive copy of the block. */
+ bool needsExclusive() { return targets->needsExclusive; }
+
+ /** True if the request is uncacheable */
+ bool _isUncacheable;
+
+ bool downstreamPending;
+
+ bool pendingInvalidate;
+ bool pendingShared;
+
/** Thread number of the miss. */
- int threadNum;
- /** The request that is forwarded to the next level of the hierarchy. */
- PacketPtr pkt;
+ short threadNum;
/** The number of currently allocated targets. */
short ntargets;
- /** The original requesting command. */
- MemCmd originalCmd;
- /** Order number of assigned by the miss queue. */
- uint64_t order;
+
+
+ /** Data buffer (if needed). Currently used only for pending
+ * upgrade handling. */
+ uint8_t *data;
/**
* Pointer to this MSHR on the ready list.
* @sa MissQueue, MSHRQueue::readyList
*/
Iterator readyIter;
+
/**
* Pointer to this MSHR on the allocated list.
* @sa MissQueue, MSHRQueue::allocatedList
@@ -89,9 +147,14 @@ class MSHR {
private:
/** List of all requests that match the address */
- TargetList targets;
+ TargetList *targets;
+
+ TargetList *deferredTargets;
public:
+
+ bool isUncacheable() { return _isUncacheable; }
+
/**
* Allocate a miss to this MSHR.
* @param cmd The requesting command.
@@ -100,14 +163,10 @@ public:
* @param size The number of bytes to request.
* @param pkt The original miss.
*/
- void allocate(MemCmd cmd, Addr addr, int size,
- PacketPtr &pkt);
+ void allocate(Addr addr, int size, PacketPtr pkt,
+ Tick when, Counter _order);
- /**
- * Allocate this MSHR as a buffer for the given request.
- * @param target The memory request to buffer.
- */
- void allocateAsBuffer(PacketPtr &target);
+ bool markInService();
/**
* Mark this MSHR as free.
@@ -118,7 +177,8 @@ public:
* Add a request to the list of targets.
* @param target The target.
*/
- void allocateTarget(PacketPtr &target);
+ void allocateTarget(PacketPtr target, Tick when, Counter order);
+ bool handleSnoop(PacketPtr target, Counter order);
/** A simple constructor. */
MSHR();
@@ -129,28 +189,25 @@ public:
* Returns the current number of allocated targets.
* @return The current number of allocated targets.
*/
- int getNumTargets()
- {
- return(ntargets);
- }
+ int getNumTargets() { return ntargets; }
/**
* Returns a pointer to the target list.
* @return a pointer to the target list.
*/
- TargetList* getTargetList()
- {
- return &targets;
- }
+ TargetList *getTargetList() { return targets; }
+
+ /**
+ * Returns true if there are targets left.
+ * @return true if there are targets
+ */
+ bool hasTargets() { return !targets->empty(); }
/**
* Returns a reference to the first target.
* @return A pointer to the first target.
*/
- PacketPtr getTarget()
- {
- return targets.front();
- }
+ Target *getTarget() { assert(hasTargets()); return &targets->front(); }
/**
* Pop first target.
@@ -158,18 +215,21 @@ public:
void popTarget()
{
--ntargets;
- targets.pop_front();
+ targets->pop_front();
}
- /**
- * Returns true if there are targets left.
- * @return true if there are targets
- */
- bool hasTargets()
+ bool isSimpleForward()
{
- return !targets.empty();
+ if (getNumTargets() != 1)
+ return false;
+ Target *tgt = getTarget();
+ return tgt->isCpuSide() && !tgt->pkt->needsResponse();
}
+ bool promoteDeferredTargets();
+
+ void handleFill(Packet *pkt, CacheBlk *blk);
+
/**
* Prints the contents of this MSHR to stderr.
*/
diff --git a/src/mem/cache/miss/mshr_queue.cc b/src/mem/cache/miss/mshr_queue.cc
index add11dfe7..50a28fb3c 100644
--- a/src/mem/cache/miss/mshr_queue.cc
+++ b/src/mem/cache/miss/mshr_queue.cc
@@ -29,22 +29,22 @@
*/
/** @file
- * Definition of the MSHRQueue.
+ * Definition of MSHRQueue class functions.
*/
#include "mem/cache/miss/mshr_queue.hh"
-#include "sim/eventq.hh"
using namespace std;
-MSHRQueue::MSHRQueue(int num_mshrs, int reserve)
- : numMSHRs(num_mshrs + reserve - 1), numReserve(reserve)
+MSHRQueue::MSHRQueue(int num_entries, int reserve, int _index)
+ : numEntries(num_entries + reserve - 1), numReserve(reserve),
+ index(_index)
{
allocated = 0;
- inServiceMSHRs = 0;
- allocatedTargets = 0;
- registers = new MSHR[numMSHRs];
- for (int i = 0; i < numMSHRs; ++i) {
+ inServiceEntries = 0;
+ registers = new MSHR[numEntries];
+ for (int i = 0; i < numEntries; ++i) {
+ registers[i].queue = this;
freeList.push_back(&registers[i]);
}
}
@@ -54,7 +54,7 @@ MSHRQueue::~MSHRQueue()
delete [] registers;
}
-MSHR*
+MSHR *
MSHRQueue::findMatch(Addr addr) const
{
MSHR::ConstIterator i = allocatedList.begin();
@@ -87,19 +87,19 @@ MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
}
-MSHR*
-MSHRQueue::findPending(PacketPtr &pkt) const
+MSHR *
+MSHRQueue::findPending(Addr addr, int size) const
{
- MSHR::ConstIterator i = pendingList.begin();
- MSHR::ConstIterator end = pendingList.end();
+ MSHR::ConstIterator i = readyList.begin();
+ MSHR::ConstIterator end = readyList.end();
for (; i != end; ++i) {
MSHR *mshr = *i;
- if (mshr->addr < pkt->getAddr()) {
- if (mshr->addr + mshr->pkt->getSize() > pkt->getAddr()) {
+ if (mshr->addr < addr) {
+ if (mshr->addr + mshr->size > addr) {
return mshr;
}
} else {
- if (pkt->getAddr() + pkt->getSize() > mshr->addr) {
+ if (addr + size > mshr->addr) {
return mshr;
}
}
@@ -107,76 +107,60 @@ MSHRQueue::findPending(PacketPtr &pkt) const
return NULL;
}
-MSHR*
-MSHRQueue::allocate(PacketPtr &pkt, int size)
-{
- Addr aligned_addr = pkt->getAddr() & ~((Addr)size - 1);
- assert(!freeList.empty());
- MSHR *mshr = freeList.front();
- assert(mshr->getNumTargets() == 0);
- freeList.pop_front();
- if (!pkt->needsResponse()) {
- mshr->allocateAsBuffer(pkt);
- } else {
- assert(size !=0);
- mshr->allocate(pkt->cmd, aligned_addr, size, pkt);
- allocatedTargets += 1;
+MSHR::Iterator
+MSHRQueue::addToReadyList(MSHR *mshr)
+{
+ if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
+ return readyList.insert(readyList.end(), mshr);
}
- mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
- mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
- allocated += 1;
- return mshr;
+ MSHR::Iterator i = readyList.begin();
+ MSHR::Iterator end = readyList.end();
+ for (; i != end; ++i) {
+ if ((*i)->readyTime > mshr->readyTime) {
+ return readyList.insert(i, mshr);
+ }
+ }
+ assert(false);
+ return end; // keep stupid compilers happy
}
-MSHR*
-MSHRQueue::allocateFetch(Addr addr, int size, PacketPtr &target)
+
+MSHR *
+MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt,
+ Tick when, Counter order)
{
+ assert(!freeList.empty());
MSHR *mshr = freeList.front();
assert(mshr->getNumTargets() == 0);
freeList.pop_front();
- mshr->allocate(MemCmd::ReadReq, addr, size, target);
+
+ mshr->allocate(addr, size, pkt, when, order);
mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
- mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
+ mshr->readyIter = addToReadyList(mshr);
allocated += 1;
return mshr;
}
-MSHR*
-MSHRQueue::allocateTargetList(Addr addr, int size)
-{
- MSHR *mshr = freeList.front();
- assert(mshr->getNumTargets() == 0);
- freeList.pop_front();
- PacketPtr dummy;
- mshr->allocate(MemCmd::ReadReq, addr, size, dummy);
- mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
- mshr->inService = true;
- ++inServiceMSHRs;
- ++allocated;
- return mshr;
-}
-
void
-MSHRQueue::deallocate(MSHR* mshr)
+MSHRQueue::deallocate(MSHR *mshr)
{
deallocateOne(mshr);
}
MSHR::Iterator
-MSHRQueue::deallocateOne(MSHR* mshr)
+MSHRQueue::deallocateOne(MSHR *mshr)
{
MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
freeList.push_front(mshr);
allocated--;
- allocatedTargets -= mshr->getNumTargets();
if (mshr->inService) {
- inServiceMSHRs--;
+ inServiceEntries--;
} else {
- pendingList.erase(mshr->readyIter);
+ readyList.erase(mshr->readyIter);
}
mshr->deallocate();
return retval;
@@ -187,40 +171,33 @@ MSHRQueue::moveToFront(MSHR *mshr)
{
if (!mshr->inService) {
assert(mshr == *(mshr->readyIter));
- pendingList.erase(mshr->readyIter);
- mshr->readyIter = pendingList.insert(pendingList.begin(), mshr);
+ readyList.erase(mshr->readyIter);
+ mshr->readyIter = readyList.insert(readyList.begin(), mshr);
}
}
void
-MSHRQueue::markInService(MSHR* mshr)
+MSHRQueue::markInService(MSHR *mshr)
{
- //assert(mshr == pendingList.front());
- if (!mshr->pkt->needsResponse() && !(mshr->pkt->cmd == MemCmd::UpgradeReq)) {
- assert(mshr->getNumTargets() == 0);
+ if (mshr->markInService()) {
deallocate(mshr);
- return;
+ } else {
+ readyList.erase(mshr->readyIter);
+ inServiceEntries += 1;
}
- mshr->inService = true;
- pendingList.erase(mshr->readyIter);
- //mshr->readyIter = NULL;
- inServiceMSHRs += 1;
- //pendingList.pop_front();
}
void
-MSHRQueue::markPending(MSHR* mshr, MemCmd cmd)
+MSHRQueue::markPending(MSHR *mshr)
{
- //assert(mshr->readyIter == NULL);
- mshr->pkt->cmd = cmd;
- mshr->pkt->flags &= ~SATISFIED;
+ assert(mshr->inService);
mshr->inService = false;
- --inServiceMSHRs;
+ --inServiceEntries;
/**
* @ todo might want to add rerequests to front of pending list for
* performance.
*/
- mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
+ mshr->readyIter = addToReadyList(mshr);
}
void
@@ -232,11 +209,8 @@ MSHRQueue::squash(int threadNum)
MSHR *mshr = *i;
if (mshr->threadNum == threadNum) {
while (mshr->hasTargets()) {
- PacketPtr target = mshr->getTarget();
mshr->popTarget();
-
assert(0/*target->req->getThreadNum()*/ == threadNum);
- target = NULL;
}
assert(!mshr->hasTargets());
assert(mshr->ntargets==0);
diff --git a/src/mem/cache/miss/mshr_queue.hh b/src/mem/cache/miss/mshr_queue.hh
index 5069db661..1f1d59e98 100644
--- a/src/mem/cache/miss/mshr_queue.hh
+++ b/src/mem/cache/miss/mshr_queue.hh
@@ -32,71 +32,77 @@
* Declaration of a structure to manage MSHRs.
*/
-#ifndef __MSHR_QUEUE_HH__
-#define __MSHR_QUEUE_HH__
+#ifndef __MEM__CACHE__MISS__MSHR_QUEUE_HH__
+#define __MEM__CACHE__MISS__MSHR_QUEUE_HH__
#include <vector>
+
+#include "mem/packet.hh"
#include "mem/cache/miss/mshr.hh"
/**
* A Class for maintaining a list of pending and allocated memory requests.
*/
-class MSHRQueue {
+class MSHRQueue
+{
private:
/** MSHR storage. */
- MSHR* registers;
- /** Holds pointers to all allocated MSHRs. */
+ MSHR *registers;
+ /** Holds pointers to all allocated entries. */
MSHR::List allocatedList;
- /** Holds pointers to MSHRs that haven't been sent to the bus. */
- MSHR::List pendingList;
- /** Holds non allocated MSHRs. */
+ /** Holds pointers to entries that haven't been sent to the bus. */
+ MSHR::List readyList;
+ /** Holds non allocated entries. */
MSHR::List freeList;
// Parameters
/**
- * The total number of MSHRs in this queue. This number is set as the
- * number of MSHRs requested plus (numReserve - 1). This allows for
- * the same number of effective MSHRs while still maintaining the reserve.
+ * The total number of entries in this queue. This number is set as the
+ * number of entries requested plus (numReserve - 1). This allows for
+ * the same number of effective entries while still maintaining the reserve.
*/
- const int numMSHRs;
+ const int numEntries;
/**
- * The number of MSHRs to hold in reserve. This is needed because copy
- * operations can allocate upto 4 MSHRs at one time.
+ * The number of entries to hold in reserve. This is needed because copy
+ * operations can allocate upto 4 entries at one time.
*/
const int numReserve;
+ MSHR::Iterator addToReadyList(MSHR *mshr);
+
+
public:
- /** The number of allocated MSHRs. */
+ /** The number of allocated entries. */
int allocated;
- /** The number of MSHRs that have been forwarded to the bus. */
- int inServiceMSHRs;
- /** The number of targets waiting for response. */
- int allocatedTargets;
+ /** The number of entries that have been forwarded to the bus. */
+ int inServiceEntries;
+ /** The index of this queue within the cache (MSHR queue vs. write
+ * buffer). */
+ const int index;
/**
- * Create a queue with a given number of MSHRs.
- * @param num_mshrs The number of MSHRs in this queue.
- * @param reserve The minimum number of MSHRs needed to satisfy any access.
+ * Create a queue with a given number of entries.
+ * @param num_entrys The number of entries in this queue.
+ * @param reserve The minimum number of entries needed to satisfy
+ * any access.
*/
- MSHRQueue(int num_mshrs, int reserve = 1);
+ MSHRQueue(int num_entries, int reserve, int index);
/** Destructor */
~MSHRQueue();
/**
- * Find the first MSHR that matches the provide address and asid.
+ * Find the first MSHR that matches the provided address.
* @param addr The address to find.
- * @param asid The address space id.
* @return Pointer to the matching MSHR, null if not found.
*/
- MSHR* findMatch(Addr addr) const;
+ MSHR *findMatch(Addr addr) const;
/**
- * Find and return all the matching MSHRs in the provided vector.
+ * Find and return all the matching entries in the provided vector.
* @param addr The address to find.
- * @param asid The address space ID.
- * @param matches The vector to return pointers to the matching MSHRs.
+ * @param matches The vector to return pointers to the matching entries.
* @return True if any matches are found, false otherwise.
* @todo Typedef the vector??
*/
@@ -107,7 +113,7 @@ class MSHRQueue {
* @param pkt The request to find.
* @return A pointer to the earliest matching MSHR.
*/
- MSHR* findPending(PacketPtr &pkt) const;
+ MSHR *findPending(Addr addr, int size) const;
/**
* Allocates a new MSHR for the request and size. This places the request
@@ -116,76 +122,45 @@ class MSHRQueue {
* @param size The number in bytes to fetch from memory.
* @return The a pointer to the MSHR allocated.
*
- * @pre There are free MSHRs.
- */
- MSHR* allocate(PacketPtr &pkt, int size = 0);
-
- /**
- * Allocate a read request for the given address, and places the given
- * target on the target list.
- * @param addr The address to fetch.
- * @param asid The address space for the fetch.
- * @param size The number of bytes to request.
- * @param target The first target for the request.
- * @return Pointer to the new MSHR.
- */
- MSHR* allocateFetch(Addr addr, int size, PacketPtr &target);
-
- /**
- * Allocate a target list for the given address.
- * @param addr The address to fetch.
- * @param asid The address space for the fetch.
- * @param size The number of bytes to request.
- * @return Pointer to the new MSHR.
+ * @pre There are free entries.
*/
- MSHR* allocateTargetList(Addr addr, int size);
+ MSHR *allocate(Addr addr, int size, PacketPtr &pkt,
+ Tick when, Counter order);
/**
* Removes the given MSHR from the queue. This places the MSHR on the
* free list.
* @param mshr
*/
- void deallocate(MSHR* mshr);
+ void deallocate(MSHR *mshr);
/**
- * Allocates a target to the given MSHR. Used to keep track of the number
- * of outstanding targets.
- * @param mshr The MSHR to allocate the target to.
- * @param pkt The target request.
- */
- void allocateTarget(MSHR* mshr, PacketPtr &pkt)
- {
- mshr->allocateTarget(pkt);
- allocatedTargets += 1;
- }
-
- /**
- * Remove a MSHR from the queue. Returns an iterator into the allocatedList
- * for faster squash implementation.
+ * Remove a MSHR from the queue. Returns an iterator into the
+ * allocatedList for faster squash implementation.
* @param mshr The MSHR to remove.
* @return An iterator to the next entry in the allocatedList.
*/
- MSHR::Iterator deallocateOne(MSHR* mshr);
+ MSHR::Iterator deallocateOne(MSHR *mshr);
/**
- * Moves the MSHR to the front of the pending list if it is not in service.
- * @param mshr The mshr to move.
+ * Moves the MSHR to the front of the pending list if it is not
+ * in service.
+ * @param mshr The entry to move.
*/
void moveToFront(MSHR *mshr);
/**
* Mark the given MSHR as in service. This removes the MSHR from the
- * pendingList. Deallocates the MSHR if it does not expect a response.
+ * readyList. Deallocates the MSHR if it does not expect a response.
* @param mshr The MSHR to mark in service.
*/
- void markInService(MSHR* mshr);
+ void markInService(MSHR *mshr);
/**
- * Mark an in service mshr as pending, used to resend a request.
+ * Mark an in service entry as pending, used to resend a request.
* @param mshr The MSHR to resend.
- * @param cmd The command to resend.
*/
- void markPending(MSHR* mshr, MemCmd cmd);
+ void markPending(MSHR *mshr);
/**
* Squash outstanding requests with the given thread number. If a request
@@ -200,40 +175,34 @@ class MSHRQueue {
*/
bool havePending() const
{
- return !pendingList.empty();
+ return !readyList.empty();
}
/**
- * Returns true if there are no free MSHRs.
+ * Returns true if there are no free entries.
* @return True if this queue is full.
*/
bool isFull() const
{
- return (allocated > numMSHRs - numReserve);
+ return (allocated > numEntries - numReserve);
}
/**
- * Returns the request at the head of the pendingList.
+ * Returns the MSHR at the head of the readyList.
* @return The next request to service.
*/
- PacketPtr getReq() const
+ MSHR *getNextMSHR() const
{
- if (pendingList.empty()) {
+ if (readyList.empty() || readyList.front()->readyTime > curTick) {
return NULL;
}
- MSHR* mshr = pendingList.front();
- return mshr->pkt;
+ return readyList.front();
}
- /**
- * Returns the number of outstanding targets.
- * @return the number of allocated targets.
- */
- int getAllocatedTargets() const
+ Tick nextMSHRReadyTime() const
{
- return allocatedTargets;
+ return readyList.empty() ? MaxTick : readyList.front()->readyTime;
}
-
};
-#endif //__MSHR_QUEUE_HH__
+#endif //__MEM__CACHE__MISS__MSHR_QUEUE_HH__