lsq_impl.hh

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 628 行

HH
628
字号
/* * Copyright (c) 2005, 2006 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Korey L. Sewell */#include <algorithm>#include <list>#include <string>#include "cpu/o3/lsq.hh"template<class Impl>voidLSQ<Impl>::DcachePort::setPeer(Port *port){    Port::setPeer(port);#if FULL_SYSTEM    // Update the ThreadContext's memory ports (Functional/Virtual    // Ports)    lsq->updateMemPorts();#endif}template <class Impl>TickLSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt){    panic("O3CPU model does not work with atomic mode!");    return curTick;}template <class Impl>voidLSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt){    DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional.");}template <class Impl>voidLSQ<Impl>::DcachePort::recvStatusChange(Status status){    if (status == RangeChange) {        if (!snoopRangeSent) {            snoopRangeSent = true;            sendStatusChange(Port::RangeChange);        }        return;    }    panic("O3CPU doesn't expect recvStatusChange callback!");}template <class Impl>boolLSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt){    if (pkt->isError())        DPRINTF(LSQ, "Got error packet back for address: %#X\n", pkt->getAddr());    if (pkt->isResponse()) {        lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt);    }    else {        // must be a snoop        // @TODO someday may need to process invalidations in LSQ here        // to provide stronger consistency model    }    return true;}template <class Impl>voidLSQ<Impl>::DcachePort::recvRetry(){    if (lsq->retryTid == -1)    {        //Squashed, so drop it        return;    }    int curr_retry_tid = lsq->retryTid;    // Speculatively clear the retry Tid.  This will get set again if    // the LSQUnit was unable to complete its access.    lsq->retryTid = -1;    lsq->thread[curr_retry_tid].recvRetry();}template <class Impl>LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params)    : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this),      LQEntries(params->LQEntries),      SQEntries(params->SQEntries),      numThreads(params->numberOfThreads),      retryTid(-1){    dcachePort.snoopRangeSent = false;    //**********************************************/    //************ Handle SMT Parameters ***********/    //**********************************************/    std::string policy = params->smtLSQPolicy;    //Convert string to lowercase    std::transform(policy.begin(), policy.end(), policy.begin(),                   (int(*)(int)) tolower);    //Figure out fetch policy    if (policy == "dynamic") {        lsqPolicy = Dynamic;        maxLQEntries = LQEntries;        maxSQEntries = SQEntries;        DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");    } else if (policy == "partitioned") {        lsqPolicy = Partitioned;        //@todo:make work if part_amt doesnt divide evenly.        maxLQEntries = LQEntries / numThreads;        maxSQEntries = SQEntries / numThreads;        DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "                "%i entries per LQ | %i entries per SQ",                maxLQEntries,maxSQEntries);    } else if (policy == "threshold") {        lsqPolicy = Threshold;        assert(params->smtLSQThreshold > LQEntries);        assert(params->smtLSQThreshold > SQEntries);        //Divide up by threshold amount        //@todo: Should threads check the max and the total        //amount of the LSQ        maxLQEntries  = params->smtLSQThreshold;        maxSQEntries  = params->smtLSQThreshold;        DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "                "%i entries per LQ | %i entries per SQ",                maxLQEntries,maxSQEntries);    } else {        assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"                    "Partitioned, Threshold}");    }    //Initialize LSQs    for (int tid=0; tid < numThreads; tid++) {        thread[tid].init(cpu, iew_ptr, params, this,                         maxLQEntries, maxSQEntries, tid);        thread[tid].setDcachePort(&dcachePort);    }}template<class Impl>std::stringLSQ<Impl>::name() const{    return iewStage->name() + ".lsq";}template<class Impl>voidLSQ<Impl>::regStats(){    //Initialize LSQs    for (int tid=0; tid < numThreads; tid++) {        thread[tid].regStats();    }}template<class Impl>voidLSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr){    activeThreads = at_ptr;    assert(activeThreads != 0);}template <class Impl>voidLSQ<Impl>::switchOut(){    for (int tid = 0; tid < numThreads; tid++) {        thread[tid].switchOut();    }}template <class Impl>voidLSQ<Impl>::takeOverFrom(){    for (int tid = 0; tid < numThreads; tid++) {        thread[tid].takeOverFrom();    }}template <class Impl>intLSQ<Impl>::entryAmount(int num_threads){    if (lsqPolicy == Partitioned) {        return LQEntries / num_threads;    } else {        return 0;    }}template <class Impl>voidLSQ<Impl>::resetEntries(){    if (lsqPolicy != Dynamic || numThreads > 1) {        int active_threads = activeThreads->size();        int maxEntries;        if (lsqPolicy == Partitioned) {            maxEntries = LQEntries / active_threads;        } else if (lsqPolicy == Threshold && active_threads == 1) {            maxEntries = LQEntries;        } else {            maxEntries = LQEntries;        }        std::list<unsigned>::iterator threads  = activeThreads->begin();        std::list<unsigned>::iterator end = activeThreads->end();        while (threads != end) {            unsigned tid = *threads++;            resizeEntries(maxEntries, tid);        }    }}template<class Impl>voidLSQ<Impl>::removeEntries(unsigned tid){    thread[tid].clearLQ();    thread[tid].clearSQ();}template<class Impl>voidLSQ<Impl>::resizeEntries(unsigned size,unsigned tid){    thread[tid].resizeLQ(size);    thread[tid].resizeSQ(size);}template<class Impl>voidLSQ<Impl>::tick(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        thread[tid].tick();    }}template<class Impl>voidLSQ<Impl>::insertLoad(DynInstPtr &load_inst){    unsigned tid = load_inst->threadNumber;    thread[tid].insertLoad(load_inst);}template<class Impl>voidLSQ<Impl>::insertStore(DynInstPtr &store_inst){    unsigned tid = store_inst->threadNumber;    thread[tid].insertStore(store_inst);}template<class Impl>FaultLSQ<Impl>::executeLoad(DynInstPtr &inst){    unsigned tid = inst->threadNumber;    return thread[tid].executeLoad(inst);}template<class Impl>FaultLSQ<Impl>::executeStore(DynInstPtr &inst){    unsigned tid = inst->threadNumber;    return thread[tid].executeStore(inst);}template<class Impl>voidLSQ<Impl>::writebackStores(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (numStoresToWB(tid) > 0) {            DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "                "available for Writeback.\n", tid, numStoresToWB(tid));        }        thread[tid].writebackStores();    }}template<class Impl>boolLSQ<Impl>::violation(){    /* Answers: Does Anybody Have a Violation?*/    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (thread[tid].violation())            return true;    }    return false;}template<class Impl>intLSQ<Impl>::getCount(){    unsigned total = 0;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        total += getCount(tid);    }    return total;}template<class Impl>intLSQ<Impl>::numLoads(){    unsigned total = 0;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        total += numLoads(tid);    }    return total;}template<class Impl>intLSQ<Impl>::numStores(){    unsigned total = 0;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        total += thread[tid].numStores();    }    return total;}template<class Impl>intLSQ<Impl>::numLoadsReady(){    unsigned total = 0;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        total += thread[tid].numLoadsReady();    }    return total;}template<class Impl>unsignedLSQ<Impl>::numFreeEntries(){    unsigned total = 0;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        total += thread[tid].numFreeEntries();    }    return total;}template<class Impl>unsignedLSQ<Impl>::numFreeEntries(unsigned tid){    //if (lsqPolicy == Dynamic)    //return numFreeEntries();    //else        return thread[tid].numFreeEntries();}template<class Impl>boolLSQ<Impl>::isFull(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (!(thread[tid].lqFull() || thread[tid].sqFull()))            return false;    }    return true;}template<class Impl>boolLSQ<Impl>::isFull(unsigned tid){    //@todo: Change to Calculate All Entries for    //Dynamic Policy    if (lsqPolicy == Dynamic)        return isFull();    else        return thread[tid].lqFull() || thread[tid].sqFull();}template<class Impl>boolLSQ<Impl>::lqFull(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (!thread[tid].lqFull())            return false;    }    return true;}template<class Impl>boolLSQ<Impl>::lqFull(unsigned tid){    //@todo: Change to Calculate All Entries for    //Dynamic Policy    if (lsqPolicy == Dynamic)        return lqFull();    else        return thread[tid].lqFull();}template<class Impl>boolLSQ<Impl>::sqFull(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (!sqFull(tid))            return false;    }    return true;}template<class Impl>boolLSQ<Impl>::sqFull(unsigned tid){     //@todo: Change to Calculate All Entries for    //Dynamic Policy    if (lsqPolicy == Dynamic)        return sqFull();    else        return thread[tid].sqFull();}template<class Impl>boolLSQ<Impl>::isStalled(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (!thread[tid].isStalled())            return false;    }    return true;}template<class Impl>boolLSQ<Impl>::isStalled(unsigned tid){    if (lsqPolicy == Dynamic)        return isStalled();    else        return thread[tid].isStalled();}template<class Impl>boolLSQ<Impl>::hasStoresToWB(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    if (threads == end)        return false;    while (threads != end) {        unsigned tid = *threads++;        if (!hasStoresToWB(tid))            return false;    }    return true;}template<class Impl>boolLSQ<Impl>::willWB(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (!willWB(tid))            return false;    }    return true;}template<class Impl>voidLSQ<Impl>::dumpInsts(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        thread[tid].dumpInsts();    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?