mshr_queue.cc (10622:0b969a35781f) mshr_queue.cc (10679:204a0f53035e)
1/*
2 * Copyright (c) 2012-2013 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 addr, bool is_secure) const
70{
71 MSHR::ConstIterator i = allocatedList.begin();
72 MSHR::ConstIterator end = allocatedList.end();
73 for (; i != end; ++i) {
74 MSHR *mshr = *i;
75 if (mshr->addr == addr && mshr->isSecure == is_secure) {
76 return mshr;
77 }
78 }
79 return NULL;
80}
81
82bool
83MSHRQueue::findMatches(Addr addr, bool is_secure, vector<MSHR*>& matches) const
84{
85 // Need an empty vector
86 assert(matches.empty());
87 bool retval = false;
88 MSHR::ConstIterator i = allocatedList.begin();
89 MSHR::ConstIterator end = allocatedList.end();
90 for (; i != end; ++i) {
91 MSHR *mshr = *i;
92 if (mshr->addr == addr && mshr->isSecure == is_secure) {
93 retval = true;
94 matches.push_back(mshr);
95 }
96 }
97 return retval;
98}
99
100
101bool
102MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
103{
104 pkt->pushLabel(label);
105 MSHR::ConstIterator i = allocatedList.begin();
106 MSHR::ConstIterator end = allocatedList.end();
107 for (; i != end; ++i) {
108 MSHR *mshr = *i;
109 if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) {
110 pkt->popLabel();
111 return true;
112 }
113 }
114 pkt->popLabel();
115 return false;
116}
117
118
119MSHR *
120MSHRQueue::findPending(Addr addr, int size, bool is_secure) const
121{
122 MSHR::ConstIterator i = readyList.begin();
123 MSHR::ConstIterator end = readyList.end();
124 for (; i != end; ++i) {
125 MSHR *mshr = *i;
126 if (mshr->isSecure == is_secure) {
127 if (mshr->addr < addr) {
128 if (mshr->addr + mshr->size > addr)
129 return mshr;
130 } else {
131 if (addr + size > mshr->addr)
132 return mshr;
133 }
134 }
135 }
136 return NULL;
137}
138
139
140MSHR::Iterator
141MSHRQueue::addToReadyList(MSHR *mshr)
142{
143 if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
144 return readyList.insert(readyList.end(), mshr);
145 }
146
147 MSHR::Iterator i = readyList.begin();
148 MSHR::Iterator end = readyList.end();
149 for (; i != end; ++i) {
150 if ((*i)->readyTime > mshr->readyTime) {
151 return readyList.insert(i, mshr);
152 }
153 }
154 assert(false);
155 return end; // keep stupid compilers happy
156}
157
158
159MSHR *
160MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt,
161 Tick when, Counter order)
162{
163 assert(!freeList.empty());
164 MSHR *mshr = freeList.front();
165 assert(mshr->getNumTargets() == 0);
166 freeList.pop_front();
167
168 mshr->allocate(addr, size, pkt, when, order);
169 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
170 mshr->readyIter = addToReadyList(mshr);
171
172 allocated += 1;
173 return mshr;
174}
175
176
177void
178MSHRQueue::deallocate(MSHR *mshr)
179{
180 deallocateOne(mshr);
181}
182
183MSHR::Iterator
184MSHRQueue::deallocateOne(MSHR *mshr)
185{
186 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
187 freeList.push_front(mshr);
188 allocated--;
189 if (mshr->inService) {
190 inServiceEntries--;
191 } else {
192 readyList.erase(mshr->readyIter);
193 }
194 mshr->deallocate();
195 if (drainManager && allocated == 0) {
196 // Notify the drain manager that we have completed draining if
197 // there are no other outstanding requests in this MSHR queue.
198 DPRINTF(Drain, "MSHRQueue now empty, signalling drained\n");
199 drainManager->signalDrainDone();
200 drainManager = NULL;
201 setDrainState(Drainable::Drained);
202 }
203 return retval;
204}
205
206void
207MSHRQueue::moveToFront(MSHR *mshr)
208{
209 if (!mshr->inService) {
210 assert(mshr == *(mshr->readyIter));
211 readyList.erase(mshr->readyIter);
212 mshr->readyIter = readyList.insert(readyList.begin(), mshr);
213 }
214}
215
216void
1/*
2 * Copyright (c) 2012-2013 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 addr, bool is_secure) const
70{
71 MSHR::ConstIterator i = allocatedList.begin();
72 MSHR::ConstIterator end = allocatedList.end();
73 for (; i != end; ++i) {
74 MSHR *mshr = *i;
75 if (mshr->addr == addr && mshr->isSecure == is_secure) {
76 return mshr;
77 }
78 }
79 return NULL;
80}
81
82bool
83MSHRQueue::findMatches(Addr addr, bool is_secure, vector<MSHR*>& matches) const
84{
85 // Need an empty vector
86 assert(matches.empty());
87 bool retval = false;
88 MSHR::ConstIterator i = allocatedList.begin();
89 MSHR::ConstIterator end = allocatedList.end();
90 for (; i != end; ++i) {
91 MSHR *mshr = *i;
92 if (mshr->addr == addr && mshr->isSecure == is_secure) {
93 retval = true;
94 matches.push_back(mshr);
95 }
96 }
97 return retval;
98}
99
100
101bool
102MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
103{
104 pkt->pushLabel(label);
105 MSHR::ConstIterator i = allocatedList.begin();
106 MSHR::ConstIterator end = allocatedList.end();
107 for (; i != end; ++i) {
108 MSHR *mshr = *i;
109 if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) {
110 pkt->popLabel();
111 return true;
112 }
113 }
114 pkt->popLabel();
115 return false;
116}
117
118
119MSHR *
120MSHRQueue::findPending(Addr addr, int size, bool is_secure) const
121{
122 MSHR::ConstIterator i = readyList.begin();
123 MSHR::ConstIterator end = readyList.end();
124 for (; i != end; ++i) {
125 MSHR *mshr = *i;
126 if (mshr->isSecure == is_secure) {
127 if (mshr->addr < addr) {
128 if (mshr->addr + mshr->size > addr)
129 return mshr;
130 } else {
131 if (addr + size > mshr->addr)
132 return mshr;
133 }
134 }
135 }
136 return NULL;
137}
138
139
140MSHR::Iterator
141MSHRQueue::addToReadyList(MSHR *mshr)
142{
143 if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
144 return readyList.insert(readyList.end(), mshr);
145 }
146
147 MSHR::Iterator i = readyList.begin();
148 MSHR::Iterator end = readyList.end();
149 for (; i != end; ++i) {
150 if ((*i)->readyTime > mshr->readyTime) {
151 return readyList.insert(i, mshr);
152 }
153 }
154 assert(false);
155 return end; // keep stupid compilers happy
156}
157
158
159MSHR *
160MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt,
161 Tick when, Counter order)
162{
163 assert(!freeList.empty());
164 MSHR *mshr = freeList.front();
165 assert(mshr->getNumTargets() == 0);
166 freeList.pop_front();
167
168 mshr->allocate(addr, size, pkt, when, order);
169 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
170 mshr->readyIter = addToReadyList(mshr);
171
172 allocated += 1;
173 return mshr;
174}
175
176
177void
178MSHRQueue::deallocate(MSHR *mshr)
179{
180 deallocateOne(mshr);
181}
182
183MSHR::Iterator
184MSHRQueue::deallocateOne(MSHR *mshr)
185{
186 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
187 freeList.push_front(mshr);
188 allocated--;
189 if (mshr->inService) {
190 inServiceEntries--;
191 } else {
192 readyList.erase(mshr->readyIter);
193 }
194 mshr->deallocate();
195 if (drainManager && allocated == 0) {
196 // Notify the drain manager that we have completed draining if
197 // there are no other outstanding requests in this MSHR queue.
198 DPRINTF(Drain, "MSHRQueue now empty, signalling drained\n");
199 drainManager->signalDrainDone();
200 drainManager = NULL;
201 setDrainState(Drainable::Drained);
202 }
203 return retval;
204}
205
206void
207MSHRQueue::moveToFront(MSHR *mshr)
208{
209 if (!mshr->inService) {
210 assert(mshr == *(mshr->readyIter));
211 readyList.erase(mshr->readyIter);
212 mshr->readyIter = readyList.insert(readyList.begin(), mshr);
213 }
214}
215
216void
217MSHRQueue::markInService(MSHR *mshr, PacketPtr pkt)
217MSHRQueue::markInService(MSHR *mshr, bool pending_dirty_resp)
218{
218{
219 if (mshr->markInService(pkt)) {
219 if (mshr->markInService(pending_dirty_resp)) {
220 deallocate(mshr);
221 } else {
222 readyList.erase(mshr->readyIter);
223 inServiceEntries += 1;
224 }
225}
226
227void
228MSHRQueue::markPending(MSHR *mshr)
229{
230 assert(mshr->inService);
231 mshr->inService = false;
232 --inServiceEntries;
233 /**
234 * @ todo might want to add rerequests to front of pending list for
235 * performance.
236 */
237 mshr->readyIter = addToReadyList(mshr);
238}
239
240bool
241MSHRQueue::forceDeallocateTarget(MSHR *mshr)
242{
243 bool was_full = isFull();
244 assert(mshr->hasTargets());
245 // Pop the prefetch off of the target list
246 mshr->popTarget();
247 // Delete mshr if no remaining targets
248 if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
249 deallocateOne(mshr);
250 }
251
252 // Notify if MSHR queue no longer full
253 return was_full && !isFull();
254}
255
256void
257MSHRQueue::squash(int threadNum)
258{
259 MSHR::Iterator i = allocatedList.begin();
260 MSHR::Iterator end = allocatedList.end();
261 for (; i != end;) {
262 MSHR *mshr = *i;
263 if (mshr->threadNum == threadNum) {
264 while (mshr->hasTargets()) {
265 mshr->popTarget();
266 assert(0/*target->req->threadId()*/ == threadNum);
267 }
268 assert(!mshr->hasTargets());
269 assert(mshr->getNumTargets()==0);
270 if (!mshr->inService) {
271 i = deallocateOne(mshr);
272 } else {
273 //mshr->pkt->flags &= ~CACHE_LINE_FILL;
274 ++i;
275 }
276 } else {
277 ++i;
278 }
279 }
280}
281
282unsigned int
283MSHRQueue::drain(DrainManager *dm)
284{
285 if (allocated == 0) {
286 setDrainState(Drainable::Drained);
287 return 0;
288 } else {
289 drainManager = dm;
290 setDrainState(Drainable::Draining);
291 return 1;
292 }
293}
220 deallocate(mshr);
221 } else {
222 readyList.erase(mshr->readyIter);
223 inServiceEntries += 1;
224 }
225}
226
227void
228MSHRQueue::markPending(MSHR *mshr)
229{
230 assert(mshr->inService);
231 mshr->inService = false;
232 --inServiceEntries;
233 /**
234 * @ todo might want to add rerequests to front of pending list for
235 * performance.
236 */
237 mshr->readyIter = addToReadyList(mshr);
238}
239
240bool
241MSHRQueue::forceDeallocateTarget(MSHR *mshr)
242{
243 bool was_full = isFull();
244 assert(mshr->hasTargets());
245 // Pop the prefetch off of the target list
246 mshr->popTarget();
247 // Delete mshr if no remaining targets
248 if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
249 deallocateOne(mshr);
250 }
251
252 // Notify if MSHR queue no longer full
253 return was_full && !isFull();
254}
255
256void
257MSHRQueue::squash(int threadNum)
258{
259 MSHR::Iterator i = allocatedList.begin();
260 MSHR::Iterator end = allocatedList.end();
261 for (; i != end;) {
262 MSHR *mshr = *i;
263 if (mshr->threadNum == threadNum) {
264 while (mshr->hasTargets()) {
265 mshr->popTarget();
266 assert(0/*target->req->threadId()*/ == threadNum);
267 }
268 assert(!mshr->hasTargets());
269 assert(mshr->getNumTargets()==0);
270 if (!mshr->inService) {
271 i = deallocateOne(mshr);
272 } else {
273 //mshr->pkt->flags &= ~CACHE_LINE_FILL;
274 ++i;
275 }
276 } else {
277 ++i;
278 }
279 }
280}
281
282unsigned int
283MSHRQueue::drain(DrainManager *dm)
284{
285 if (allocated == 0) {
286 setDrainState(Drainable::Drained);
287 return 0;
288 } else {
289 drainManager = dm;
290 setDrainState(Drainable::Draining);
291 return 1;
292 }
293}