diff options
-rwxr-xr-x | src/cpu/o3/SConscript | 1 | ||||
-rw-r--r-- | src/cpu/o3/cpu.cc | 86 | ||||
-rw-r--r-- | src/cpu/o3/cpu.hh | 3 | ||||
-rw-r--r-- | src/cpu/o3/cpu_policy.hh | 9 | ||||
-rw-r--r-- | src/cpu/o3/free_list.cc | 41 | ||||
-rw-r--r-- | src/cpu/o3/free_list.hh | 176 | ||||
-rw-r--r-- | src/cpu/o3/regfile.cc | 64 | ||||
-rw-r--r-- | src/cpu/o3/regfile.hh | 38 | ||||
-rw-r--r-- | src/cpu/o3/rename_impl.hh | 135 | ||||
-rw-r--r-- | src/cpu/o3/rename_map.cc | 272 | ||||
-rw-r--r-- | src/cpu/o3/rename_map.hh | 302 |
11 files changed, 593 insertions, 534 deletions
diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript index 50b5a8ea4..b8f14cc25 100755 --- a/src/cpu/o3/SConscript +++ b/src/cpu/o3/SConscript @@ -56,6 +56,7 @@ if 'O3CPU' in env['CPU_MODELS']: Source('lsq.cc') Source('lsq_unit.cc') Source('mem_dep_unit.cc') + Source('regfile.cc') Source('rename.cc') Source('rename_map.cc') Source('rob.cc') diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 496961380..3e33e139a 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -227,9 +227,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) regFile(params->numPhysIntRegs, params->numPhysFloatRegs), - freeList(params->numThreads, - TheISA::NumIntRegs, params->numPhysIntRegs, - TheISA::NumFloatRegs, params->numPhysFloatRegs), + freeList(name() + ".freelist", ®File), rob(this, params->numROBEntries, params->squashWidth, @@ -334,56 +332,46 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) iew.setScoreboard(&scoreboard); // Setup the rename map for whichever stages need it. - PhysRegIndex lreg_idx = 0; - PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs - for (ThreadID tid = 0; tid < numThreads; tid++) { - bool bindRegs = (tid <= active_threads - 1); - isa[tid] = params->isa[tid]; - commitRenameMap[tid].init(TheISA::NumIntRegs, - params->numPhysIntRegs, - lreg_idx, //Index for Logical. Regs - - TheISA::NumFloatRegs, - params->numPhysFloatRegs, - freg_idx, //Index for Float Regs - - TheISA::NumMiscRegs, - - TheISA::ZeroReg, - TheISA::ZeroReg, - - tid, - false); - - renameMap[tid].init(TheISA::NumIntRegs, - params->numPhysIntRegs, - lreg_idx, //Index for Logical. Regs - - TheISA::NumFloatRegs, - params->numPhysFloatRegs, - freg_idx, //Index for Float Regs - - TheISA::NumMiscRegs, + // Only Alpha has an FP zero register, so for other ISAs we + // use an invalid FP register index to avoid special treatment + // of any valid FP reg. + RegIndex invalidFPReg = TheISA::NumFloatRegs + 1; + RegIndex fpZeroReg = + (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg; - TheISA::ZeroReg, - TheISA::ZeroReg, + commitRenameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, + &freeList); - tid, - bindRegs); + renameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, + &freeList); activateThreadEvent[tid].init(tid, this); deallocateContextEvent[tid].init(tid, this); } + // Initialize rename map to assign physical registers to the + // architectural registers for active threads only. + for (ThreadID tid = 0; tid < active_threads; tid++) { + for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) { + // Note that we can't use the rename() method because we don't + // want special treatment for the zero register at this point + PhysRegIndex phys_reg = freeList.getIntReg(); + renameMap[tid].setIntEntry(ridx, phys_reg); + commitRenameMap[tid].setIntEntry(ridx, phys_reg); + } + + for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) { + PhysRegIndex phys_reg = freeList.getFloatReg(); + renameMap[tid].setFloatEntry(ridx, phys_reg); + commitRenameMap[tid].setFloatEntry(ridx, phys_reg); + } + } + rename.setRenameMap(renameMap); commit.setRenameMap(commitRenameMap); - - // Give renameMap & rename stage access to the freeList; - for (ThreadID tid = 0; tid < numThreads; tid++) - renameMap[tid].setFreeList(&freeList); rename.setFreeList(&freeList); // Setup the ROB for whichever stages need it. @@ -1406,7 +1394,7 @@ uint64_t FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid) { intRegfileReads++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); + PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); return regFile.readIntReg(phys_reg); } @@ -1416,8 +1404,7 @@ float FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid) { fpRegfileReads++; - int idx = reg_idx + TheISA::NumIntRegs; - PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); + PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); return regFile.readFloatReg(phys_reg); } @@ -1427,8 +1414,7 @@ uint64_t FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid) { fpRegfileReads++; - int idx = reg_idx + TheISA::NumIntRegs; - PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); + PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); return regFile.readFloatRegBits(phys_reg); } @@ -1438,7 +1424,7 @@ void FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) { intRegfileWrites++; - PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); + PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); regFile.setIntReg(phys_reg, val); } @@ -1448,8 +1434,7 @@ void FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid) { fpRegfileWrites++; - int idx = reg_idx + TheISA::NumIntRegs; - PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); + PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); regFile.setFloatReg(phys_reg, val); } @@ -1459,8 +1444,7 @@ void FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) { fpRegfileWrites++; - int idx = reg_idx + TheISA::NumIntRegs; - PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); + PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); regFile.setFloatRegBits(phys_reg, val); } diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 98a6972e9..1a1f8f8a3 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2013 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -655,7 +656,7 @@ class FullO3CPU : public BaseO3CPU typename CPUPolicy::Commit commit; /** The register file. */ - typename CPUPolicy::RegFile regFile; + PhysRegFile regFile; /** The free list. */ typename CPUPolicy::FreeList freeList; diff --git a/src/cpu/o3/cpu_policy.hh b/src/cpu/o3/cpu_policy.hh index a48059202..6db532ade 100644 --- a/src/cpu/o3/cpu_policy.hh +++ b/src/cpu/o3/cpu_policy.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,14 +60,10 @@ template<class Impl> struct SimpleCPUPolicy { - /** Typedef for the register file. Most classes assume a unified - * physical register file. - */ - typedef PhysRegFile RegFile; /** Typedef for the freelist of registers. */ - typedef SimpleFreeList FreeList; + typedef UnifiedFreeList FreeList; /** Typedef for the rename map. */ - typedef SimpleRenameMap RenameMap; + typedef UnifiedRenameMap RenameMap; /** Typedef for the ROB. */ typedef ::ROB<Impl> ROB; /** Typedef for the instruction queue/scheduler. */ diff --git a/src/cpu/o3/free_list.cc b/src/cpu/o3/free_list.cc index 4224d0e41..0c8a16d0d 100644 --- a/src/cpu/o3/free_list.cc +++ b/src/cpu/o3/free_list.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,41 +33,13 @@ #include "cpu/o3/free_list.hh" #include "debug/FreeList.hh" -SimpleFreeList::SimpleFreeList(ThreadID activeThreads, - unsigned _numLogicalIntRegs, - unsigned _numPhysicalIntRegs, - unsigned _numLogicalFloatRegs, - unsigned _numPhysicalFloatRegs) - : numLogicalIntRegs(_numLogicalIntRegs), - numPhysicalIntRegs(_numPhysicalIntRegs), - numLogicalFloatRegs(_numLogicalFloatRegs), - numPhysicalFloatRegs(_numPhysicalFloatRegs), - numPhysicalRegs(numPhysicalIntRegs + numPhysicalFloatRegs) +UnifiedFreeList::UnifiedFreeList(const std::string &_my_name, + PhysRegFile *_regFile) + : _name(_my_name), regFile(_regFile) { DPRINTF(FreeList, "Creating new free list object.\n"); - // Put all of the extra physical registers onto the free list. This - // means excluding all of the base logical registers. - for (PhysRegIndex i = numLogicalIntRegs * activeThreads; - i < numPhysicalIntRegs; ++i) - { - freeIntRegs.push(i); - } - - // Put all of the extra physical registers onto the free list. This - // means excluding all of the base logical registers. Because the - // float registers' indices start where the physical registers end, - // some math must be done to determine where the free registers start. - PhysRegIndex i = numPhysicalIntRegs + (numLogicalFloatRegs * activeThreads); - - for ( ; i < numPhysicalRegs; ++i) - { - freeFloatRegs.push(i); - } -} - -std::string -SimpleFreeList::name() const -{ - return "cpu.freelist"; + // Have the register file initialize the free list since it knows + // about its internal organization + regFile->initFreeList(this); } diff --git a/src/cpu/o3/free_list.hh b/src/cpu/o3/free_list.hh index fec076097..3919d0afb 100644 --- a/src/cpu/o3/free_list.hh +++ b/src/cpu/o3/free_list.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +35,51 @@ #include <iostream> #include <queue> -#include "arch/registers.hh" #include "base/misc.hh" #include "base/trace.hh" -#include "config/the_isa.hh" #include "cpu/o3/comm.hh" +#include "cpu/o3/regfile.hh" #include "debug/FreeList.hh" /** + * Free list for a single class of registers (e.g., integer + * or floating point). Because the register class is implicitly + * determined by the rename map instance being accessed, all + * architectural register index parameters and values in this class + * are relative (e.g., %fp2 is just index 2). + */ +class SimpleFreeList +{ + private: + + /** The actual free list */ + std::queue<PhysRegIndex> freeRegs; + + public: + + SimpleFreeList() {}; + + /** Add a physical register to the free list */ + void addReg(PhysRegIndex reg) { freeRegs.push(reg); } + + /** Get the next available register from the free list */ + PhysRegIndex getReg() + { + assert(!freeRegs.empty()); + PhysRegIndex free_reg = freeRegs.front(); + freeRegs.pop(); + return free_reg; + } + + /** Return the number of free registers on the list. */ + unsigned numFreeRegs() const { return freeRegs.size(); } + + /** True iff there are free registers on the list. */ + bool hasFreeRegs() const { return !freeRegs.empty(); } +}; + + +/** * FreeList class that simply holds the list of free integer and floating * point registers. Can request for a free register of either type, and * also send back free registers of either type. This is a very simple @@ -54,125 +92,86 @@ * class can be named simply "FreeList". * @todo: Give a better name to the base FP dependency. */ -class SimpleFreeList +class UnifiedFreeList { private: - /** The list of free integer registers. */ - std::queue<PhysRegIndex> freeIntRegs; - /** The list of free floating point registers. */ - std::queue<PhysRegIndex> freeFloatRegs; - - /** Number of logical integer registers. */ - int numLogicalIntRegs; + /** The object name, for DPRINTF. We have to declare this + * explicitly because Scoreboard is not a SimObject. */ + const std::string _name; - /** Number of physical integer registers. */ - int numPhysicalIntRegs; + /** The list of free integer registers. */ + SimpleFreeList intList; - /** Number of logical floating point registers. */ - int numLogicalFloatRegs; + /** The list of free floating point registers. */ + SimpleFreeList floatList; - /** Number of physical floating point registers. */ - int numPhysicalFloatRegs; + /** + * The register file object is used only to distinguish integer + * from floating-point physical register indices. + */ + PhysRegFile *regFile; - /** Total number of physical registers. */ - int numPhysicalRegs; + /* + * We give UnifiedRenameMap internal access so it can get at the + * internal per-class free lists and associate those with its + * per-class rename maps. See UnifiedRenameMap::init(). + */ + friend class UnifiedRenameMap; public: /** Constructs a free list. - * @param activeThreads Number of active threads. - * @param _numLogicalIntRegs Number of logical integer registers. * @param _numPhysicalIntRegs Number of physical integer registers. - * @param _numLogicalFloatRegs Number of logical fp registers. + * @param reservedIntRegs Number of integer registers already + * used by initial mappings. * @param _numPhysicalFloatRegs Number of physical fp registers. + * @param reservedFloatRegs Number of fp registers already + * used by initial mappings. */ - SimpleFreeList(ThreadID activeThreads, - unsigned _numLogicalIntRegs, - unsigned _numPhysicalIntRegs, - unsigned _numLogicalFloatRegs, - unsigned _numPhysicalFloatRegs); + UnifiedFreeList(const std::string &_my_name, PhysRegFile *_regFile); /** Gives the name of the freelist. */ - std::string name() const; + std::string name() const { return _name; }; /** Gets a free integer register. */ - inline PhysRegIndex getIntReg(); + PhysRegIndex getIntReg() { return intList.getReg(); } /** Gets a free fp register. */ - inline PhysRegIndex getFloatReg(); + PhysRegIndex getFloatReg() { return floatList.getReg(); } /** Adds a register back to the free list. */ - inline void addReg(PhysRegIndex freed_reg); + void addReg(PhysRegIndex freed_reg); /** Adds an integer register back to the free list. */ - inline void addIntReg(PhysRegIndex freed_reg); + void addIntReg(PhysRegIndex freed_reg) { intList.addReg(freed_reg); } /** Adds a fp register back to the free list. */ - inline void addFloatReg(PhysRegIndex freed_reg); + void addFloatReg(PhysRegIndex freed_reg) { floatList.addReg(freed_reg); } /** Checks if there are any free integer registers. */ - bool hasFreeIntRegs() - { return !freeIntRegs.empty(); } + bool hasFreeIntRegs() const { return intList.hasFreeRegs(); } /** Checks if there are any free fp registers. */ - bool hasFreeFloatRegs() - { return !freeFloatRegs.empty(); } + bool hasFreeFloatRegs() const { return floatList.hasFreeRegs(); } /** Returns the number of free integer registers. */ - int numFreeIntRegs() - { return freeIntRegs.size(); } + unsigned numFreeIntRegs() const { return intList.numFreeRegs(); } /** Returns the number of free fp registers. */ - int numFreeFloatRegs() - { return freeFloatRegs.size(); } + unsigned numFreeFloatRegs() const { return floatList.numFreeRegs(); } }; -inline PhysRegIndex -SimpleFreeList::getIntReg() -{ - DPRINTF(FreeList, "Trying to get free integer register.\n"); - - if (freeIntRegs.empty()) { - panic("No free integer registers!"); - } - - PhysRegIndex free_reg = freeIntRegs.front(); - - freeIntRegs.pop(); - - return(free_reg); -} - -inline PhysRegIndex -SimpleFreeList::getFloatReg() -{ - DPRINTF(FreeList, "Trying to get free float register.\n"); - - if (freeFloatRegs.empty()) { - panic("No free integer registers!"); - } - - PhysRegIndex free_reg = freeFloatRegs.front(); - - freeFloatRegs.pop(); - - return(free_reg); -} - inline void -SimpleFreeList::addReg(PhysRegIndex freed_reg) +UnifiedFreeList::addReg(PhysRegIndex freed_reg) { DPRINTF(FreeList,"Freeing register %i.\n", freed_reg); //Might want to add in a check for whether or not this register is //already in there. A bit vector or something similar would be useful. - if (freed_reg < numPhysicalIntRegs) { - if (freed_reg != TheISA::ZeroReg) - freeIntRegs.push(freed_reg); - } else if (freed_reg < numPhysicalRegs) { -#if THE_ISA == ALPHA_ISA - if (freed_reg != (TheISA::ZeroReg + numPhysicalIntRegs)) -#endif - freeFloatRegs.push(freed_reg); + if (regFile->isIntPhysReg(freed_reg)) { + intList.addReg(freed_reg); + } else { + assert(regFile->isFloatPhysReg(freed_reg)); + floatList.addReg(freed_reg); } // These assert conditions ensure that the number of free @@ -188,20 +187,5 @@ SimpleFreeList::addReg(PhysRegIndex freed_reg) // assert(freeFloatRegs.size() <= numPhysicalFloatRegs); } -inline void -SimpleFreeList::addIntReg(PhysRegIndex freed_reg) -{ - DPRINTF(FreeList,"Freeing int register %i.\n", freed_reg); - - freeIntRegs.push(freed_reg); -} - -inline void -SimpleFreeList::addFloatReg(PhysRegIndex freed_reg) -{ - DPRINTF(FreeList,"Freeing float register %i.\n", freed_reg); - - freeFloatRegs.push(freed_reg); -} #endif // __CPU_O3_FREE_LIST_HH__ diff --git a/src/cpu/o3/regfile.cc b/src/cpu/o3/regfile.cc new file mode 100644 index 000000000..5ba0caefc --- /dev/null +++ b/src/cpu/o3/regfile.cc @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Gabe Black + * Steve Reinhardt + */ + +#include "cpu/o3/free_list.hh" +#include "cpu/o3/regfile.hh" + + +PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, + unsigned _numPhysicalFloatRegs) + : intRegFile(_numPhysicalIntRegs), + floatRegFile(_numPhysicalFloatRegs), + baseFloatRegIndex(_numPhysicalIntRegs), + totalNumRegs(_numPhysicalIntRegs + _numPhysicalFloatRegs) +{ +} + + +void +PhysRegFile::initFreeList(UnifiedFreeList *freeList) +{ + // Initialize the free lists. + PhysRegIndex reg_idx = 0; + + // The initial batch of registers are the integer ones + while (reg_idx < baseFloatRegIndex) { + freeList->addIntReg(reg_idx++); + } + + // The rest of the registers are the floating-point physical + // registers; put them onto the floating-point free list. + while (reg_idx < totalNumRegs) { + freeList->addFloatReg(reg_idx++); + } +} diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index b58f7a2a5..bd3a4f730 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -43,6 +43,8 @@ #include "cpu/o3/comm.hh" #include "debug/IEW.hh" +class UnifiedFreeList; + /** * Simple physical register file class. */ @@ -60,10 +62,10 @@ class PhysRegFile } PhysFloatReg; /** Integer register file. */ - IntReg *intRegFile; + std::vector<IntReg> intRegFile; /** Floating point register file. */ - PhysFloatReg *floatRegFile; + std::vector<PhysFloatReg> floatRegFile; /** * The first floating-point physical register index. The physical @@ -72,6 +74,12 @@ class PhysRegFile * immediately by the floating-point registers. Thus the first * floating-point index is equal to the number of integer * registers. + * + * Note that this internal organizational detail on how physical + * register file indices are ordered should *NOT* be exposed + * outside of this class. Other classes can use the is*PhysReg() + * methods to map from a physical register index to a class + * without knowing the internal structure of the index map. */ unsigned baseFloatRegIndex; @@ -89,7 +97,10 @@ class PhysRegFile /** * Destructor to free resources */ - ~PhysRegFile(); + ~PhysRegFile() {} + + /** Initialize the free list */ + void initFreeList(UnifiedFreeList *freeList); /** @return the number of integer physical registers. */ unsigned numIntPhysRegs() const { return baseFloatRegIndex; } @@ -203,25 +214,4 @@ class PhysRegFile }; -inline -PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, - unsigned _numPhysicalFloatRegs) - : baseFloatRegIndex(_numPhysicalIntRegs), - totalNumRegs(_numPhysicalIntRegs + _numPhysicalFloatRegs) -{ - intRegFile = new IntReg[_numPhysicalIntRegs]; - floatRegFile = new PhysFloatReg[_numPhysicalFloatRegs]; - - memset(intRegFile, 0, sizeof(IntReg) * _numPhysicalIntRegs); - memset(floatRegFile, 0, sizeof(PhysFloatReg) * _numPhysicalFloatRegs); -} - - -inline -PhysRegFile::~PhysRegFile() -{ - delete intRegFile; - delete floatRegFile; -} - #endif //__CPU_O3_REGFILE_HH__ diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 60a929551..6bfc7d952 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -871,18 +871,26 @@ DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, ThreadID tid) // Go through the most recent instructions, undoing the mappings // they did and freeing up the registers. while (!historyBuffer[tid].empty() && - (*hb_it).instSeqNum > squashed_seq_num) { + hb_it->instSeqNum > squashed_seq_num) { assert(hb_it != historyBuffer[tid].end()); DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence " - "number %i.\n", tid, (*hb_it).instSeqNum); - - // Tell the rename map to set the architected register to the - // previous physical register that it was renamed to. - renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg); - - // Put the renamed physical register back on the free list. - freeList->addReg(hb_it->newPhysReg); + "number %i.\n", tid, hb_it->instSeqNum); + + // Undo the rename mapping only if it was really a change. + // Special regs that are not really renamed (like misc regs + // and the zero reg) can be recognized because the new mapping + // is the same as the old one. While it would be merely a + // waste of time to update the rename table, we definitely + // don't want to put these on the free list. + if (hb_it->newPhysReg != hb_it->prevPhysReg) { + // Tell the rename map to set the architected register to the + // previous physical register that it was renamed to. + renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg); + + // Put the renamed physical register back on the free list. + freeList->addReg(hb_it->newPhysReg); + } historyBuffer[tid].erase(hb_it++); @@ -918,13 +926,19 @@ DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid) // renamed. while (!historyBuffer[tid].empty() && hb_it != historyBuffer[tid].end() && - (*hb_it).instSeqNum <= inst_seq_num) { + hb_it->instSeqNum <= inst_seq_num) { DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, " "[sn:%lli].\n", - tid, (*hb_it).prevPhysReg, (*hb_it).instSeqNum); + tid, hb_it->prevPhysReg, hb_it->instSeqNum); + + // Don't free special phys regs like misc and zero regs, which + // can be recognized because the new mapping is the same as + // the old one. + if (hb_it->newPhysReg != hb_it->prevPhysReg) { + freeList->addReg(hb_it->prevPhysReg); + } - freeList->addReg((*hb_it).prevPhysReg); ++renameCommittedMaps; historyBuffer[tid].erase(hb_it--); @@ -935,54 +949,49 @@ template <class Impl> inline void DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid) { - assert(renameMap[tid] != 0); - + ThreadContext *tc = inst->tcBase(); + RenameMap *map = renameMap[tid]; 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. + // operands, and redirect them to the right physical register. for (int src_idx = 0; src_idx < num_src_regs; src_idx++) { RegIndex src_reg = inst->srcRegIdx(src_idx); - RegIndex flat_src_reg = src_reg; - switch (regIdxToClass(src_reg)) { + RegIndex rel_src_reg; + RegIndex flat_rel_src_reg; + PhysRegIndex renamed_reg; + + switch (regIdxToClass(src_reg, &rel_src_reg)) { case IntRegClass: - flat_src_reg = inst->tcBase()->flattenIntIndex(src_reg); - DPRINTF(Rename, "Flattening index %d to %d.\n", - (int)src_reg, (int)flat_src_reg); + flat_rel_src_reg = tc->flattenIntIndex(rel_src_reg); + renamed_reg = map->lookupInt(flat_rel_src_reg); + intRenameLookups++; break; case FloatRegClass: - src_reg = src_reg - TheISA::FP_Reg_Base; - flat_src_reg = inst->tcBase()->flattenFloatIndex(src_reg); - DPRINTF(Rename, "Flattening index %d to %d.\n", - (int)src_reg, (int)flat_src_reg); - flat_src_reg += TheISA::NumIntRegs; + flat_rel_src_reg = tc->flattenFloatIndex(rel_src_reg); + renamed_reg = map->lookupFloat(flat_rel_src_reg); + fpRenameLookups++; break; case MiscRegClass: - flat_src_reg = src_reg - TheISA::Misc_Reg_Base + - TheISA::NumFloatRegs + TheISA::NumIntRegs; - DPRINTF(Rename, "Adjusting reg index from %d to %d.\n", - src_reg, flat_src_reg); + // misc regs don't get flattened + flat_rel_src_reg = rel_src_reg; + renamed_reg = map->lookupMisc(flat_rel_src_reg); break; default: panic("Reg index is out of bound: %d.", src_reg); } - // 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[tid]->lookup(flat_src_reg); - - DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got " - "physical reg %i.\n", tid, (int)flat_src_reg, - (int)renamed_reg); + DPRINTF(Rename, "[tid:%u]: Looking up %s arch reg %i (flattened %i), " + "got phys reg %i\n", tid, RegClassStrings[regIdxToClass(src_reg)], + (int)src_reg, (int)flat_rel_src_reg, (int)renamed_reg); inst->renameSrcReg(src_idx, renamed_reg); // See if the register is ready or not. - if (scoreboard->getReg(renamed_reg) == true) { + if (scoreboard->getReg(renamed_reg)) { DPRINTF(Rename, "[tid:%u]: Register %d is ready.\n", tid, renamed_reg); @@ -993,7 +1002,6 @@ DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid) } ++renameRenameLookups; - inst->isFloating() ? fpRenameLookups++ : intRenameLookups++; } } @@ -1001,58 +1009,53 @@ template <class Impl> inline void DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid) { - typename RenameMap::RenameInfo rename_result; - + ThreadContext *tc = inst->tcBase(); + RenameMap *map = renameMap[tid]; unsigned num_dest_regs = inst->numDestRegs(); // Rename the destination registers. for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) { RegIndex dest_reg = inst->destRegIdx(dest_idx); - RegIndex flat_dest_reg = dest_reg; - switch (regIdxToClass(dest_reg)) { + RegIndex rel_dest_reg; + RegIndex flat_rel_dest_reg; + RegIndex flat_uni_dest_reg; + typename RenameMap::RenameInfo rename_result; + + switch (regIdxToClass(dest_reg, &rel_dest_reg)) { case IntRegClass: - // Integer registers are flattened. - flat_dest_reg = inst->tcBase()->flattenIntIndex(dest_reg); - DPRINTF(Rename, "Flattening index %d to %d.\n", - (int)dest_reg, (int)flat_dest_reg); + flat_rel_dest_reg = tc->flattenIntIndex(rel_dest_reg); + rename_result = map->renameInt(flat_rel_dest_reg); + flat_uni_dest_reg = flat_rel_dest_reg; // 1:1 mapping break; case FloatRegClass: - dest_reg = dest_reg - TheISA::FP_Reg_Base; - flat_dest_reg = inst->tcBase()->flattenFloatIndex(dest_reg); - DPRINTF(Rename, "Flattening index %d to %d.\n", - (int)dest_reg, (int)flat_dest_reg); - flat_dest_reg += TheISA::NumIntRegs; + flat_rel_dest_reg = tc->flattenFloatIndex(rel_dest_reg); + rename_result = map->renameFloat(flat_rel_dest_reg); + flat_uni_dest_reg = flat_rel_dest_reg + TheISA::FP_Reg_Base; break; case MiscRegClass: - // Floating point and Miscellaneous registers need their indexes - // adjusted to account for the expanded number of flattened int regs. - flat_dest_reg = dest_reg - TheISA::Misc_Reg_Base + - TheISA::NumIntRegs + TheISA::NumFloatRegs; - DPRINTF(Rename, "Adjusting reg index from %d to %d.\n", - dest_reg, flat_dest_reg); + // misc regs don't get flattened + flat_rel_dest_reg = rel_dest_reg; + rename_result = map->renameMisc(flat_rel_dest_reg); + flat_uni_dest_reg = flat_rel_dest_reg + TheISA::Misc_Reg_Base; break; default: panic("Reg index is out of bound: %d.", dest_reg); } - inst->flattenDestReg(dest_idx, flat_dest_reg); - - // Get the physical register that the destination will be - // renamed to. - rename_result = renameMap[tid]->rename(flat_dest_reg); + inst->flattenDestReg(dest_idx, flat_uni_dest_reg); - //Mark Scoreboard entry as not ready + // Mark Scoreboard entry as not ready scoreboard->unsetReg(rename_result.first); DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical " - "reg %i.\n", tid, (int)flat_dest_reg, + "reg %i.\n", tid, (int)flat_rel_dest_reg, (int)rename_result.first); // Record the rename information so that a history can be kept. - RenameHistory hb_entry(inst->seqNum, flat_dest_reg, + RenameHistory hb_entry(inst->seqNum, flat_uni_dest_reg, rename_result.first, rename_result.second); diff --git a/src/cpu/o3/rename_map.cc b/src/cpu/o3/rename_map.cc index 57caa76be..ecee4c721 100644 --- a/src/cpu/o3/rename_map.cc +++ b/src/cpu/o3/rename_map.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,222 +36,135 @@ using namespace std; -// @todo: Consider making inline bool functions that determine if the -// register is a logical int, logical fp, physical int, physical fp, -// etc. +/**** SimpleRenameMap methods ****/ -SimpleRenameMap::~SimpleRenameMap() +SimpleRenameMap::SimpleRenameMap() + : freeList(NULL) { } -void -SimpleRenameMap::init(unsigned _numLogicalIntRegs, - unsigned _numPhysicalIntRegs, - PhysRegIndex &ireg_idx, - - unsigned _numLogicalFloatRegs, - unsigned _numPhysicalFloatRegs, - PhysRegIndex &freg_idx, - unsigned _numMiscRegs, +void +SimpleRenameMap::init(unsigned size, SimpleFreeList *_freeList, + RegIndex _zeroReg) +{ + assert(freeList == NULL); + assert(map.empty()); - RegIndex _intZeroReg, - RegIndex _floatZeroReg, + map.resize(size); + freeList = _freeList; + zeroReg = _zeroReg; +} - int map_id, - bool bindRegs) +SimpleRenameMap::RenameInfo +SimpleRenameMap::rename(RegIndex arch_reg) { - id = map_id; - - numLogicalIntRegs = _numLogicalIntRegs; + PhysRegIndex renamed_reg; - numLogicalFloatRegs = _numLogicalFloatRegs; + // Record the current physical register that is renamed to the + // requested architected register. + PhysRegIndex prev_reg = map[arch_reg]; - numPhysicalIntRegs = _numPhysicalIntRegs; + // If it's not referencing the zero register, then rename the + // register. + if (arch_reg != zeroReg) { + renamed_reg = freeList->getReg(); - numPhysicalFloatRegs = _numPhysicalFloatRegs; + map[arch_reg] = renamed_reg; + } else { + // Otherwise return the zero register so nothing bad happens. + assert(prev_reg == zeroReg); + renamed_reg = zeroReg; + } - numMiscRegs = _numMiscRegs; + DPRINTF(Rename, "Renamed reg %d to physical reg %d old mapping was %d\n", + arch_reg, renamed_reg, prev_reg); - intZeroReg = _intZeroReg; - floatZeroReg = _floatZeroReg; + return RenameInfo(renamed_reg, prev_reg); +} - DPRINTF(Rename, "Creating rename map %i. Phys: %i / %i, Float: " - "%i / %i.\n", id, numLogicalIntRegs, numPhysicalIntRegs, - numLogicalFloatRegs, numPhysicalFloatRegs); - numLogicalRegs = numLogicalIntRegs + numLogicalFloatRegs; +/**** UnifiedRenameMap methods ****/ - numPhysicalRegs = numPhysicalIntRegs + numPhysicalFloatRegs; +void +UnifiedRenameMap::init(PhysRegFile *_regFile, + RegIndex _intZeroReg, + RegIndex _floatZeroReg, + UnifiedFreeList *freeList) +{ + regFile = _regFile; - //Create the rename maps - intRenameMap.resize(numLogicalIntRegs); - floatRenameMap.resize(numLogicalRegs); + intMap.init(TheISA::NumIntRegs, &(freeList->intList), _intZeroReg); - if (bindRegs) { - DPRINTF(Rename, "Binding registers into rename map %i\n",id); + floatMap.init(TheISA::NumFloatRegs, &(freeList->floatList), _floatZeroReg); +} - // Initialize the entries in the integer rename map to point to the - // physical registers of the same index - for (RegIndex index = 0; index < numLogicalIntRegs; ++index) - { - intRenameMap[index].physical_reg = ireg_idx++; - } - // Initialize the entries in the floating point rename map to point to - // the physical registers of the same index - // Although the index refers purely to architected registers, because - // the floating reg indices come after the integer reg indices, they - // may exceed the size of a normal RegIndex (short). - for (PhysRegIndex index = numLogicalIntRegs; - index < numLogicalRegs; ++index) - { - floatRenameMap[index].physical_reg = freg_idx++; - } - } else { - DPRINTF(Rename, "Binding registers into rename map %i\n",id); +UnifiedRenameMap::RenameInfo +UnifiedRenameMap::rename(RegIndex arch_reg) +{ + RegIndex rel_arch_reg; - PhysRegIndex temp_ireg = ireg_idx; + switch (regIdxToClass(arch_reg, &rel_arch_reg)) { + case IntRegClass: + return renameInt(rel_arch_reg); - for (RegIndex index = 0; index < numLogicalIntRegs; ++index) - { - intRenameMap[index].physical_reg = temp_ireg++; - } + case FloatRegClass: + return renameFloat(rel_arch_reg); - PhysRegIndex temp_freg = freg_idx; + case MiscRegClass: + return renameMisc(rel_arch_reg); - for (PhysRegIndex index = numLogicalIntRegs; - index < numLogicalRegs; ++index) - { - floatRenameMap[index].physical_reg = temp_freg++; - } + default: + panic("rename rename(): unknown reg class %s\n", + RegClassStrings[regIdxToClass(arch_reg)]); } } -void -SimpleRenameMap::setFreeList(SimpleFreeList *fl_ptr) -{ - freeList = fl_ptr; -} - -SimpleRenameMap::RenameInfo -SimpleRenameMap::rename(RegIndex arch_reg) +PhysRegIndex +UnifiedRenameMap::lookup(RegIndex arch_reg) const { - PhysRegIndex renamed_reg; - PhysRegIndex prev_reg; - - if (arch_reg < numLogicalIntRegs) { - - // Record the current physical register that is renamed to the - // requested architected register. - prev_reg = intRenameMap[arch_reg].physical_reg; - - // If it's not referencing the zero register, then rename the - // register. - if (arch_reg != intZeroReg) { - renamed_reg = freeList->getIntReg(); - - intRenameMap[arch_reg].physical_reg = renamed_reg; - - assert(renamed_reg >= 0 && renamed_reg < numPhysicalIntRegs); - - } else { - // Otherwise return the zero register so nothing bad happens. - renamed_reg = intZeroReg; - prev_reg = intZeroReg; - } - } else if (arch_reg < numLogicalRegs) { - // Record the current physical register that is renamed to the - // requested architected register. - prev_reg = floatRenameMap[arch_reg].physical_reg; - - // If it's not referencing the zero register, then rename the - // register. -#if THE_ISA == ALPHA_ISA - if (arch_reg != floatZeroReg) { -#endif - renamed_reg = freeList->getFloatReg(); - - floatRenameMap[arch_reg].physical_reg = renamed_reg; - - assert(renamed_reg < numPhysicalRegs && - renamed_reg >= numPhysicalIntRegs); -#if THE_ISA == ALPHA_ISA - } else { - // Otherwise return the zero register so nothing bad happens. - renamed_reg = floatZeroReg; - } -#endif - } else { - // Subtract off the base offset for miscellaneous registers. - arch_reg = arch_reg - numLogicalRegs; + RegIndex rel_arch_reg; - DPRINTF(Rename, "Renamed misc reg %d\n", arch_reg); + switch (regIdxToClass(arch_reg, &rel_arch_reg)) { + case IntRegClass: + return lookupInt(rel_arch_reg); - // No renaming happens to the misc. registers. They are - // simply the registers that come after all the physical - // registers; thus take the base architected register and add - // the physical registers to it. - renamed_reg = arch_reg + numPhysicalRegs; + case FloatRegClass: + return lookupFloat(rel_arch_reg); - // Set the previous register to the same register; mainly it must be - // known that the prev reg was outside the range of normal registers - // so the free list can avoid adding it. - prev_reg = renamed_reg; - } - - DPRINTF(Rename, "Renamed reg %d to physical reg %d old mapping was %d\n", - arch_reg, renamed_reg, prev_reg); + case MiscRegClass: + return lookupMisc(rel_arch_reg); - return RenameInfo(renamed_reg, prev_reg); -} - -PhysRegIndex -SimpleRenameMap::lookup(RegIndex arch_reg) -{ - if (arch_reg < numLogicalIntRegs) { - return intRenameMap[arch_reg].physical_reg; - } else if (arch_reg < numLogicalRegs) { - return floatRenameMap[arch_reg].physical_reg; - } else { - // Subtract off the misc registers offset. - arch_reg = arch_reg - numLogicalRegs; - - // Misc. regs don't rename, so simply add the base arch reg to - // the number of physical registers. - return numPhysicalRegs + arch_reg; + default: + panic("rename lookup(): unknown reg class %s\n", + RegClassStrings[regIdxToClass(arch_reg)]); } } void -SimpleRenameMap::setEntry(RegIndex arch_reg, PhysRegIndex renamed_reg) +UnifiedRenameMap::setEntry(RegIndex arch_reg, PhysRegIndex phys_reg) { - // In this implementation the miscellaneous registers do not - // actually rename, so this function does not allow you to try to - // change their mappings. - if (arch_reg < numLogicalIntRegs) { - DPRINTF(Rename, "Rename Map: Integer register %i being set to %i.\n", - (int)arch_reg, renamed_reg); - - intRenameMap[arch_reg].physical_reg = renamed_reg; - } else if (arch_reg < numLogicalIntRegs + numLogicalFloatRegs) { - DPRINTF(Rename, "Rename Map: Float register %i being set to %i.\n", - (int)arch_reg - numLogicalIntRegs, renamed_reg); - - floatRenameMap[arch_reg].physical_reg = renamed_reg; - } -} - -int -SimpleRenameMap::numFreeEntries() -{ - int free_int_regs = freeList->numFreeIntRegs(); - int free_float_regs = freeList->numFreeFloatRegs(); - - if (free_int_regs < free_float_regs) { - return free_int_regs; - } else { - return free_float_regs; + RegIndex rel_arch_reg; + + switch (regIdxToClass(arch_reg, &rel_arch_reg)) { + case IntRegClass: + return setIntEntry(rel_arch_reg, phys_reg); + + case FloatRegClass: + return setFloatEntry(rel_arch_reg, phys_reg); + + case MiscRegClass: + // Misc registers do not actually rename, so don't change + // their mappings. We end up here when a commit or squash + // tries to update or undo a hardwired misc reg nmapping, + // which should always be setting it to what it already is. + assert(phys_reg == lookupMisc(rel_arch_reg)); + return; + + default: + panic("rename setEntry(): unknown reg class %s\n", + RegClassStrings[regIdxToClass(arch_reg)]); } } diff --git a/src/cpu/o3/rename_map.hh b/src/cpu/o3/rename_map.hh index 51d8db4d8..c989fb88f 100644 --- a/src/cpu/o3/rename_map.hh +++ b/src/cpu/o3/rename_map.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,6 +27,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Kevin Lim + * Steve Reinhardt */ // Todo: Create destructor. @@ -42,18 +44,54 @@ #include "arch/types.hh" #include "config/the_isa.hh" #include "cpu/o3/free_list.hh" - +#include "cpu/o3/regfile.hh" +#include "cpu/reg_class.hh" + +/** + * Register rename map for a single class of registers (e.g., integer + * or floating point). Because the register class is implicitly + * determined by the rename map instance being accessed, all + * architectural register index parameters and values in this class + * are relative (e.g., %fp2 is just index 2). + */ class SimpleRenameMap { - protected: + public: + typedef TheISA::RegIndex RegIndex; + + private: + + /** The acutal arch-to-phys register map */ + std::vector<PhysRegIndex> map; + + /** + * Pointer to the free list from which new physical registers + * should be allocated in rename() + */ + SimpleFreeList *freeList; + + /** + * The architectural index of the zero register. This register is + * mapped but read-only, so we ignore attempts to rename it via + * the rename() method. If there is no such register for this map + * table, it should be set to an invalid index so that it never + * matches. + */ + RegIndex zeroReg; + public: + + SimpleRenameMap(); + + ~SimpleRenameMap() {}; + /** - * Pair of a logical register and a physical register. Tells the - * previous mapping of a logical register to a physical register. - * Used to roll back the rename map to a previous state. + * Because we have an array of rename maps (one per thread) in the CPU, + * it's awkward to initialize this object via the constructor. + * Instead, this method is used for initialization. */ - typedef std::pair<RegIndex, PhysRegIndex> UnmapInfo; + void init(unsigned size, SimpleFreeList *_freeList, RegIndex _zeroReg); /** * Pair of a physical register and a physical register. Used to @@ -63,106 +101,216 @@ class SimpleRenameMap */ typedef std::pair<PhysRegIndex, PhysRegIndex> RenameInfo; - public: - /** Default constructor. init() must be called prior to use. */ - SimpleRenameMap() {}; - - /** Destructor. */ - ~SimpleRenameMap(); - - /** Initializes rename map with given parameters. */ - void init(unsigned _numLogicalIntRegs, - unsigned _numPhysicalIntRegs, - PhysRegIndex &_int_reg_start, + /** + * Tell rename map to get a new free physical register to remap + * the specified architectural register. + * @param arch_reg The architectural register to remap. + * @return A RenameInfo pair indicating both the new and previous + * physical registers. + */ + RenameInfo rename(RegIndex arch_reg); - unsigned _numLogicalFloatRegs, - unsigned _numPhysicalFloatRegs, - PhysRegIndex &_float_reg_start, + /** + * Look up the physical register mapped to an architectural register. + * @param arch_reg The architectural register to look up. + * @return The physical register it is currently mapped to. + */ + PhysRegIndex lookup(RegIndex arch_reg) const + { + assert(arch_reg < map.size()); + return map[arch_reg]; + } - unsigned _numMiscRegs, + /** + * Update rename map with a specific mapping. Generally used to + * roll back to old mappings on a squash. + * @param arch_reg The architectural register to remap. + * @param phys_reg The physical register to remap it to. + */ + void setEntry(RegIndex arch_reg, PhysRegIndex phys_reg) + { + map[arch_reg] = phys_reg; + } - RegIndex _intZeroReg, - RegIndex _floatZeroReg, + /** Return the number of free entries on the associated free list. */ + unsigned numFreeEntries() const { return freeList->numFreeRegs(); } +}; - int id, - bool bindRegs); - /** Sets the free list used with this rename map. */ - void setFreeList(SimpleFreeList *fl_ptr); +/** + * Unified register rename map for all classes of registers. Wraps a + * set of class-specific rename maps. Methods that do not specify a + * register class (e.g., rename()) take unified register indices, + * while methods that do specify a register class (e.g., renameInt()) + * take relative register indices. See http://gem5.org/Register_Indexing. + */ +class UnifiedRenameMap +{ + private: - //Tell rename map to get a free physical register for a given - //architected register. Not sure it should have a return value, - //but perhaps it should have some sort of fault in case there are - //no free registers. - RenameInfo rename(RegIndex arch_reg); + /** The integer register rename map */ + SimpleRenameMap intMap; - PhysRegIndex lookup(RegIndex phys_reg); + /** The floating-point register rename map */ + SimpleRenameMap floatMap; /** - * Marks the given register as ready, meaning that its value has been - * calculated and written to the register file. - * @param ready_reg The index of the physical register that is now ready. + * The register file object is used only to distinguish integer + * from floating-point physical register indices, which in turn is + * used only for assert statements that make sure the physical + * register indices that get passed in and handed out are of the + * proper class. */ - void setEntry(RegIndex arch_reg, PhysRegIndex renamed_reg); + PhysRegFile *regFile; + + public: + typedef TheISA::RegIndex RegIndex; - int numFreeEntries(); + typedef SimpleRenameMap::RenameInfo RenameInfo; - private: - /** Rename Map ID */ - int id; + /** Default constructor. init() must be called prior to use. */ + UnifiedRenameMap() {}; - /** Number of logical integer registers. */ - int numLogicalIntRegs; + /** Destructor. */ + ~UnifiedRenameMap() {}; - /** Number of physical integer registers. */ - int numPhysicalIntRegs; + /** Initializes rename map with given parameters. */ + void init(PhysRegFile *_regFile, + RegIndex _intZeroReg, + RegIndex _floatZeroReg, + UnifiedFreeList *freeList); - /** Number of logical floating point registers. */ - int numLogicalFloatRegs; + /** + * Tell rename map to get a new free physical register to remap + * the specified architectural register. This version takes a + * unified flattened architectural register index and calls the + * appropriate class-specific rename table. + * @param arch_reg The unified architectural register index to remap. + * @return A RenameInfo pair indicating both the new and previous + * physical registers. + */ + RenameInfo rename(RegIndex arch_reg); - /** Number of physical floating point registers. */ - int numPhysicalFloatRegs; + /** + * Perform rename() on an integer register, given a relative + * integer register index. + */ + RenameInfo renameInt(RegIndex rel_arch_reg) + { + RenameInfo info = intMap.rename(rel_arch_reg); + assert(regFile->isIntPhysReg(info.first)); + return info; + } + + /** + * Perform rename() on a floating-point register, given a relative + * floating-point register index. + */ + RenameInfo renameFloat(RegIndex rel_arch_reg) + { + RenameInfo info = floatMap.rename(rel_arch_reg); + assert(regFile->isFloatPhysReg(info.first)); + return info; + } - /** Number of miscellaneous registers. */ - int numMiscRegs; + /** + * Perform rename() on a misc register, given a relative + * misc register index. + */ + RenameInfo renameMisc(RegIndex rel_arch_reg) + { + // misc regs aren't really renamed, just remapped + PhysRegIndex phys_reg = lookupMisc(rel_arch_reg); + // Set the previous register to the same register; mainly it must be + // known that the prev reg was outside the range of normal registers + // so the free list can avoid adding it. + return RenameInfo(phys_reg, phys_reg); + } - /** Number of logical integer + float registers. */ - int numLogicalRegs; - /** Number of physical integer + float registers. */ - int numPhysicalRegs; + /** + * Look up the physical register mapped to an architectural register. + * This version takes a unified flattened architectural register index + * and calls the appropriate class-specific rename table. + * @param arch_reg The unified architectural register to look up. + * @return The physical register it is currently mapped to. + */ + PhysRegIndex lookup(RegIndex arch_reg) const; - /** The integer zero register. This implementation assumes it is always - * zero and never can be anything else. + /** + * Perform lookup() on an integer register, given a relative + * integer register index. */ - RegIndex intZeroReg; + PhysRegIndex lookupInt(RegIndex rel_arch_reg) const + { + PhysRegIndex phys_reg = intMap.lookup(rel_arch_reg); + assert(regFile->isIntPhysReg(phys_reg)); + return phys_reg; + } - /** The floating point zero register. This implementation assumes it is - * always zero and never can be anything else. + /** + * Perform lookup() on a floating-point register, given a relative + * floating-point register index. */ - RegIndex floatZeroReg; + PhysRegIndex lookupFloat(RegIndex rel_arch_reg) const + { + PhysRegIndex phys_reg = floatMap.lookup(rel_arch_reg); + assert(regFile->isFloatPhysReg(phys_reg)); + return phys_reg; + } - class RenameEntry + /** + * Perform lookup() on a misc register, given a relative + * misc register index. + */ + PhysRegIndex lookupMisc(RegIndex rel_arch_reg) const { - public: - PhysRegIndex physical_reg; - bool valid; + // misc regs aren't really renamed, just given an index + // beyond the range of actual physical registers + PhysRegIndex phys_reg = rel_arch_reg + regFile->totalNumPhysRegs(); + return phys_reg; + } - RenameEntry() - : physical_reg(0), valid(false) - { } - }; + /** + * Update rename map with a specific mapping. Generally used to + * roll back to old mappings on a squash. This version takes a + * unified flattened architectural register index and calls the + * appropriate class-specific rename table. + * @param arch_reg The unified architectural register to remap. + * @param phys_reg The physical register to remap it to. + */ + void setEntry(RegIndex arch_reg, PhysRegIndex phys_reg); - private: - /** Integer rename map. */ - std::vector<RenameEntry> intRenameMap; + /** + * Perform setEntry() on an integer register, given a relative + * integer register index. + */ + void setIntEntry(RegIndex arch_reg, PhysRegIndex phys_reg) + { + assert(regFile->isIntPhysReg(phys_reg)); + intMap.setEntry(arch_reg, phys_reg); + } - /** Floating point rename map. */ - std::vector<RenameEntry> floatRenameMap; + /** + * Perform setEntry() on a floating-point register, given a relative + * floating-point register index. + */ + void setFloatEntry(RegIndex arch_reg, PhysRegIndex phys_reg) + { + assert(regFile->isFloatPhysReg(phys_reg)); + floatMap.setEntry(arch_reg, phys_reg); + } - private: - /** Free list interface. */ - SimpleFreeList *freeList; + /** + * Return the minimum number of free entries across all of the + * register classes. The minimum is used so we guarantee that + * this number of entries is available regardless of which class + * of registers is requested. + */ + unsigned numFreeEntries() const + { + return std::min(intMap.numFreeEntries(), floatMap.numFreeEntries()); + } }; #endif //__CPU_O3_RENAME_MAP_HH__ |