rename_impl.hh
来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 758 行 · 第 1/2 页
HH
758 行
/* * 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. */#include <list>#include "config/full_system.hh"#include "cpu/o3/rename.hh"template <class Impl>SimpleRename<Impl>::SimpleRename(Params ¶ms) : iewToRenameDelay(params.iewToRenameDelay), decodeToRenameDelay(params.decodeToRenameDelay), commitToRenameDelay(params.commitToRenameDelay), renameWidth(params.renameWidth), commitWidth(params.commitWidth), numInst(0){ _status = Idle;}template <class Impl>voidSimpleRename<Impl>::regStats(){ renameSquashCycles .name(name() + ".renameSquashCycles") .desc("Number of cycles rename is squashing") .prereq(renameSquashCycles); renameIdleCycles .name(name() + ".renameIdleCycles") .desc("Number of cycles rename is idle") .prereq(renameIdleCycles); renameBlockCycles .name(name() + ".renameBlockCycles") .desc("Number of cycles rename is blocking") .prereq(renameBlockCycles); renameUnblockCycles .name(name() + ".renameUnblockCycles") .desc("Number of cycles rename is unblocking") .prereq(renameUnblockCycles); renameRenamedInsts .name(name() + ".renameRenamedInsts") .desc("Number of instructions processed by rename") .prereq(renameRenamedInsts); renameSquashedInsts .name(name() + ".renameSquashedInsts") .desc("Number of squashed instructions processed by rename") .prereq(renameSquashedInsts); renameROBFullEvents .name(name() + ".renameROBFullEvents") .desc("Number of times rename has considered the ROB 'full'") .prereq(renameROBFullEvents); renameIQFullEvents .name(name() + ".renameIQFullEvents") .desc("Number of times rename has considered the IQ 'full'") .prereq(renameIQFullEvents); renameFullRegistersEvents .name(name() + ".renameFullRegisterEvents") .desc("Number of times there has been no free registers") .prereq(renameFullRegistersEvents); renameRenamedOperands .name(name() + ".renameRenamedOperands") .desc("Number of destination operands rename has renamed") .prereq(renameRenamedOperands); renameRenameLookups .name(name() + ".renameRenameLookups") .desc("Number of register rename lookups that rename has made") .prereq(renameRenameLookups); renameHBPlaceHolders .name(name() + ".renameHBPlaceHolders") .desc("Number of place holders added to the history buffer") .prereq(renameHBPlaceHolders); renameCommittedMaps .name(name() + ".renameCommittedMaps") .desc("Number of HB maps that are committed") .prereq(renameCommittedMaps); renameUndoneMaps .name(name() + ".renameUndoneMaps") .desc("Number of HB maps that are undone due to squashing") .prereq(renameUndoneMaps); renameValidUndoneMaps .name(name() + ".renameValidUndoneMaps") .desc("Number of HB maps that are undone, and are not place holders") .prereq(renameValidUndoneMaps);}template <class Impl>voidSimpleRename<Impl>::setCPU(FullCPU *cpu_ptr){ DPRINTF(Rename, "Rename: Setting CPU pointer.\n"); cpu = cpu_ptr;}template <class Impl>voidSimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr){ DPRINTF(Rename, "Rename: Setting time buffer pointer.\n"); timeBuffer = tb_ptr; // Setup wire to read information from time buffer, from IEW stage. fromIEW = timeBuffer->getWire(-iewToRenameDelay); // Setup wire to read infromation from time buffer, from commit stage. fromCommit = timeBuffer->getWire(-commitToRenameDelay); // Setup wire to write information to previous stages. toDecode = timeBuffer->getWire(0);}template <class Impl>voidSimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr){ DPRINTF(Rename, "Rename: Setting rename queue pointer.\n"); renameQueue = rq_ptr; // Setup wire to write information to future stages. toIEW = renameQueue->getWire(0);}template <class Impl>voidSimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr){ DPRINTF(Rename, "Rename: Setting decode queue pointer.\n"); decodeQueue = dq_ptr; // Setup wire to get information from decode. fromDecode = decodeQueue->getWire(-decodeToRenameDelay);}template <class Impl>voidSimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr){ DPRINTF(Rename, "Rename: Setting rename map pointer.\n"); renameMap = rm_ptr;}template <class Impl>voidSimpleRename<Impl>::setFreeList(FreeList *fl_ptr){ DPRINTF(Rename, "Rename: Setting free list pointer.\n"); freeList = fl_ptr;}template <class Impl>voidSimpleRename<Impl>::dumpHistory(){ typename list<RenameHistory>::iterator buf_it = historyBuffer.begin(); while (buf_it != historyBuffer.end()) { cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys " "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg, (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg); buf_it++; }}template <class Impl>voidSimpleRename<Impl>::block(){ DPRINTF(Rename, "Rename: Blocking.\n"); // Set status to Blocked. _status = Blocked; // Add the current inputs onto the skid buffer, so they can be // reprocessed when this stage unblocks. skidBuffer.push(*fromDecode); // Note that this stage only signals previous stages to stall when // it is the cause of the stall originates at this stage. Otherwise // the previous stages are expected to check all possible stall signals.}template <class Impl>inline voidSimpleRename<Impl>::unblock(){ DPRINTF(Rename, "Rename: Read instructions out of skid buffer this " "cycle.\n"); // Remove the now processed instructions from the skid buffer. skidBuffer.pop(); // If there's still information in the skid buffer, then // continue to tell previous stages to stall. They will be // able to restart once the skid buffer is empty. if (!skidBuffer.empty()) { toDecode->renameInfo.stall = true; } else { DPRINTF(Rename, "Rename: Done unblocking.\n"); _status = Running; }}template <class Impl>voidSimpleRename<Impl>::doSquash(){ typename list<RenameHistory>::iterator hb_it = historyBuffer.begin(); InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum;#if FULL_SYSTEM assert(!historyBuffer.empty());#else // After a syscall squashes everything, the history buffer may be empty // but the ROB may still be squashing instructions. if (historyBuffer.empty()) { return; }#endif // FULL_SYSTEM // Go through the most recent instructions, undoing the mappings // they did and freeing up the registers. while ((*hb_it).instSeqNum > squashed_seq_num) { assert(hb_it != historyBuffer.end()); DPRINTF(Rename, "Rename: Removing history entry with sequence " "number %i.\n", (*hb_it).instSeqNum); // If it's not simply a place holder, then add the registers. if (!(*hb_it).placeHolder) { // Tell the rename map to set the architected register to the // previous physical register that it was renamed to. renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg); // Put the renamed physical register back on the free list. freeList->addReg(hb_it->newPhysReg); ++renameValidUndoneMaps; } historyBuffer.erase(hb_it++); ++renameUndoneMaps; }}template <class Impl>voidSimpleRename<Impl>::squash(){ DPRINTF(Rename, "Rename: Squashing instructions.\n"); // Set the status to Squashing. _status = Squashing; numInst = 0; // Clear the skid buffer in case it has any data in it. while (!skidBuffer.empty()) { skidBuffer.pop(); } doSquash();}template<class Impl>voidSimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num){ DPRINTF(Rename, "Rename: Removing a committed instruction from the " "history buffer, until sequence number %lli.\n", inst_seq_num); typename list<RenameHistory>::iterator hb_it = historyBuffer.end(); --hb_it; if (hb_it->instSeqNum > inst_seq_num) { DPRINTF(Rename, "Rename: Old sequence number encountered. Ensure " "that a syscall happened recently.\n"); return; } while ((*hb_it).instSeqNum != inst_seq_num) { // Make sure we haven't gone off the end of the list. assert(hb_it != historyBuffer.end()); // In theory instructions at the end of the history buffer // should be older than the instruction being removed, which // means they will have a lower sequence number. Also the // instruction being removed from the history really should // be the last instruction in the list, as it is the instruction // that was just committed that is being removed. assert(hb_it->instSeqNum < inst_seq_num); DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence" " number %i.\n", (*hb_it).prevPhysReg, (*hb_it).instSeqNum); if (!(*hb_it).placeHolder) { freeList->addReg((*hb_it).prevPhysReg); ++renameCommittedMaps; } historyBuffer.erase(hb_it--); } // Finally free up the previous register of the finished instruction // itself. if (!(*hb_it).placeHolder) { freeList->addReg(hb_it->prevPhysReg); ++renameCommittedMaps; } historyBuffer.erase(hb_it); }template <class Impl>inline voidSimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst){ unsigned num_src_regs = inst->numSrcRegs(); // Get the architectual register numbers from the source and // destination operands, and redirect them to the right register. // Will need to mark dependencies though. for (int src_idx = 0; src_idx < num_src_regs; src_idx++) { RegIndex src_reg = inst->srcRegIdx(src_idx); // Look up the source registers to get the phys. register they've // been renamed to, and set the sources to those registers. PhysRegIndex renamed_reg = renameMap->lookup(src_reg); DPRINTF(Rename, "Rename: Looking up arch reg %i, got " "physical reg %i.\n", (int)src_reg, (int)renamed_reg); inst->renameSrcReg(src_idx, renamed_reg); // Either incorporate it into the info passed back, // or make another function call to see if that register is // ready or not. if (renameMap->isReady(renamed_reg)) { DPRINTF(Rename, "Rename: Register is ready.\n"); inst->markSrcRegReady(src_idx); } ++renameRenameLookups; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?