inst_queue_impl.hh

来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 1,139 行 · 第 1/3 页

HH
1,139
字号
/* * Copyright (c) 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator, developed by Nathan Binkert, * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions * from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi,  * and Andrew Schultz. * * 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. */// Todo: // Current ordering allows for 0 cycle added-to-scheduled.  Could maybe fake// it; either do in reverse order, or have added instructions put into a// different ready queue that, in scheduleRreadyInsts(), gets put onto the// normal ready queue.  This would however give only a one cycle delay,// but probably is more flexible to actually add in a delay parameter than// just running it backwards.#include <vector>#include "sim/root.hh"#include "cpu/o3/inst_queue.hh"// Either compile error or max int due to sign extension.// Hack to avoid compile warnings.const InstSeqNum MaxInstSeqNum = 0 - 1;template <class Impl>InstructionQueue<Impl>::InstructionQueue(Params &params)    : memDepUnit(params),      numEntries(params.numIQEntries),      intWidth(params.executeIntWidth),      floatWidth(params.executeFloatWidth),      branchWidth(params.executeBranchWidth),      memoryWidth(params.executeMemoryWidth),      totalWidth(params.issueWidth),      numPhysIntRegs(params.numPhysIntRegs),      numPhysFloatRegs(params.numPhysFloatRegs),      commitToIEWDelay(params.commitToIEWDelay){    // Initialize the number of free IQ entries.    freeEntries = numEntries;    // Set the number of physical registers as the number of int + float    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;    DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs);    //Create an entry for each physical register within the     //dependency graph.    dependGraph = new DependencyEntry[numPhysRegs];    // Resize the register scoreboard.    regScoreboard.resize(numPhysRegs);    // Initialize all the head pointers to point to NULL, and all the    // entries as unready.    // 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)    {        dependGraph[i].next = NULL;        dependGraph[i].inst = NULL;        regScoreboard[i] = false;    }}template <class Impl>voidInstructionQueue<Impl>::regStats(){    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);//    iqIntInstsAdded;    iqIntInstsIssued        .name(name() + ".iqIntInstsIssued")        .desc("Number of integer instructions issued")        .prereq(iqIntInstsIssued);//    iqFloatInstsAdded;    iqFloatInstsIssued        .name(name() + ".iqFloatInstsIssued")        .desc("Number of float instructions issued")        .prereq(iqFloatInstsIssued);//    iqBranchInstsAdded;    iqBranchInstsIssued        .name(name() + ".iqBranchInstsIssued")        .desc("Number of branch instructions issued")        .prereq(iqBranchInstsIssued);//    iqMemInstsAdded;    iqMemInstsIssued        .name(name() + ".iqMemInstsIssued")        .desc("Number of memory instructions issued")        .prereq(iqMemInstsIssued);//    iqMiscInstsAdded;    iqMiscInstsIssued        .name(name() + ".iqMiscInstsIssued")        .desc("Number of miscellaneous instructions issued")        .prereq(iqMiscInstsIssued);    iqSquashedInstsIssued        .name(name() + ".iqSquashedInstsIssued")        .desc("Number of squashed instructions issued")        .prereq(iqSquashedInstsIssued);    iqLoopSquashStalls        .name(name() + ".iqLoopSquashStalls")        .desc("Number of times issue loop had to restart due to squashed "              "inst; mainly for profiling")        .prereq(iqLoopSquashStalls);    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);    // Tell mem dependence unit to reg stats as well.    memDepUnit.regStats();}template <class Impl>voidInstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr){    cpu = cpu_ptr;    tail = cpu->instList.begin();}template <class Impl>voidInstructionQueue<Impl>::setIssueToExecuteQueue(                        TimeBuffer<IssueStruct> *i2e_ptr){    DPRINTF(IQ, "IQ: Set the issue to execute queue.\n");    issueToExecuteQueue = i2e_ptr;}template <class Impl>voidInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr){    DPRINTF(IQ, "IQ: Set the time buffer.\n");    timeBuffer = tb_ptr;    fromCommit = timeBuffer->getWire(-commitToIEWDelay);}template <class Impl>unsignedInstructionQueue<Impl>::numFreeEntries(){    return freeEntries;}// 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>voidInstructionQueue<Impl>::insert(DynInstPtr &new_inst){    // Make sure the instruction is valid    assert(new_inst);    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",            new_inst->readPC());    // Check if there are any free entries.  Panic if there are none.    // Might want to have this return a fault in the future instead of    // panicing.    assert(freeEntries != 0);    // If the IQ currently has nothing in it, then there's a possibility    // that the tail iterator is invalid (might have been pointing at an    // instruction that was retired).  Reset the tail iterator.    if (freeEntries == numEntries) {        tail = cpu->instList.begin();    }    // Move the tail iterator.  Instructions may not have been issued    // to the IQ, so we may have to increment the iterator more than once.    while ((*tail) != new_inst) {        tail++;                // Make sure the tail iterator points at something legal.        assert(tail != cpu->instList.end());    }        // Decrease the number of free entries.    --freeEntries;    // Look through its source registers (physical regs), and mark any    // dependencies.    addToDependents(new_inst);    // Have this instruction set itself as the producer of its destination    // register(s).    createDependency(new_inst);    // If it's a memory instruction, add it to the memory dependency    // unit.    if (new_inst->isMemRef()) {        memDepUnit.insert(new_inst);        // Uh..forgot to look it up and put it on the proper dependency list        // if the instruction should not go yet.    } else {           // If the instruction is ready then add it to the ready list.        addIfReady(new_inst);    }    ++iqInstsAdded;    assert(freeEntries == (numEntries - countInsts()));}template <class Impl>voidInstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst){    nonSpecInsts[inst->seqNum] = inst;    // @todo: Clean up this code; can do it by setting inst as unable    // to issue, then calling normal insert on the inst.    // Make sure the instruction is valid    assert(inst);    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",            inst->readPC());    // Check if there are any free entries.  Panic if there are none.    // Might want to have this return a fault in the future instead of    // panicing.    assert(freeEntries != 0);    // If the IQ currently has nothing in it, then there's a possibility    // that the tail iterator is invalid (might have been pointing at an    // instruction that was retired).  Reset the tail iterator.    if (freeEntries == numEntries) {        tail = cpu->instList.begin();    }    // Move the tail iterator.  Instructions may not have been issued    // to the IQ, so we may have to increment the iterator more than once.    while ((*tail) != inst) {        tail++;                // Make sure the tail iterator points at something legal.        assert(tail != cpu->instList.end());    }    // Decrease the number of free entries.    --freeEntries;    // Have this instruction set itself as the producer of its destination    // register(s).    createDependency(inst);    // If it's a memory instruction, add it to the memory dependency    // unit.    if (inst->isMemRef()) {        memDepUnit.insertNonSpec(inst);    }    ++iqNonSpecInstsAdded;}// Slightly hack function to advance the tail iterator in the case that// the IEW stage issues an instruction that is not added to the IQ.  This// is needed in case a long chain of such instructions occurs.// I don't think this is used anymore.template <class Impl>voidInstructionQueue<Impl>::advanceTail(DynInstPtr &inst){    // Make sure the instruction is valid    assert(inst);    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",            inst->readPC());    // Check if there are any free entries.  Panic if there are none.    // Might want to have this return a fault in the future instead of    // panicing.    assert(freeEntries != 0);    // If the IQ currently has nothing in it, then there's a possibility    // that the tail iterator is invalid (might have been pointing at an    // instruction that was retired).  Reset the tail iterator.    if (freeEntries == numEntries) {        tail = cpu->instList.begin();    }    // Move the tail iterator.  Instructions may not have been issued    // to the IQ, so we may have to increment the iterator more than once.    while ((*tail) != inst) {        tail++;                // Make sure the tail iterator points at something legal.        assert(tail != cpu->instList.end());    }    assert(freeEntries <= numEntries);    // Have this instruction set itself as the producer of its destination    // register(s).    createDependency(inst);}// Need to make sure the number of float and integer instructions// issued does not exceed the total issue bandwidth.  // @todo: Figure out a better way to remove the squashed items from the// lists.  Checking the top item of each list to see if it's squashed// wastes time and forces jumps.

⌨️ 快捷键说明

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