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 ¶ms) : 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 + -
显示快捷键?