mshr_queue.cc revision 4626
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Erik Hallnor
29 */
30
31/** @file
32 * Definition of MSHRQueue class functions.
33 */
34
35#include "mem/cache/miss/mshr_queue.hh"
36
37using namespace std;
38
39MSHRQueue::MSHRQueue(int num_entries, int reserve)
40    : numEntries(num_entries + reserve - 1), numReserve(reserve)
41{
42    allocated = 0;
43    inServiceEntries = 0;
44    registers = new MSHR[numEntries];
45    for (int i = 0; i < numEntries; ++i) {
46        registers[i].queue = this;
47        freeList.push_back(&registers[i]);
48    }
49}
50
51MSHRQueue::~MSHRQueue()
52{
53    delete [] registers;
54}
55
56MSHR *
57MSHRQueue::findMatch(Addr addr) const
58{
59    MSHR::ConstIterator i = allocatedList.begin();
60    MSHR::ConstIterator end = allocatedList.end();
61    for (; i != end; ++i) {
62        MSHR *mshr = *i;
63        if (mshr->addr == addr) {
64            return mshr;
65        }
66    }
67    return NULL;
68}
69
70bool
71MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
72{
73    // Need an empty vector
74    assert(matches.empty());
75    bool retval = false;
76    MSHR::ConstIterator i = allocatedList.begin();
77    MSHR::ConstIterator end = allocatedList.end();
78    for (; i != end; ++i) {
79        MSHR *mshr = *i;
80        if (mshr->addr == addr) {
81            retval = true;
82            matches.push_back(mshr);
83        }
84    }
85    return retval;
86
87}
88
89MSHR *
90MSHRQueue::findPending(Addr addr, int size) const
91{
92    MSHR::ConstIterator i = pendingList.begin();
93    MSHR::ConstIterator end = pendingList.end();
94    for (; i != end; ++i) {
95        MSHR *mshr = *i;
96        if (mshr->addr < addr) {
97            if (mshr->addr + mshr->size > addr) {
98                return mshr;
99            }
100        } else {
101            if (addr + size > mshr->addr) {
102                return mshr;
103            }
104        }
105    }
106    return NULL;
107}
108
109MSHR *
110MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt, bool isFill)
111{
112    assert(!freeList.empty());
113    MSHR *mshr = freeList.front();
114    assert(mshr->getNumTargets() == 0);
115    freeList.pop_front();
116
117    mshr->allocate(addr, size, pkt, isFill);
118    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
119    mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
120
121    allocated += 1;
122    return mshr;
123}
124
125
126void
127MSHRQueue::deallocate(MSHR *mshr)
128{
129    deallocateOne(mshr);
130}
131
132MSHR::Iterator
133MSHRQueue::deallocateOne(MSHR *mshr)
134{
135    MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
136    freeList.push_front(mshr);
137    allocated--;
138    if (mshr->inService) {
139        inServiceEntries--;
140    } else {
141        pendingList.erase(mshr->readyIter);
142    }
143    mshr->deallocate();
144    return retval;
145}
146
147void
148MSHRQueue::moveToFront(MSHR *mshr)
149{
150    if (!mshr->inService) {
151        assert(mshr == *(mshr->readyIter));
152        pendingList.erase(mshr->readyIter);
153        mshr->readyIter = pendingList.insert(pendingList.begin(), mshr);
154    }
155}
156
157void
158MSHRQueue::markInService(MSHR *mshr)
159{
160    //assert(mshr == pendingList.front());
161#if 0
162    if (!mshr->pkt->needsResponse() && !(mshr->pkt->cmd == MemCmd::UpgradeReq)) {
163        assert(mshr->getNumTargets() == 0);
164        deallocate(mshr);
165        return;
166    }
167#endif
168    mshr->inService = true;
169    pendingList.erase(mshr->readyIter);
170    //mshr->readyIter = NULL;
171    inServiceEntries += 1;
172    //pendingList.pop_front();
173}
174
175void
176MSHRQueue::markPending(MSHR *mshr)
177{
178    //assert(mshr->readyIter == NULL);
179    mshr->inService = false;
180    --inServiceEntries;
181    /**
182     * @ todo might want to add rerequests to front of pending list for
183     * performance.
184     */
185    mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
186}
187
188void
189MSHRQueue::squash(int threadNum)
190{
191    MSHR::Iterator i = allocatedList.begin();
192    MSHR::Iterator end = allocatedList.end();
193    for (; i != end;) {
194        MSHR *mshr = *i;
195        if (mshr->threadNum == threadNum) {
196            while (mshr->hasTargets()) {
197                mshr->popTarget();
198                assert(0/*target->req->getThreadNum()*/ == threadNum);
199            }
200            assert(!mshr->hasTargets());
201            assert(mshr->ntargets==0);
202            if (!mshr->inService) {
203                i = deallocateOne(mshr);
204            } else {
205                //mshr->pkt->flags &= ~CACHE_LINE_FILL;
206                ++i;
207            }
208        } else {
209            ++i;
210        }
211    }
212}
213