mem_dep_unit_impl.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 584 行 · 第 1/2 页
HH
584 行
/* * 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 */#include <map>#include "cpu/o3/inst_queue.hh"#include "cpu/o3/mem_dep_unit.hh"template <class MemDepPred, class Impl>MemDepUnit<MemDepPred, Impl>::MemDepUnit() : loadBarrier(false), loadBarrierSN(0), storeBarrier(false), storeBarrierSN(0), iqPtr(NULL){}template <class MemDepPred, class Impl>MemDepUnit<MemDepPred, Impl>::MemDepUnit(Params *params) : depPred(params->SSITSize, params->LFSTSize), loadBarrier(false), loadBarrierSN(0), storeBarrier(false), storeBarrierSN(0), iqPtr(NULL){ DPRINTF(MemDepUnit, "Creating MemDepUnit object.\n");}template <class MemDepPred, class Impl>MemDepUnit<MemDepPred, Impl>::~MemDepUnit(){ for (int tid=0; tid < Impl::MaxThreads; tid++) { ListIt inst_list_it = instList[tid].begin(); MemDepHashIt hash_it; while (!instList[tid].empty()) { hash_it = memDepHash.find((*inst_list_it)->seqNum); assert(hash_it != memDepHash.end()); memDepHash.erase(hash_it); instList[tid].erase(inst_list_it++); } }#ifdef DEBUG assert(MemDepEntry::memdep_count == 0);#endif}template <class MemDepPred, class Impl>std::stringMemDepUnit<MemDepPred, Impl>::name() const{ return "memdepunit";}template <class MemDepPred, class Impl>voidMemDepUnit<MemDepPred, Impl>::init(Params *params, int tid){ DPRINTF(MemDepUnit, "Creating MemDepUnit %i object.\n",tid); id = tid; depPred.init(params->SSITSize, params->LFSTSize);}template <class MemDepPred, class Impl>voidMemDepUnit<MemDepPred, Impl>::regStats(){ insertedLoads .name(name() + ".memDep.insertedLoads") .desc("Number of loads inserted to the mem dependence unit."); insertedStores .name(name() + ".memDep.insertedStores") .desc("Number of stores inserted to the mem dependence unit."); conflictingLoads .name(name() + ".memDep.conflictingLoads") .desc("Number of conflicting loads."); conflictingStores .name(name() + ".memDep.conflictingStores") .desc("Number of conflicting stores.");}template <class MemDepPred, class Impl>voidMemDepUnit<MemDepPred, Impl>::switchOut(){ assert(instList[0].empty()); assert(instsToReplay.empty()); assert(memDepHash.empty()); // Clear any state. for (int i = 0; i < Impl::MaxThreads; ++i) { instList[i].clear(); } instsToReplay.clear(); memDepHash.clear();}template <class MemDepPred, class Impl>voidMemDepUnit<MemDepPred, Impl>::takeOverFrom(){ // Be sure to reset all state. loadBarrier = storeBarrier = false; loadBarrierSN = storeBarrierSN = 0; depPred.clear();}template <class MemDepPred, class Impl>voidMemDepUnit<MemDepPred, Impl>::setIQ(InstructionQueue<Impl> *iq_ptr){ iqPtr = iq_ptr;}template <class MemDepPred, class Impl>voidMemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst){ unsigned tid = inst->threadNumber; MemDepEntryPtr inst_entry = new MemDepEntry(inst); // Add the MemDepEntry to the hash. memDepHash.insert( std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));#ifdef DEBUG MemDepEntry::memdep_insert++;#endif instList[tid].push_back(inst); inst_entry->listIt = --(instList[tid].end()); // Check any barriers and the dependence predictor for any // producing memrefs/stores. InstSeqNum producing_store; if (inst->isLoad() && loadBarrier) { DPRINTF(MemDepUnit, "Load barrier [sn:%lli] in flight\n", loadBarrierSN); producing_store = loadBarrierSN; } else if (inst->isStore() && storeBarrier) { DPRINTF(MemDepUnit, "Store barrier [sn:%lli] in flight\n", storeBarrierSN); producing_store = storeBarrierSN; } else { producing_store = depPred.checkInst(inst->readPC()); } MemDepEntryPtr store_entry = NULL; // If there is a producing store, try to find the entry. if (producing_store != 0) { DPRINTF(MemDepUnit, "Searching for producer\n"); MemDepHashIt hash_it = memDepHash.find(producing_store); if (hash_it != memDepHash.end()) { store_entry = (*hash_it).second; DPRINTF(MemDepUnit, "Proucer found\n"); } } // If no store entry, then instruction can issue as soon as the registers // are ready. if (!store_entry) { DPRINTF(MemDepUnit, "No dependency for inst PC " "%#x [sn:%lli].\n", inst->readPC(), inst->seqNum); inst_entry->memDepReady = true; if (inst->readyToIssue()) { inst_entry->regsReady = true; moveToReady(inst_entry); } } else { // Otherwise make the instruction dependent on the store/barrier. DPRINTF(MemDepUnit, "Adding to dependency list; " "inst PC %#x is dependent on [sn:%lli].\n", inst->readPC(), producing_store); if (inst->readyToIssue()) { inst_entry->regsReady = true; } // Clear the bit saying this instruction can issue. inst->clearCanIssue(); // Add this instruction to the list of dependents. store_entry->dependInsts.push_back(inst_entry); if (inst->isLoad()) { ++conflictingLoads; } else { ++conflictingStores; } } if (inst->isStore()) { DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n", inst->readPC(), inst->seqNum); depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber); ++insertedStores; } else if (inst->isLoad()) { ++insertedLoads; } else { panic("Unknown type! (most likely a barrier)."); }}template <class MemDepPred, class Impl>voidMemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst){ unsigned tid = inst->threadNumber; MemDepEntryPtr inst_entry = new MemDepEntry(inst); // Insert the MemDepEntry into the hash. memDepHash.insert( std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));#ifdef DEBUG MemDepEntry::memdep_insert++;#endif // Add the instruction to the list. instList[tid].push_back(inst); inst_entry->listIt = --(instList[tid].end()); // Might want to turn this part into an inline function or something. // It's shared between both insert functions. if (inst->isStore()) { DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n", inst->readPC(), inst->seqNum); depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber); ++insertedStores; } else if (inst->isLoad()) { ++insertedLoads; } else { panic("Unknown type! (most likely a barrier)."); }}template <class MemDepPred, class Impl>voidMemDepUnit<MemDepPred, Impl>::insertBarrier(DynInstPtr &barr_inst){ InstSeqNum barr_sn = barr_inst->seqNum; // Memory barriers block loads and stores, write barriers only stores. if (barr_inst->isMemBarrier()) { loadBarrier = true; loadBarrierSN = barr_sn; storeBarrier = true; storeBarrierSN = barr_sn; DPRINTF(MemDepUnit, "Inserted a memory barrier\n"); } else if (barr_inst->isWriteBarrier()) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?