rob_impl.hh
来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 316 行
HH
316 行
/* * 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. */#ifndef __CPU_O3_CPU_ROB_IMPL_HH__#define __CPU_O3_CPU_ROB_IMPL_HH__#include "config/full_system.hh"#include "cpu/o3/rob.hh"template <class Impl>ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) : numEntries(_numEntries), squashWidth(_squashWidth), numInstsInROB(0), squashedSeqNum(0){ doneSquashing = true;}template <class Impl>voidROB<Impl>::setCPU(FullCPU *cpu_ptr){ cpu = cpu_ptr; // Set the tail to the beginning of the CPU instruction list so that // upon the first instruction being inserted into the ROB, the tail // iterator can simply be incremented. tail = cpu->instList.begin(); // Set the squash iterator to the end of the instruction list. squashIt = cpu->instList.end();}template <class Impl>intROB<Impl>::countInsts(){ // Start at 1; if the tail matches cpu->instList.begin(), then there is // one inst in the ROB. int return_val = 1; // There are quite a few special cases. Do not use this function other // than for debugging purposes. if (cpu->instList.begin() == cpu->instList.end()) { // In this case there are no instructions in the list. The ROB // must be empty. return 0; } else if (tail == cpu->instList.end()) { // In this case, the tail is not yet pointing to anything valid. // The ROB must be empty. return 0; } // Iterate through the ROB from the head to the tail, counting the // entries. for (InstIt_t i = cpu->instList.begin(); i != tail; ++i) { assert(i != cpu->instList.end()); ++return_val; } return return_val; // Because the head won't be tracked properly until the ROB gets the // first instruction, and any time that the ROB is empty and has not // yet gotten the instruction, this function doesn't work.// return numInstsInROB;}template <class Impl>voidROB<Impl>::insertInst(DynInstPtr &inst){ // Make sure we have the right number of instructions. assert(numInstsInROB == countInsts()); // Make sure the instruction is valid. assert(inst); DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); // If the ROB is full then exit. assert(numInstsInROB != numEntries); ++numInstsInROB; // Increment the tail iterator, moving it one instruction back. // There is a special case if the ROB was empty prior to this insertion, // in which case the tail will be pointing at instList.end(). If that // happens, then reset the tail to the beginning of the list. if (tail != cpu->instList.end()) { ++tail; } else { tail = cpu->instList.begin(); } // Make sure the tail iterator is actually pointing at the instruction // added. assert((*tail) == inst); DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);}// Whatever calls this function needs to ensure that it properly frees up // registers prior to this function.template <class Impl>voidROB<Impl>::retireHead(){ assert(numInstsInROB == countInsts()); assert(numInstsInROB > 0); // Get the head ROB instruction. DynInstPtr head_inst = cpu->instList.front(); // Make certain this can retire. assert(head_inst->readyToCommit()); DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " "instruction PC %#x, seq num %i\n", head_inst->readPC(), head_inst->seqNum); // Keep track of how many instructions are in the ROB. --numInstsInROB; // Tell CPU to remove the instruction from the list of instructions. // A special case is needed if the instruction being retired is the // only instruction in the ROB; otherwise the tail iterator will become // invalidated. cpu->removeFrontInst(head_inst); if (numInstsInROB == 0) { tail = cpu->instList.end(); }}template <class Impl>boolROB<Impl>::isHeadReady(){ if (numInstsInROB != 0) { return cpu->instList.front()->readyToCommit(); } return false;}template <class Impl>unsignedROB<Impl>::numFreeEntries(){ assert(numInstsInROB == countInsts()); return numEntries - numInstsInROB;}template <class Impl>voidROB<Impl>::doSquash(){ DPRINTF(ROB, "ROB: Squashing instructions.\n"); assert(squashIt != cpu->instList.end()); for (int numSquashed = 0; numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; ++numSquashed) { // Ensure that the instruction is younger. assert((*squashIt)->seqNum > squashedSeqNum); DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", (*squashIt)->readPC(), (*squashIt)->seqNum); // Mark the instruction as squashed, and ready to commit so that // it can drain out of the pipeline. (*squashIt)->setSquashed(); (*squashIt)->setCanCommit(); // Special case for when squashing due to a syscall. It's possible // that the squash happened after the head instruction was already // committed, meaning that (*squashIt)->seqNum != squashedSeqNum // will never be false. Normally the squash would never be able // to go past the head of the ROB; in this case it might, so it // must be handled otherwise it will segfault.#if !FULL_SYSTEM if (squashIt == cpu->instList.begin()) { DPRINTF(ROB, "ROB: Reached head of instruction list while " "squashing.\n"); squashIt = cpu->instList.end(); doneSquashing = true; return; }#endif // Move the tail iterator to the next instruction. squashIt--; } // Check if ROB is done squashing. if ((*squashIt)->seqNum == squashedSeqNum) { DPRINTF(ROB, "ROB: Done squashing instructions.\n"); squashIt = cpu->instList.end(); doneSquashing = true; }}template <class Impl>voidROB<Impl>::squash(InstSeqNum squash_num){ DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); doneSquashing = false; squashedSeqNum = squash_num; assert(tail != cpu->instList.end()); squashIt = tail; doSquash();}template <class Impl>uint64_tROB<Impl>::readHeadPC(){ assert(numInstsInROB == countInsts()); DynInstPtr head_inst = cpu->instList.front(); return head_inst->readPC();}template <class Impl>uint64_tROB<Impl>::readHeadNextPC(){ assert(numInstsInROB == countInsts()); DynInstPtr head_inst = cpu->instList.front(); return head_inst->readNextPC();}template <class Impl>InstSeqNumROB<Impl>::readHeadSeqNum(){ // Return the last sequence number that has not been squashed. Other // stages can use it to squash any instructions younger than the current // tail. DynInstPtr head_inst = cpu->instList.front(); return head_inst->seqNum;}template <class Impl>uint64_tROB<Impl>::readTailPC(){ assert(numInstsInROB == countInsts()); assert(tail != cpu->instList.end()); return (*tail)->readPC();}template <class Impl>InstSeqNumROB<Impl>::readTailSeqNum(){ // Return the last sequence number that has not been squashed. Other // stages can use it to squash any instructions younger than the current // tail. return (*tail)->seqNum;}#endif // __CPU_O3_CPU_ROB_IMPL_HH__
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?