mshr_queue.cc revision 3149
12292SN/A/*
22689Sktlim@umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan
32292SN/A * All rights reserved.
42292SN/A *
52292SN/A * Redistribution and use in source and binary forms, with or without
62292SN/A * modification, are permitted provided that the following conditions are
72292SN/A * met: redistributions of source code must retain the above copyright
82292SN/A * notice, this list of conditions and the following disclaimer;
92292SN/A * redistributions in binary form must reproduce the above copyright
102292SN/A * notice, this list of conditions and the following disclaimer in the
112292SN/A * documentation and/or other materials provided with the distribution;
122292SN/A * neither the name of the copyright holders nor the names of its
132292SN/A * contributors may be used to endorse or promote products derived from
142292SN/A * this software without specific prior written permission.
152292SN/A *
162292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182292SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272689Sktlim@umich.edu *
282689Sktlim@umich.edu * Authors: Erik Hallnor
292292SN/A */
302292SN/A
312292SN/A/** @file
322292SN/A * Definition of the MSHRQueue.
332292SN/A */
342292SN/A
352292SN/A#include "mem/cache/miss/mshr_queue.hh"
362292SN/A#include "sim/eventq.hh"
372292SN/A
382292SN/Ausing namespace std;
392292SN/A
402669Sktlim@umich.eduMSHRQueue::MSHRQueue(int num_mshrs, int reserve)
415034Smilesck@eecs.umich.edu    : numMSHRs(num_mshrs + reserve - 1), numReserve(reserve)
422292SN/A{
432292SN/A    allocated = 0;
442292SN/A    inServiceMSHRs = 0;
452292SN/A    allocatedTargets = 0;
462292SN/A    registers = new MSHR[numMSHRs];
472292SN/A    for (int i = 0; i < numMSHRs; ++i) {
482292SN/A        freeList.push_back(&registers[i]);
492292SN/A    }
502292SN/A}
512292SN/A
522292SN/AMSHRQueue::~MSHRQueue()
532292SN/A{
542292SN/A    delete [] registers;
552292SN/A}
562292SN/A
572292SN/AMSHR*
582292SN/AMSHRQueue::findMatch(Addr addr) const
592292SN/A{
602292SN/A    MSHR::ConstIterator i = allocatedList.begin();
612292SN/A    MSHR::ConstIterator end = allocatedList.end();
622292SN/A    for (; i != end; ++i) {
632292SN/A        MSHR *mshr = *i;
642292SN/A        if (mshr->addr == addr) {
652292SN/A            return mshr;
662292SN/A        }
672292SN/A    }
682292SN/A    return NULL;
692292SN/A}
702292SN/A
712292SN/Abool
722292SN/AMSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
732292SN/A{
742292SN/A    // Need an empty vector
752292SN/A    assert(matches.empty());
762292SN/A    bool retval = false;
772292SN/A    MSHR::ConstIterator i = allocatedList.begin();
782292SN/A    MSHR::ConstIterator end = allocatedList.end();
792292SN/A    for (; i != end; ++i) {
802292SN/A        MSHR *mshr = *i;
812292SN/A        if (mshr->addr == addr) {
822292SN/A            retval = true;
832292SN/A            matches.push_back(mshr);
842292SN/A        }
852292SN/A    }
862292SN/A    return retval;
872292SN/A
882292SN/A}
892292SN/A
902292SN/AMSHR*
912292SN/AMSHRQueue::findPending(Packet * &pkt) const
922292SN/A{
932292SN/A    MSHR::ConstIterator i = pendingList.begin();
942292SN/A    MSHR::ConstIterator end = pendingList.end();
952292SN/A    for (; i != end; ++i) {
962292SN/A        MSHR *mshr = *i;
972292SN/A        if (mshr->addr < pkt->getAddr()) {
982292SN/A            if (mshr->addr + mshr->pkt->getSize() > pkt->getAddr()) {
992292SN/A                return mshr;
1002292SN/A            }
1012292SN/A        } else {
1022292SN/A            if (pkt->getAddr() + pkt->getSize() > mshr->addr) {
1032292SN/A                return mshr;
1042292SN/A            }
1052292SN/A        }
1062292SN/A
1072292SN/A        //need to check destination address for copies.
1082292SN/A        //TEMP NOT DOING COPIES
1092292SN/A#if 0
1102292SN/A        if (mshr->pkt->cmd == Copy) {
1112292SN/A            Addr dest = mshr->pkt->dest;
1122292SN/A            if (dest < pkt->addr) {
1132292SN/A                if (dest + mshr->pkt->size > pkt->addr) {
1142292SN/A                    return mshr;
1152292SN/A                }
1162292SN/A            } else {
1172292SN/A                if (pkt->addr + pkt->size > dest) {
1182292SN/A                    return mshr;
1192292SN/A                }
1205034Smilesck@eecs.umich.edu            }
1212292SN/A        }
1225034Smilesck@eecs.umich.edu#endif
1232292SN/A    }
1242292SN/A    return NULL;
1252292SN/A}
1262292SN/A
1272292SN/AMSHR*
1282292SN/AMSHRQueue::allocate(Packet * &pkt, int size)
1292292SN/A{
1302292SN/A    Addr aligned_addr = pkt->getAddr() & ~((Addr)size - 1);
1312292SN/A    assert(!freeList.empty());
1322292SN/A    MSHR *mshr = freeList.front();
1332292SN/A    assert(mshr->getNumTargets() == 0);
1342292SN/A    freeList.pop_front();
1352292SN/A
1362292SN/A    if (!pkt->needsResponse()) {
1372292SN/A        mshr->allocateAsBuffer(pkt);
1382292SN/A    } else {
1392292SN/A        assert(size !=0);
1402327SN/A        mshr->allocate(pkt->cmd, aligned_addr, size, pkt);
1412292SN/A        allocatedTargets += 1;
1422292SN/A    }
1432292SN/A    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
1442292SN/A    mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
1452292SN/A
1462292SN/A    allocated += 1;
1472292SN/A    return mshr;
1482292SN/A}
1492292SN/A
1502292SN/AMSHR*
1512292SN/AMSHRQueue::allocateFetch(Addr addr, int size, Packet * &target)
1522292SN/A{
1532292SN/A    MSHR *mshr = freeList.front();
1542292SN/A    assert(mshr->getNumTargets() == 0);
1552292SN/A    freeList.pop_front();
1562292SN/A    mshr->allocate(Packet::ReadReq, addr, size, target);
1572292SN/A    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
1582292SN/A    mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
1592292SN/A
1602307SN/A    allocated += 1;
1612348SN/A    return mshr;
1622307SN/A}
1632348SN/A
1642348SN/AMSHR*
1652307SN/AMSHRQueue::allocateTargetList(Addr addr, int size)
1662292SN/A{
1672292SN/A    MSHR *mshr = freeList.front();
1682292SN/A    assert(mshr->getNumTargets() == 0);
169    freeList.pop_front();
170    Packet * dummy;
171    mshr->allocate(Packet::ReadReq, addr, size, dummy);
172    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
173    mshr->inService = true;
174    ++inServiceMSHRs;
175    ++allocated;
176    return mshr;
177}
178
179
180void
181MSHRQueue::deallocate(MSHR* mshr)
182{
183    deallocateOne(mshr);
184}
185
186MSHR::Iterator
187MSHRQueue::deallocateOne(MSHR* mshr)
188{
189    MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
190    freeList.push_front(mshr);
191    allocated--;
192    allocatedTargets -= mshr->getNumTargets();
193    if (mshr->inService) {
194        inServiceMSHRs--;
195    } else {
196        pendingList.erase(mshr->readyIter);
197    }
198    mshr->deallocate();
199    return retval;
200}
201
202void
203MSHRQueue::moveToFront(MSHR *mshr)
204{
205    if (!mshr->inService) {
206        assert(mshr == *(mshr->readyIter));
207        pendingList.erase(mshr->readyIter);
208        mshr->readyIter = pendingList.insert(pendingList.begin(), mshr);
209    }
210}
211
212void
213MSHRQueue::markInService(MSHR* mshr)
214{
215    //assert(mshr == pendingList.front());
216    if (!mshr->pkt->needsResponse()) {
217        assert(mshr->getNumTargets() == 0);
218        deallocate(mshr);
219        return;
220    }
221    mshr->inService = true;
222    pendingList.erase(mshr->readyIter);
223    //mshr->readyIter = NULL;
224    inServiceMSHRs += 1;
225    //pendingList.pop_front();
226}
227
228void
229MSHRQueue::markPending(MSHR* mshr, Packet::Command cmd)
230{
231    //assert(mshr->readyIter == NULL);
232    mshr->pkt->cmd = cmd;
233    mshr->pkt->flags &= ~SATISFIED;
234    mshr->inService = false;
235    --inServiceMSHRs;
236    /**
237     * @ todo might want to add rerequests to front of pending list for
238     * performance.
239     */
240    mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
241}
242
243void
244MSHRQueue::squash(int threadNum)
245{
246    MSHR::Iterator i = allocatedList.begin();
247    MSHR::Iterator end = allocatedList.end();
248    for (; i != end;) {
249        MSHR *mshr = *i;
250        if (mshr->threadNum == threadNum) {
251            while (mshr->hasTargets()) {
252                Packet * target = mshr->getTarget();
253                mshr->popTarget();
254
255                assert(0/*target->req->getThreadNum()*/ == threadNum);
256                target = NULL;
257            }
258            assert(!mshr->hasTargets());
259            assert(mshr->ntargets==0);
260            if (!mshr->inService) {
261                i = deallocateOne(mshr);
262            } else {
263                //mshr->pkt->flags &= ~CACHE_LINE_FILL;
264                ++i;
265            }
266        } else {
267            ++i;
268        }
269    }
270}
271