rename_impl.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 1,362 行 · 第 1/3 页
HH
1,362 行
/* * 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 <list>#include "arch/isa_traits.hh"#include "arch/regfile.hh"#include "config/full_system.hh"#include "cpu/o3/rename.hh"template <class Impl>DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, Params *params) : cpu(_cpu), iewToRenameDelay(params->iewToRenameDelay), decodeToRenameDelay(params->decodeToRenameDelay), commitToRenameDelay(params->commitToRenameDelay), renameWidth(params->renameWidth), commitWidth(params->commitWidth), resumeSerialize(false), resumeUnblocking(false), numThreads(params->numberOfThreads), maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs){ _status = Inactive; for (int i=0; i< numThreads; i++) { renameStatus[i] = Idle; freeEntries[i].iqEntries = 0; freeEntries[i].lsqEntries = 0; freeEntries[i].robEntries = 0; stalls[i].iew = false; stalls[i].commit = false; serializeInst[i] = NULL; instsInProgress[i] = 0; emptyROB[i] = true; serializeOnNextInst[i] = false; } // @todo: Make into a parameter. skidBufferMax = (2 * (iewToRenameDelay * params->decodeWidth)) + renameWidth;}template <class Impl>std::stringDefaultRename<Impl>::name() const{ return cpu->name() + ".rename";}template <class Impl>voidDefaultRename<Impl>::regStats(){ renameSquashCycles .name(name() + ".RENAME:SquashCycles") .desc("Number of cycles rename is squashing") .prereq(renameSquashCycles); renameIdleCycles .name(name() + ".RENAME:IdleCycles") .desc("Number of cycles rename is idle") .prereq(renameIdleCycles); renameBlockCycles .name(name() + ".RENAME:BlockCycles") .desc("Number of cycles rename is blocking") .prereq(renameBlockCycles); renameSerializeStallCycles .name(name() + ".RENAME:serializeStallCycles") .desc("count of cycles rename stalled for serializing inst") .flags(Stats::total); renameRunCycles .name(name() + ".RENAME:RunCycles") .desc("Number of cycles rename is running") .prereq(renameIdleCycles); renameUnblockCycles .name(name() + ".RENAME:UnblockCycles") .desc("Number of cycles rename is unblocking") .prereq(renameUnblockCycles); renameRenamedInsts .name(name() + ".RENAME:RenamedInsts") .desc("Number of instructions processed by rename") .prereq(renameRenamedInsts); renameSquashedInsts .name(name() + ".RENAME:SquashedInsts") .desc("Number of squashed instructions processed by rename") .prereq(renameSquashedInsts); renameROBFullEvents .name(name() + ".RENAME:ROBFullEvents") .desc("Number of times rename has blocked due to ROB full") .prereq(renameROBFullEvents); renameIQFullEvents .name(name() + ".RENAME:IQFullEvents") .desc("Number of times rename has blocked due to IQ full") .prereq(renameIQFullEvents); renameLSQFullEvents .name(name() + ".RENAME:LSQFullEvents") .desc("Number of times rename has blocked due to LSQ full") .prereq(renameLSQFullEvents); renameFullRegistersEvents .name(name() + ".RENAME:FullRegisterEvents") .desc("Number of times there has been no free registers") .prereq(renameFullRegistersEvents); renameRenamedOperands .name(name() + ".RENAME:RenamedOperands") .desc("Number of destination operands rename has renamed") .prereq(renameRenamedOperands); renameRenameLookups .name(name() + ".RENAME:RenameLookups") .desc("Number of register rename lookups that rename has made") .prereq(renameRenameLookups); renameCommittedMaps .name(name() + ".RENAME:CommittedMaps") .desc("Number of HB maps that are committed") .prereq(renameCommittedMaps); renameUndoneMaps .name(name() + ".RENAME:UndoneMaps") .desc("Number of HB maps that are undone due to squashing") .prereq(renameUndoneMaps); renamedSerializing .name(name() + ".RENAME:serializingInsts") .desc("count of serializing insts renamed") .flags(Stats::total) ; renamedTempSerializing .name(name() + ".RENAME:tempSerializingInsts") .desc("count of temporary serializing insts renamed") .flags(Stats::total) ; renameSkidInsts .name(name() + ".RENAME:skidInsts") .desc("count of insts added to the skid buffer") .flags(Stats::total) ;}template <class Impl>voidDefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr){ 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>voidDefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr){ renameQueue = rq_ptr; // Setup wire to write information to future stages. toIEW = renameQueue->getWire(0);}template <class Impl>voidDefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr){ decodeQueue = dq_ptr; // Setup wire to get information from decode. fromDecode = decodeQueue->getWire(-decodeToRenameDelay);}template <class Impl>voidDefaultRename<Impl>::initStage(){ // Grab the number of free entries directly from the stages. for (int tid=0; tid < numThreads; tid++) { freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid); freeEntries[tid].lsqEntries = iew_ptr->ldstQueue.numFreeEntries(tid); freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid); emptyROB[tid] = true; }}template<class Impl>voidDefaultRename<Impl>::setActiveThreads(std::list<unsigned> *at_ptr){ activeThreads = at_ptr;}template <class Impl>voidDefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[]){ for (int i=0; i<numThreads; i++) { renameMap[i] = &rm_ptr[i]; }}template <class Impl>voidDefaultRename<Impl>::setFreeList(FreeList *fl_ptr){ freeList = fl_ptr;}template<class Impl>voidDefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard){ scoreboard = _scoreboard;}template <class Impl>boolDefaultRename<Impl>::drain(){ // Rename is ready to switch out at any time. cpu->signalDrained(); return true;}template <class Impl>voidDefaultRename<Impl>::switchOut(){ // Clear any state, fix up the rename map. for (int i = 0; i < numThreads; i++) { typename std::list<RenameHistory>::iterator hb_it = historyBuffer[i].begin(); while (!historyBuffer[i].empty()) { assert(hb_it != historyBuffer[i].end()); DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence " "number %i.\n", i, (*hb_it).instSeqNum); // Tell the rename map to set the architected register to the // previous physical register that it was renamed to. renameMap[i]->setEntry(hb_it->archReg, hb_it->prevPhysReg); // Put the renamed physical register back on the free list. freeList->addReg(hb_it->newPhysReg); // Be sure to mark its register as ready if it's a misc register. if (hb_it->newPhysReg >= maxPhysicalRegs) { scoreboard->setReg(hb_it->newPhysReg); } historyBuffer[i].erase(hb_it++); } insts[i].clear(); skidBuffer[i].clear(); }}template <class Impl>voidDefaultRename<Impl>::takeOverFrom(){ _status = Inactive; initStage(); // Reset all state prior to taking over from the other CPU. for (int i=0; i< numThreads; i++) { renameStatus[i] = Idle; stalls[i].iew = false; stalls[i].commit = false; serializeInst[i] = NULL; instsInProgress[i] = 0; emptyROB[i] = true; serializeOnNextInst[i] = false; }}template <class Impl>voidDefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, unsigned tid){ DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid); // Clear the stall signal if rename was blocked or unblocking before. // If it still needs to block, the blocking should happen the next // cycle and there should be space to hold everything due to the squash. if (renameStatus[tid] == Blocked || renameStatus[tid] == Unblocking) { toDecode->renameUnblock[tid] = 1; resumeSerialize = false; serializeInst[tid] = NULL; } else if (renameStatus[tid] == SerializeStall) { if (serializeInst[tid]->seqNum <= squash_seq_num) { DPRINTF(Rename, "Rename will resume serializing after squash\n"); resumeSerialize = true; assert(serializeInst[tid]); } else { resumeSerialize = false; toDecode->renameUnblock[tid] = 1; serializeInst[tid] = NULL; } } // Set the status to Squashing. renameStatus[tid] = Squashing; // Squash any instructions from decode. unsigned squashCount = 0; for (int i=0; i<fromDecode->size; i++) { if (fromDecode->insts[i]->threadNumber == tid && fromDecode->insts[i]->seqNum > squash_seq_num) { fromDecode->insts[i]->setSquashed(); wroteToTimeBuffer = true; squashCount++; } } // Clear the instruction list and skid buffer in case they have any // insts in them. insts[tid].clear(); // Clear the skid buffer in case it has any data in it. skidBuffer[tid].clear(); doSquash(squash_seq_num, tid);}template <class Impl>voidDefaultRename<Impl>::tick(){ wroteToTimeBuffer = false; blockThisCycle = false; bool status_change = false; toIEWIndex = 0; sortInsts(); std::list<unsigned>::iterator threads = activeThreads->begin(); std::list<unsigned>::iterator end = activeThreads->end(); // Check stall and squash signals. while (threads != end) { unsigned tid = *threads++; DPRINTF(Rename, "Processing [tid:%i]\n", tid); status_change = checkSignalsAndUpdate(tid) || status_change; rename(status_change, tid); } if (status_change) { updateStatus(); } if (wroteToTimeBuffer) { DPRINTF(Activity, "Activity this cycle.\n"); cpu->activityThisCycle(); } threads = activeThreads->begin(); while (threads != end) { unsigned tid = *threads++; // If we committed this cycle then doneSeqNum will be > 0 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && !fromCommit->commitInfo[tid].squash && renameStatus[tid] != Squashing) { removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum, tid); } } // @todo: make into updateProgress function for (int tid=0; tid < numThreads; tid++) { instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched; assert(instsInProgress[tid] >=0); }}template<class Impl>voidDefaultRename<Impl>::rename(bool &status_change, unsigned tid){ // If status is Running or idle, // call renameInsts() // If status is Unblocking, // buffer any instructions coming from decode // continue trying to empty skid buffer // check if stall conditions have passed if (renameStatus[tid] == Blocked) { ++renameBlockCycles; } else if (renameStatus[tid] == Squashing) { ++renameSquashCycles; } else if (renameStatus[tid] == SerializeStall) { ++renameSerializeStallCycles; // If we are currently in SerializeStall and resumeSerialize // was set, then that means that we are resuming serializing // this cycle. Tell the previous stages to block. if (resumeSerialize) { resumeSerialize = false; block(tid); toDecode->renameUnblock[tid] = false; } } else if (renameStatus[tid] == Unblocking) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?