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