Deleted Added
sdiff udiff text old ( 10766:b2071d0eb5f1 ) new ( 10768:9a34e28cd2c2 )
full compact
1/*
2 * Copyright (c) 2012-2013, 2015 ARM Limited
3 * All rights reserved.
4 *
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.
13 *
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
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.
27 *
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.
39 *
40 * Authors: Erik Hallnor
41 * Andreas Sandberg
42 */
43
44/** @file
45 * Definition of MSHRQueue class functions.
46 */
47
48#include "base/trace.hh"
49#include "mem/cache/mshr_queue.hh"
50#include "debug/Drain.hh"
51
52using namespace std;
53
54MSHRQueue::MSHRQueue(const std::string &_label,
55 int num_entries, int reserve, int demand_reserve,
56 int _index)
57 : label(_label), numEntries(num_entries + reserve - 1),
58 numReserve(reserve), demandReserve(demand_reserve),
59 registers(numEntries), drainManager(NULL), allocated(0),
60 inServiceEntries(0), index(_index)
61{
62 for (int i = 0; i < numEntries; ++i) {
63 registers[i].queue = this;
64 freeList.push_back(&registers[i]);
65 }
66}
67
68MSHR *
69MSHRQueue::findMatch(Addr blk_addr, bool is_secure) const
70{
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) {
79 return mshr;
80 }
81 }
82 return NULL;
83}
84
85bool
86MSHRQueue::findMatches(Addr blk_addr, bool is_secure,
87 vector<MSHR*>& matches) const
88{
89 // Need an empty vector
90 assert(matches.empty());
91 bool retval = false;
92 for (const auto& mshr : allocatedList) {
93 if (!mshr->isUncacheable() && mshr->blkAddr == blk_addr &&
94 mshr->isSecure == is_secure) {
95 retval = true;
96 matches.push_back(mshr);
97 }
98 }
99 return retval;
100}
101
102
103bool
104MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
105{
106 pkt->pushLabel(label);
107 for (const auto& mshr : allocatedList) {
108 if (mshr->blkAddr == blk_addr && mshr->checkFunctional(pkt)) {
109 pkt->popLabel();
110 return true;
111 }
112 }
113 pkt->popLabel();
114 return false;
115}
116
117
118MSHR *
119MSHRQueue::findPending(Addr blk_addr, bool is_secure) const
120{
121 for (const auto& mshr : readyList) {
122 if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) {
123 return mshr;
124 }
125 }
126 return NULL;
127}
128
129
130MSHR::Iterator
131MSHRQueue::addToReadyList(MSHR *mshr)
132{
133 if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
134 return readyList.insert(readyList.end(), mshr);
135 }
136
137 for (auto i = readyList.begin(); i != readyList.end(); ++i) {
138 if ((*i)->readyTime > mshr->readyTime) {
139 return readyList.insert(i, mshr);
140 }
141 }
142 assert(false);
143 return readyList.end(); // keep stupid compilers happy
144}
145
146
147MSHR *
148MSHRQueue::allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt,
149 Tick when_ready, Counter order)
150{
151 assert(!freeList.empty());
152 MSHR *mshr = freeList.front();
153 assert(mshr->getNumTargets() == 0);
154 freeList.pop_front();
155
156 mshr->allocate(blk_addr, blk_size, pkt, when_ready, order);
157 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
158 mshr->readyIter = addToReadyList(mshr);
159
160 allocated += 1;
161 return mshr;
162}
163
164
165void
166MSHRQueue::deallocate(MSHR *mshr)
167{
168 deallocateOne(mshr);
169}
170
171MSHR::Iterator
172MSHRQueue::deallocateOne(MSHR *mshr)
173{
174 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
175 freeList.push_front(mshr);
176 allocated--;
177 if (mshr->inService) {
178 inServiceEntries--;
179 } else {
180 readyList.erase(mshr->readyIter);
181 }
182 mshr->deallocate();
183 if (drainManager && 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");
187 drainManager->signalDrainDone();
188 drainManager = NULL;
189 setDrainState(Drainable::Drained);
190 }
191 return retval;
192}
193
194void
195MSHRQueue::moveToFront(MSHR *mshr)
196{
197 if (!mshr->inService) {
198 assert(mshr == *(mshr->readyIter));
199 readyList.erase(mshr->readyIter);
200 mshr->readyIter = readyList.insert(readyList.begin(), mshr);
201 }
202}
203
204void
205MSHRQueue::markInService(MSHR *mshr, bool pending_dirty_resp)
206{
207 if (mshr->markInService(pending_dirty_resp)) {
208 deallocate(mshr);
209 } else {
210 readyList.erase(mshr->readyIter);
211 inServiceEntries += 1;
212 }
213}
214
215void
216MSHRQueue::markPending(MSHR *mshr)
217{
218 assert(mshr->inService);
219 mshr->inService = false;
220 --inServiceEntries;
221 /**
222 * @ todo might want to add rerequests to front of pending list for
223 * performance.
224 */
225 mshr->readyIter = addToReadyList(mshr);
226}
227
228bool
229MSHRQueue::forceDeallocateTarget(MSHR *mshr)
230{
231 bool was_full = isFull();
232 assert(mshr->hasTargets());
233 // Pop the prefetch off of the target list
234 mshr->popTarget();
235 // Delete mshr if no remaining targets
236 if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
237 deallocateOne(mshr);
238 }
239
240 // Notify if MSHR queue no longer full
241 return was_full && !isFull();
242}
243
244void
245MSHRQueue::squash(int threadNum)
246{
247 for (auto i = allocatedList.begin(); i != allocatedList.end();) {
248 MSHR *mshr = *i;
249 if (mshr->threadNum == threadNum) {
250 while (mshr->hasTargets()) {
251 mshr->popTarget();
252 assert(0/*target->req->threadId()*/ == threadNum);
253 }
254 assert(!mshr->hasTargets());
255 assert(mshr->getNumTargets()==0);
256 if (!mshr->inService) {
257 i = deallocateOne(mshr);
258 } else {
259 //mshr->pkt->flags &= ~CACHE_LINE_FILL;
260 ++i;
261 }
262 } else {
263 ++i;
264 }
265 }
266}
267
268unsigned int
269MSHRQueue::drain(DrainManager *dm)
270{
271 if (allocated == 0) {
272 setDrainState(Drainable::Drained);
273 return 0;
274 } else {
275 drainManager = dm;
276 setDrainState(Drainable::Draining);
277 return 1;
278 }
279}