2 * Copyright (c) 2012-2013 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 "mem/cache/mshr_queue.hh"
52 MSHRQueue::MSHRQueue(const std::string
&_label
,
53 int num_entries
, int reserve
, int _index
)
54 : label(_label
), numEntries(num_entries
+ reserve
- 1),
55 numReserve(reserve
), registers(numEntries
),
56 drainManager(NULL
), allocated(0), inServiceEntries(0), index(_index
)
58 for (int i
= 0; i
< numEntries
; ++i
) {
59 registers
[i
].queue
= this;
60 freeList
.push_back(®isters
[i
]);
65 MSHRQueue::findMatch(Addr addr
, bool is_secure
) const
67 MSHR::ConstIterator i
= allocatedList
.begin();
68 MSHR::ConstIterator end
= allocatedList
.end();
69 for (; i
!= end
; ++i
) {
71 if (mshr
->addr
== addr
&& mshr
->isSecure
== is_secure
) {
79 MSHRQueue::findMatches(Addr addr
, bool is_secure
, vector
<MSHR
*>& matches
) const
81 // Need an empty vector
82 assert(matches
.empty());
84 MSHR::ConstIterator i
= allocatedList
.begin();
85 MSHR::ConstIterator end
= allocatedList
.end();
86 for (; i
!= end
; ++i
) {
88 if (mshr
->addr
== addr
&& mshr
->isSecure
== is_secure
) {
90 matches
.push_back(mshr
);
98 MSHRQueue::checkFunctional(PacketPtr pkt
, Addr blk_addr
)
100 pkt
->pushLabel(label
);
101 MSHR::ConstIterator i
= allocatedList
.begin();
102 MSHR::ConstIterator end
= allocatedList
.end();
103 for (; i
!= end
; ++i
) {
105 if (mshr
->addr
== blk_addr
&& mshr
->checkFunctional(pkt
)) {
116 MSHRQueue::findPending(Addr addr
, int size
, bool is_secure
) const
118 MSHR::ConstIterator i
= readyList
.begin();
119 MSHR::ConstIterator end
= readyList
.end();
120 for (; i
!= end
; ++i
) {
122 if (mshr
->isSecure
== is_secure
) {
123 if (mshr
->addr
< addr
) {
124 if (mshr
->addr
+ mshr
->size
> addr
)
127 if (addr
+ size
> mshr
->addr
)
137 MSHRQueue::addToReadyList(MSHR
*mshr
)
139 if (readyList
.empty() || readyList
.back()->readyTime
<= mshr
->readyTime
) {
140 return readyList
.insert(readyList
.end(), mshr
);
143 MSHR::Iterator i
= readyList
.begin();
144 MSHR::Iterator end
= readyList
.end();
145 for (; i
!= end
; ++i
) {
146 if ((*i
)->readyTime
> mshr
->readyTime
) {
147 return readyList
.insert(i
, mshr
);
151 return end
; // keep stupid compilers happy
156 MSHRQueue::allocate(Addr addr
, int size
, PacketPtr
&pkt
,
157 Tick when
, Counter order
)
159 assert(!freeList
.empty());
160 MSHR
*mshr
= freeList
.front();
161 assert(mshr
->getNumTargets() == 0);
162 freeList
.pop_front();
164 mshr
->allocate(addr
, size
, pkt
, when
, order
);
165 mshr
->allocIter
= allocatedList
.insert(allocatedList
.end(), mshr
);
166 mshr
->readyIter
= addToReadyList(mshr
);
174 MSHRQueue::deallocate(MSHR
*mshr
)
180 MSHRQueue::deallocateOne(MSHR
*mshr
)
182 MSHR::Iterator retval
= allocatedList
.erase(mshr
->allocIter
);
183 freeList
.push_front(mshr
);
185 if (mshr
->inService
) {
188 readyList
.erase(mshr
->readyIter
);
191 if (drainManager
&& allocated
== 0) {
192 // Notify the drain manager that we have completed draining if
193 // there are no other outstanding requests in this MSHR queue.
194 drainManager
->signalDrainDone();
196 setDrainState(Drainable::Drained
);
202 MSHRQueue::moveToFront(MSHR
*mshr
)
204 if (!mshr
->inService
) {
205 assert(mshr
== *(mshr
->readyIter
));
206 readyList
.erase(mshr
->readyIter
);
207 mshr
->readyIter
= readyList
.insert(readyList
.begin(), mshr
);
212 MSHRQueue::markInService(MSHR
*mshr
, PacketPtr pkt
)
214 if (mshr
->markInService(pkt
)) {
217 readyList
.erase(mshr
->readyIter
);
218 inServiceEntries
+= 1;
223 MSHRQueue::markPending(MSHR
*mshr
)
225 assert(mshr
->inService
);
226 mshr
->inService
= false;
229 * @ todo might want to add rerequests to front of pending list for
232 mshr
->readyIter
= addToReadyList(mshr
);
236 MSHRQueue::forceDeallocateTarget(MSHR
*mshr
)
238 bool was_full
= isFull();
239 assert(mshr
->hasTargets());
240 // Pop the prefetch off of the target list
242 // Delete mshr if no remaining targets
243 if (!mshr
->hasTargets() && !mshr
->promoteDeferredTargets()) {
247 // Notify if MSHR queue no longer full
248 return was_full
&& !isFull();
252 MSHRQueue::squash(int threadNum
)
254 MSHR::Iterator i
= allocatedList
.begin();
255 MSHR::Iterator end
= allocatedList
.end();
258 if (mshr
->threadNum
== threadNum
) {
259 while (mshr
->hasTargets()) {
261 assert(0/*target->req->threadId()*/ == threadNum
);
263 assert(!mshr
->hasTargets());
264 assert(mshr
->getNumTargets()==0);
265 if (!mshr
->inService
) {
266 i
= deallocateOne(mshr
);
268 //mshr->pkt->flags &= ~CACHE_LINE_FILL;
278 MSHRQueue::drain(DrainManager
*dm
)
280 if (allocated
== 0) {
281 setDrainState(Drainable::Drained
);
285 setDrainState(Drainable::Draining
);