iew_impl.hh
来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 740 行 · 第 1/2 页
HH
740 行
/* * 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: Fix the instantaneous communication among all the stages within// iew. There's a clear delay between issue and execute, yet backwards// communication happens simultaneously.// Update the statuses for each stage.#include <queue>#include "base/timebuf.hh"#include "cpu/o3/iew.hh"template<class Impl>SimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, SimpleIEW<Impl> *_iew) : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew){ this->setFlags(Event::AutoDelete);}template<class Impl>voidSimpleIEW<Impl>::WritebackEvent::process(){ DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n"); // Need to insert instruction into queue to commit iewStage->instToCommit(inst); // Need to execute second half of the instruction, do actual writing to // registers and such inst->execute();}template<class Impl>const char *SimpleIEW<Impl>::WritebackEvent::description(){ return "LSQ writeback event";}template<class Impl>SimpleIEW<Impl>::SimpleIEW(Params ¶ms) : // Just make this time buffer really big for now issueToExecQueue(5, 5), instQueue(params), ldstQueue(params), commitToIEWDelay(params.commitToIEWDelay), renameToIEWDelay(params.renameToIEWDelay), issueToExecuteDelay(params.issueToExecuteDelay), issueReadWidth(params.issueWidth), issueWidth(params.issueWidth), executeWidth(params.executeWidth){ DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth); _status = Idle; _issueStatus = Idle; _exeStatus = Idle; _wbStatus = Idle; // Setup wire to read instructions coming from issue. fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); // Instruction queue needs the queue between issue and execute. instQueue.setIssueToExecuteQueue(&issueToExecQueue); ldstQueue.setIEW(this);}template <class Impl>voidSimpleIEW<Impl>::regStats(){ instQueue.regStats(); iewIdleCycles .name(name() + ".iewIdleCycles") .desc("Number of cycles IEW is idle"); iewSquashCycles .name(name() + ".iewSquashCycles") .desc("Number of cycles IEW is squashing"); iewBlockCycles .name(name() + ".iewBlockCycles") .desc("Number of cycles IEW is blocking"); iewUnblockCycles .name(name() + ".iewUnblockCycles") .desc("Number of cycles IEW is unblocking");// iewWBInsts; iewDispatchedInsts .name(name() + ".iewDispatchedInsts") .desc("Number of instructions dispatched to IQ"); iewDispSquashedInsts .name(name() + ".iewDispSquashedInsts") .desc("Number of squashed instructions skipped by dispatch"); iewDispLoadInsts .name(name() + ".iewDispLoadInsts") .desc("Number of dispatched load instructions"); iewDispStoreInsts .name(name() + ".iewDispStoreInsts") .desc("Number of dispatched store instructions"); iewDispNonSpecInsts .name(name() + ".iewDispNonSpecInsts") .desc("Number of dispatched non-speculative instructions"); iewIQFullEvents .name(name() + ".iewIQFullEvents") .desc("Number of times the IQ has become full, causing a stall"); iewExecutedInsts .name(name() + ".iewExecutedInsts") .desc("Number of executed instructions"); iewExecLoadInsts .name(name() + ".iewExecLoadInsts") .desc("Number of load instructions executed"); iewExecStoreInsts .name(name() + ".iewExecStoreInsts") .desc("Number of store instructions executed"); iewExecSquashedInsts .name(name() + ".iewExecSquashedInsts") .desc("Number of squashed instructions skipped in execute"); memOrderViolationEvents .name(name() + ".memOrderViolationEvents") .desc("Number of memory order violations"); predictedTakenIncorrect .name(name() + ".predictedTakenIncorrect") .desc("Number of branches that were predicted taken incorrectly");}template<class Impl>voidSimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr){ DPRINTF(IEW, "IEW: Setting CPU pointer.\n"); cpu = cpu_ptr; instQueue.setCPU(cpu_ptr); ldstQueue.setCPU(cpu_ptr);}template<class Impl>voidSimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr){ DPRINTF(IEW, "IEW: Setting time buffer pointer.\n"); timeBuffer = tb_ptr; // Setup wire to read information from time buffer, from commit. fromCommit = timeBuffer->getWire(-commitToIEWDelay); // Setup wire to write information back to previous stages. toRename = timeBuffer->getWire(0); // Instruction queue also needs main time buffer. instQueue.setTimeBuffer(tb_ptr);}template<class Impl>voidSimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr){ DPRINTF(IEW, "IEW: Setting rename queue pointer.\n"); renameQueue = rq_ptr; // Setup wire to read information from rename queue. fromRename = renameQueue->getWire(-renameToIEWDelay);}template<class Impl>voidSimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr){ DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n"); iewQueue = iq_ptr; // Setup wire to write instructions to commit. toCommit = iewQueue->getWire(0);}template<class Impl>voidSimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr){ DPRINTF(IEW, "IEW: Setting rename map pointer.\n"); renameMap = rm_ptr;}template<class Impl>voidSimpleIEW<Impl>::squash(){ DPRINTF(IEW, "IEW: Squashing all instructions.\n"); _status = Squashing; // Tell the IQ to start squashing. instQueue.squash(); // Tell the LDSTQ to start squashing. ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);}template<class Impl>voidSimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst){ DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", inst->PC); // Perhaps leave the squashing up to the ROB stage to tell it when to // squash? _status = Squashing; // Tell rename to squash through the time buffer. toCommit->squash = true; // Also send PC update information back to prior stages. toCommit->squashedSeqNum = inst->seqNum; toCommit->mispredPC = inst->readPC(); toCommit->nextPC = inst->readNextPC(); toCommit->branchMispredict = true; // Prediction was incorrect, so send back inverse. toCommit->branchTaken = inst->readNextPC() != (inst->readPC() + sizeof(MachInst));}template<class Impl>voidSimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst){ DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", inst->PC); // Perhaps leave the squashing up to the ROB stage to tell it when to // squash? _status = Squashing; // Tell rename to squash through the time buffer. toCommit->squash = true; // Also send PC update information back to prior stages. toCommit->squashedSeqNum = inst->seqNum; toCommit->nextPC = inst->readNextPC();}template<class Impl>voidSimpleIEW<Impl>::block(){ DPRINTF(IEW, "IEW: Blocking.\n"); // Set the status to Blocked. _status = Blocked; // Add the current inputs to the skid buffer so they can be // reprocessed when this stage unblocks. skidBuffer.push(*fromRename); // 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 voidSimpleIEW<Impl>::unblock(){ // Check if there's information in the skid buffer. If there is, then // set status to unblocking, otherwise set it directly to running. DPRINTF(IEW, "IEW: Reading instructions out of the skid " "buffer.\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()) { toRename->iewInfo.stall = true; } else { DPRINTF(IEW, "IEW: Stage is done unblocking.\n"); _status = Running; }}template<class Impl>voidSimpleIEW<Impl>::wakeDependents(DynInstPtr &inst){ instQueue.wakeDependents(inst);}template<class Impl>voidSimpleIEW<Impl>::instToCommit(DynInstPtr &inst){ }template <class Impl>voidSimpleIEW<Impl>::dispatchInsts(){ //////////////////////////////////////// // DISPATCH/ISSUE stage //////////////////////////////////////// //Put into its own function? //Add instructions to IQ if there are any instructions there // Check if there are any instructions coming from rename, and we're. // not squashing. if (fromRename->size > 0) { int insts_to_add = fromRename->size; // Loop through the instructions, putting them in the instruction // queue. for (int inst_num = 0; inst_num < insts_to_add; ++inst_num) { DynInstPtr inst = fromRename->insts[inst_num]; // Make sure there's a valid instruction there. assert(inst); DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n", inst->readPC()); // Be sure to mark these instructions as ready so that the // commit stage can go ahead and execute them, and mark // them as issued so the IQ doesn't reprocess them. if (inst->isSquashed()) { ++iewDispSquashedInsts; continue; } else if (instQueue.isFull()) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?