inst_queue_impl.hh

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

HH
1,409
字号
/* * Copyright (c) 2004, 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: Kevin T. Lim *          Korey L. Sewell */#include <limits>#include <vector>#include "cpu/o3/fu_pool.hh"#include "cpu/o3/inst_queue.hh"#include "enums/OpClass.hh"#include "sim/core.hh"template <class Impl>InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,                                                   int fu_idx,                                                   InstructionQueue<Impl> *iq_ptr)    : Event(&mainEventQueue, Stat_Event_Pri),      inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false){    this->setFlags(Event::AutoDelete);}template <class Impl>voidInstructionQueue<Impl>::FUCompletion::process(){    iqPtr->processFUCompletion(inst, freeFU ? fuIdx : -1);    inst = NULL;}template <class Impl>const char *InstructionQueue<Impl>::FUCompletion::description() const{    return "Functional unit completion";}template <class Impl>InstructionQueue<Impl>::InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr,                                         Params *params)    : cpu(cpu_ptr),      iewStage(iew_ptr),      fuPool(params->fuPool),      numEntries(params->numIQEntries),      totalWidth(params->issueWidth),      numPhysIntRegs(params->numPhysIntRegs),      numPhysFloatRegs(params->numPhysFloatRegs),      commitToIEWDelay(params->commitToIEWDelay){    assert(fuPool);    switchedOut = false;    numThreads = params->numberOfThreads;    // Set the number of physical registers as the number of int + float    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;    //Create an entry for each physical register within the    //dependency graph.    dependGraph.resize(numPhysRegs);    // Resize the register scoreboard.    regScoreboard.resize(numPhysRegs);    //Initialize Mem Dependence Units    for (int i = 0; i < numThreads; i++) {        memDepUnit[i].init(params,i);        memDepUnit[i].setIQ(this);    }    resetState();    std::string policy = params->smtIQPolicy;    //Convert string to lowercase    std::transform(policy.begin(), policy.end(), policy.begin(),                   (int(*)(int)) tolower);    //Figure out resource sharing policy    if (policy == "dynamic") {        iqPolicy = Dynamic;        //Set Max Entries to Total ROB Capacity        for (int i = 0; i < numThreads; i++) {            maxEntries[i] = numEntries;        }    } else if (policy == "partitioned") {        iqPolicy = Partitioned;        //@todo:make work if part_amt doesnt divide evenly.        int part_amt = numEntries / numThreads;        //Divide ROB up evenly        for (int i = 0; i < numThreads; i++) {            maxEntries[i] = part_amt;        }        DPRINTF(IQ, "IQ sharing policy set to Partitioned:"                "%i entries per thread.\n",part_amt);    } else if (policy == "threshold") {        iqPolicy = Threshold;        double threshold =  (double)params->smtIQThreshold / 100;        int thresholdIQ = (int)((double)threshold * numEntries);        //Divide up by threshold amount        for (int i = 0; i < numThreads; i++) {            maxEntries[i] = thresholdIQ;        }        DPRINTF(IQ, "IQ sharing policy set to Threshold:"                "%i entries per thread.\n",thresholdIQ);   } else {       assert(0 && "Invalid IQ Sharing Policy.Options Are:{Dynamic,"              "Partitioned, Threshold}");   }}template <class Impl>InstructionQueue<Impl>::~InstructionQueue(){    dependGraph.reset();#ifdef DEBUG    cprintf("Nodes traversed: %i, removed: %i\n",            dependGraph.nodesTraversed, dependGraph.nodesRemoved);#endif}template <class Impl>std::stringInstructionQueue<Impl>::name() const{    return cpu->name() + ".iq";}template <class Impl>voidInstructionQueue<Impl>::regStats(){    using namespace Stats;    iqInstsAdded        .name(name() + ".iqInstsAdded")        .desc("Number of instructions added to the IQ (excludes non-spec)")        .prereq(iqInstsAdded);    iqNonSpecInstsAdded        .name(name() + ".iqNonSpecInstsAdded")        .desc("Number of non-speculative instructions added to the IQ")        .prereq(iqNonSpecInstsAdded);    iqInstsIssued        .name(name() + ".iqInstsIssued")        .desc("Number of instructions issued")        .prereq(iqInstsIssued);    iqIntInstsIssued        .name(name() + ".iqIntInstsIssued")        .desc("Number of integer instructions issued")        .prereq(iqIntInstsIssued);    iqFloatInstsIssued        .name(name() + ".iqFloatInstsIssued")        .desc("Number of float instructions issued")        .prereq(iqFloatInstsIssued);    iqBranchInstsIssued        .name(name() + ".iqBranchInstsIssued")        .desc("Number of branch instructions issued")        .prereq(iqBranchInstsIssued);    iqMemInstsIssued        .name(name() + ".iqMemInstsIssued")        .desc("Number of memory instructions issued")        .prereq(iqMemInstsIssued);    iqMiscInstsIssued        .name(name() + ".iqMiscInstsIssued")        .desc("Number of miscellaneous instructions issued")        .prereq(iqMiscInstsIssued);    iqSquashedInstsIssued        .name(name() + ".iqSquashedInstsIssued")        .desc("Number of squashed instructions issued")        .prereq(iqSquashedInstsIssued);    iqSquashedInstsExamined        .name(name() + ".iqSquashedInstsExamined")        .desc("Number of squashed instructions iterated over during squash;"              " mainly for profiling")        .prereq(iqSquashedInstsExamined);    iqSquashedOperandsExamined        .name(name() + ".iqSquashedOperandsExamined")        .desc("Number of squashed operands that are examined and possibly "              "removed from graph")        .prereq(iqSquashedOperandsExamined);    iqSquashedNonSpecRemoved        .name(name() + ".iqSquashedNonSpecRemoved")        .desc("Number of squashed non-spec instructions that were removed")        .prereq(iqSquashedNonSpecRemoved);/*    queueResDist        .init(Num_OpClasses, 0, 99, 2)        .name(name() + ".IQ:residence:")        .desc("cycles from dispatch to issue")        .flags(total | pdf | cdf )        ;    for (int i = 0; i < Num_OpClasses; ++i) {        queueResDist.subname(i, opClassStrings[i]);    }*/    numIssuedDist        .init(0,totalWidth,1)        .name(name() + ".ISSUE:issued_per_cycle")        .desc("Number of insts issued each cycle")        .flags(pdf)        ;/*    dist_unissued        .init(Num_OpClasses+2)        .name(name() + ".ISSUE:unissued_cause")        .desc("Reason ready instruction not issued")        .flags(pdf | dist)        ;    for (int i=0; i < (Num_OpClasses + 2); ++i) {        dist_unissued.subname(i, unissued_names[i]);    }*/    statIssuedInstType        .init(numThreads,Enums::Num_OpClass)        .name(name() + ".ISSUE:FU_type")        .desc("Type of FU issued")        .flags(total | pdf | dist)        ;    statIssuedInstType.ysubnames(Enums::OpClassStrings);    //    //  How long did instructions for a particular FU type wait prior to issue    ///*    issueDelayDist        .init(Num_OpClasses,0,99,2)        .name(name() + ".ISSUE:")        .desc("cycles from operands ready to issue")        .flags(pdf | cdf)        ;    for (int i=0; i<Num_OpClasses; ++i) {        std::stringstream subname;        subname << opClassStrings[i] << "_delay";        issueDelayDist.subname(i, subname.str());    }*/    issueRate        .name(name() + ".ISSUE:rate")        .desc("Inst issue rate")        .flags(total)        ;    issueRate = iqInstsIssued / cpu->numCycles;    statFuBusy        .init(Num_OpClasses)        .name(name() + ".ISSUE:fu_full")        .desc("attempts to use FU when none available")        .flags(pdf | dist)        ;    for (int i=0; i < Num_OpClasses; ++i) {        statFuBusy.subname(i, Enums::OpClassStrings[i]);    }    fuBusy        .init(numThreads)        .name(name() + ".ISSUE:fu_busy_cnt")        .desc("FU busy when requested")        .flags(total)        ;    fuBusyRate        .name(name() + ".ISSUE:fu_busy_rate")        .desc("FU busy rate (busy events/executed inst)")        .flags(total)        ;    fuBusyRate = fuBusy / iqInstsIssued;    for ( int i=0; i < numThreads; i++) {        // Tell mem dependence unit to reg stats as well.        memDepUnit[i].regStats();    }}template <class Impl>voidInstructionQueue<Impl>::resetState(){    //Initialize thread IQ counts    for (int i = 0; i <numThreads; i++) {        count[i] = 0;        instList[i].clear();    }    // Initialize the number of free IQ entries.    freeEntries = numEntries;    // Note that in actuality, the registers corresponding to the logical    // registers start off as ready.  However this doesn't matter for the    // IQ as the instruction should have been correctly told if those    // registers are ready in rename.  Thus it can all be initialized as    // unready.    for (int i = 0; i < numPhysRegs; ++i) {        regScoreboard[i] = false;    }    for (int i = 0; i < numThreads; ++i) {        squashedSeqNum[i] = 0;    }    for (int i = 0; i < Num_OpClasses; ++i) {        while (!readyInsts[i].empty())            readyInsts[i].pop();        queueOnList[i] = false;        readyIt[i] = listOrder.end();    }    nonSpecInsts.clear();    listOrder.clear();}template <class Impl>voidInstructionQueue<Impl>::setActiveThreads(std::list<unsigned> *at_ptr){    activeThreads = at_ptr;}template <class Impl>voidInstructionQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr){      issueToExecuteQueue = i2e_ptr;}template <class Impl>voidInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr){    timeBuffer = tb_ptr;    fromCommit = timeBuffer->getWire(-commitToIEWDelay);}template <class Impl>voidInstructionQueue<Impl>::switchOut(){/*    if (!instList[0].empty() || (numEntries != freeEntries) ||        !readyInsts[0].empty() || !nonSpecInsts.empty() || !listOrder.empty()) {        dumpInsts();//        assert(0);    }*/    resetState();    dependGraph.reset();    instsToExecute.clear();    switchedOut = true;    for (int i = 0; i < numThreads; ++i) {        memDepUnit[i].switchOut();    }}template <class Impl>voidInstructionQueue<Impl>::takeOverFrom(){    switchedOut = false;}template <class Impl>intInstructionQueue<Impl>::entryAmount(int num_threads){    if (iqPolicy == Partitioned) {        return numEntries / num_threads;    } else {        return 0;    }}template <class Impl>voidInstructionQueue<Impl>::resetEntries(){    if (iqPolicy != Dynamic || numThreads > 1) {        int active_threads = activeThreads->size();        std::list<unsigned>::iterator threads = activeThreads->begin();        std::list<unsigned>::iterator end = activeThreads->end();        while (threads != end) {            unsigned tid = *threads++;            if (iqPolicy == Partitioned) {                maxEntries[tid] = numEntries / active_threads;            } else if(iqPolicy == Threshold && active_threads == 1) {                maxEntries[tid] = numEntries;            }        }    }}template <class Impl>unsignedInstructionQueue<Impl>::numFreeEntries(){    return freeEntries;}template <class Impl>unsignedInstructionQueue<Impl>::numFreeEntries(unsigned tid){    return maxEntries[tid] - count[tid];}// Might want to do something more complex if it knows how many instructions// will be issued this cycle.template <class Impl>boolInstructionQueue<Impl>::isFull(){    if (freeEntries == 0) {        return(true);    } else {        return(false);    }}template <class Impl>

⌨️ 快捷键说明

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