mshr_queue.cc revision 5715
15131Sgblack@eecs.umich.edu/*
25131Sgblack@eecs.umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan
35131Sgblack@eecs.umich.edu * All rights reserved.
45131Sgblack@eecs.umich.edu *
55131Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
65131Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
75131Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
85131Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
95131Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
105131Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
115131Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
125131Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
135131Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
145131Sgblack@eecs.umich.edu * this software without specific prior written permission.
155131Sgblack@eecs.umich.edu *
165131Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175131Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185131Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195131Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205131Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215131Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225131Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235131Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245131Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255131Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265131Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275131Sgblack@eecs.umich.edu *
285131Sgblack@eecs.umich.edu * Authors: Erik Hallnor
295390Sgblack@eecs.umich.edu */
305131Sgblack@eecs.umich.edu
315131Sgblack@eecs.umich.edu/** @file
325131Sgblack@eecs.umich.edu * Definition of MSHRQueue class functions.
338739Sgblack@eecs.umich.edu */
345638Sgblack@eecs.umich.edu
355629Sgblack@eecs.umich.edu#include "mem/cache/mshr_queue.hh"
365131Sgblack@eecs.umich.edu
375637Sgblack@eecs.umich.eduusing namespace std;
385637Sgblack@eecs.umich.edu
395637Sgblack@eecs.umich.eduMSHRQueue::MSHRQueue(const std::string &_label,
405629Sgblack@eecs.umich.edu                     int num_entries, int reserve, int _index)
415629Sgblack@eecs.umich.edu    : label(_label),
428335Snate@binkert.org      numEntries(num_entries + reserve - 1), numReserve(reserve),
435630Sgblack@eecs.umich.edu      index(_index)
445630Sgblack@eecs.umich.edu{
455630Sgblack@eecs.umich.edu    allocated = 0;
468335Snate@binkert.org    inServiceEntries = 0;
475633Sgblack@eecs.umich.edu    registers = new MSHR[numEntries];
485636Sgblack@eecs.umich.edu    for (int i = 0; i < numEntries; ++i) {
495636Sgblack@eecs.umich.edu        registers[i].queue = this;
508335Snate@binkert.org        freeList.push_back(&registers[i]);
515636Sgblack@eecs.umich.edu    }
525818Sgblack@eecs.umich.edu}
535818Sgblack@eecs.umich.edu
548335Snate@binkert.orgMSHRQueue::~MSHRQueue()
555818Sgblack@eecs.umich.edu{
565831Sgblack@eecs.umich.edu    delete [] registers;
575831Sgblack@eecs.umich.edu}
588335Snate@binkert.org
595831Sgblack@eecs.umich.eduMSHR *
605636Sgblack@eecs.umich.eduMSHRQueue::findMatch(Addr addr) const
615636Sgblack@eecs.umich.edu{
628335Snate@binkert.org    MSHR::ConstIterator i = allocatedList.begin();
635636Sgblack@eecs.umich.edu    MSHR::ConstIterator end = allocatedList.end();
645643Sgblack@eecs.umich.edu    for (; i != end; ++i) {
655643Sgblack@eecs.umich.edu        MSHR *mshr = *i;
668335Snate@binkert.org        if (mshr->addr == addr) {
675643Sgblack@eecs.umich.edu            return mshr;
685633Sgblack@eecs.umich.edu        }
695633Sgblack@eecs.umich.edu    }
708335Snate@binkert.org    return NULL;
71}
72
73bool
74MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
75{
76    // Need an empty vector
77    assert(matches.empty());
78    bool retval = false;
79    MSHR::ConstIterator i = allocatedList.begin();
80    MSHR::ConstIterator end = allocatedList.end();
81    for (; i != end; ++i) {
82        MSHR *mshr = *i;
83        if (mshr->addr == addr) {
84            retval = true;
85            matches.push_back(mshr);
86        }
87    }
88    return retval;
89}
90
91
92bool
93MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
94{
95    pkt->pushLabel(label);
96    MSHR::ConstIterator i = allocatedList.begin();
97    MSHR::ConstIterator end = allocatedList.end();
98    for (; i != end; ++i) {
99        MSHR *mshr = *i;
100        if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) {
101            pkt->popLabel();
102            return true;
103        }
104    }
105    pkt->popLabel();
106    return false;
107}
108
109
110MSHR *
111MSHRQueue::findPending(Addr addr, int size) const
112{
113    MSHR::ConstIterator i = readyList.begin();
114    MSHR::ConstIterator end = readyList.end();
115    for (; i != end; ++i) {
116        MSHR *mshr = *i;
117        if (mshr->addr < addr) {
118            if (mshr->addr + mshr->size > addr) {
119                return mshr;
120            }
121        } else {
122            if (addr + size > mshr->addr) {
123                return mshr;
124            }
125        }
126    }
127    return NULL;
128}
129
130
131MSHR::Iterator
132MSHRQueue::addToReadyList(MSHR *mshr)
133{
134    if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
135        return readyList.insert(readyList.end(), mshr);
136    }
137
138    MSHR::Iterator i = readyList.begin();
139    MSHR::Iterator end = readyList.end();
140    for (; i != end; ++i) {
141        if ((*i)->readyTime > mshr->readyTime) {
142            return readyList.insert(i, mshr);
143        }
144    }
145    assert(false);
146    return end;  // keep stupid compilers happy
147}
148
149
150MSHR *
151MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt,
152                    Tick when, Counter order)
153{
154    assert(!freeList.empty());
155    MSHR *mshr = freeList.front();
156    assert(mshr->getNumTargets() == 0);
157    freeList.pop_front();
158
159    mshr->allocate(addr, size, pkt, when, order);
160    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
161    mshr->readyIter = addToReadyList(mshr);
162
163    allocated += 1;
164    return mshr;
165}
166
167
168void
169MSHRQueue::deallocate(MSHR *mshr)
170{
171    deallocateOne(mshr);
172}
173
174MSHR::Iterator
175MSHRQueue::deallocateOne(MSHR *mshr)
176{
177    MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
178    freeList.push_front(mshr);
179    allocated--;
180    if (mshr->inService) {
181        inServiceEntries--;
182    } else {
183        readyList.erase(mshr->readyIter);
184    }
185    mshr->deallocate();
186    return retval;
187}
188
189void
190MSHRQueue::moveToFront(MSHR *mshr)
191{
192    if (!mshr->inService) {
193        assert(mshr == *(mshr->readyIter));
194        readyList.erase(mshr->readyIter);
195        mshr->readyIter = readyList.insert(readyList.begin(), mshr);
196    }
197}
198
199void
200MSHRQueue::markInService(MSHR *mshr)
201{
202    if (mshr->markInService()) {
203        deallocate(mshr);
204    } else {
205        readyList.erase(mshr->readyIter);
206        inServiceEntries += 1;
207    }
208}
209
210void
211MSHRQueue::markPending(MSHR *mshr)
212{
213    assert(mshr->inService);
214    mshr->inService = false;
215    --inServiceEntries;
216    /**
217     * @ todo might want to add rerequests to front of pending list for
218     * performance.
219     */
220    mshr->readyIter = addToReadyList(mshr);
221}
222
223void
224MSHRQueue::squash(int threadNum)
225{
226    MSHR::Iterator i = allocatedList.begin();
227    MSHR::Iterator end = allocatedList.end();
228    for (; i != end;) {
229        MSHR *mshr = *i;
230        if (mshr->threadNum == threadNum) {
231            while (mshr->hasTargets()) {
232                mshr->popTarget();
233                assert(0/*target->req->threadId()*/ == threadNum);
234            }
235            assert(!mshr->hasTargets());
236            assert(mshr->ntargets==0);
237            if (!mshr->inService) {
238                i = deallocateOne(mshr);
239            } else {
240                //mshr->pkt->flags &= ~CACHE_LINE_FILL;
241                ++i;
242            }
243        } else {
244            ++i;
245        }
246    }
247}
248