2 * Copyright (c) 2012-2013, 2015 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 * Authors: Erik Hallnor
45 * Definition of MSHRQueue class functions.
48 #include "base/trace.hh"
49 #include "mem/cache/mshr_queue.hh"
50 #include "debug/Drain.hh"
54 MSHRQueue::MSHRQueue(const std::string
&_label
,
55 int num_entries
, int reserve
, int demand_reserve
,
57 : label(_label
), numEntries(num_entries
+ reserve
- 1),
58 numReserve(reserve
), demandReserve(demand_reserve
),
59 registers(numEntries
), allocated(0),
60 inServiceEntries(0), index(_index
)
62 for (int i
= 0; i
< numEntries
; ++i
) {
63 registers
[i
].queue
= this;
64 freeList
.push_back(®isters
[i
]);
69 MSHRQueue::findMatch(Addr blk_addr
, bool is_secure
) const
71 for (const auto& mshr
: allocatedList
) {
72 // we ignore any MSHRs allocated for uncacheable accesses and
73 // simply ignore them when matching, in the cache we never
74 // check for matches when adding new uncacheable entries, and
75 // we do not want normal cacheable accesses being added to an
76 // MSHR serving an uncacheable access
77 if (!mshr
->isUncacheable() && mshr
->blkAddr
== blk_addr
&&
78 mshr
->isSecure
== is_secure
) {
86 MSHRQueue::findMatches(Addr blk_addr
, bool is_secure
,
87 vector
<MSHR
*>& matches
) const
89 // Need an empty vector
90 assert(matches
.empty());
92 for (const auto& mshr
: allocatedList
) {
93 if (!mshr
->isUncacheable() && mshr
->blkAddr
== blk_addr
&&
94 mshr
->isSecure
== is_secure
) {
96 matches
.push_back(mshr
);
104 MSHRQueue::checkFunctional(PacketPtr pkt
, Addr blk_addr
)
106 pkt
->pushLabel(label
);
107 for (const auto& mshr
: allocatedList
) {
108 if (mshr
->blkAddr
== blk_addr
&& mshr
->checkFunctional(pkt
)) {
119 MSHRQueue::findPending(Addr blk_addr
, bool is_secure
) const
121 for (const auto& mshr
: readyList
) {
122 if (mshr
->blkAddr
== blk_addr
&& mshr
->isSecure
== is_secure
) {
131 MSHRQueue::addToReadyList(MSHR
*mshr
)
133 if (readyList
.empty() || readyList
.back()->readyTime
<= mshr
->readyTime
) {
134 return readyList
.insert(readyList
.end(), mshr
);
137 for (auto i
= readyList
.begin(); i
!= readyList
.end(); ++i
) {
138 if ((*i
)->readyTime
> mshr
->readyTime
) {
139 return readyList
.insert(i
, mshr
);
143 return readyList
.end(); // keep stupid compilers happy
148 MSHRQueue::allocate(Addr blk_addr
, unsigned blk_size
, PacketPtr pkt
,
149 Tick when_ready
, Counter order
, bool alloc_on_fill
)
151 assert(!freeList
.empty());
152 MSHR
*mshr
= freeList
.front();
153 assert(mshr
->getNumTargets() == 0);
154 freeList
.pop_front();
156 mshr
->allocate(blk_addr
, blk_size
, pkt
, when_ready
, order
, alloc_on_fill
);
157 mshr
->allocIter
= allocatedList
.insert(allocatedList
.end(), mshr
);
158 mshr
->readyIter
= addToReadyList(mshr
);
166 MSHRQueue::deallocate(MSHR
*mshr
)
172 MSHRQueue::deallocateOne(MSHR
*mshr
)
174 MSHR::Iterator retval
= allocatedList
.erase(mshr
->allocIter
);
175 freeList
.push_front(mshr
);
177 if (mshr
->inService
) {
180 readyList
.erase(mshr
->readyIter
);
183 if (drainState() == DrainState::Draining
&& allocated
== 0) {
184 // Notify the drain manager that we have completed draining if
185 // there are no other outstanding requests in this MSHR queue.
186 DPRINTF(Drain
, "MSHRQueue now empty, signalling drained\n");
193 MSHRQueue::moveToFront(MSHR
*mshr
)
195 if (!mshr
->inService
) {
196 assert(mshr
== *(mshr
->readyIter
));
197 readyList
.erase(mshr
->readyIter
);
198 mshr
->readyIter
= readyList
.insert(readyList
.begin(), mshr
);
203 MSHRQueue::markInService(MSHR
*mshr
, bool pending_dirty_resp
)
205 if (mshr
->markInService(pending_dirty_resp
)) {
208 readyList
.erase(mshr
->readyIter
);
209 inServiceEntries
+= 1;
214 MSHRQueue::markPending(MSHR
*mshr
)
216 assert(mshr
->inService
);
217 mshr
->inService
= false;
220 * @ todo might want to add rerequests to front of pending list for
223 mshr
->readyIter
= addToReadyList(mshr
);
227 MSHRQueue::forceDeallocateTarget(MSHR
*mshr
)
229 bool was_full
= isFull();
230 assert(mshr
->hasTargets());
231 // Pop the prefetch off of the target list
233 // Delete mshr if no remaining targets
234 if (!mshr
->hasTargets() && !mshr
->promoteDeferredTargets()) {
238 // Notify if MSHR queue no longer full
239 return was_full
&& !isFull();
243 MSHRQueue::squash(int threadNum
)
245 for (auto i
= allocatedList
.begin(); i
!= allocatedList
.end();) {
247 if (mshr
->threadNum
== threadNum
) {
248 while (mshr
->hasTargets()) {
250 assert(0/*target->req->threadId()*/ == threadNum
);
252 assert(!mshr
->hasTargets());
253 assert(mshr
->getNumTargets()==0);
254 if (!mshr
->inService
) {
255 i
= deallocateOne(mshr
);
257 //mshr->pkt->flags &= ~CACHE_LINE_FILL;
269 return allocated
== 0 ? DrainState::Drained
: DrainState::Draining
;