cpu/o3: clean up rename map and free list

Restructured rename map and free list to clean up some
extraneous code and separate out common code that can
be reused across different register classes (int and fp
at this point).  Both components now consist of a set
of Simple* objects that are stand-alone rename map &
free list for each class, plus a Unified* object that
presents a unified interface across all register
classes and then redirects accesses to the appropriate
Simple* object as needed.

Moved free list initialization to PhysRegFile to better
isolate knowledge of physical register index mappings
to that class (and remove the need to pass a number
of parameters to the free list constructor).

Causes a small change to these stats:
  cpu.rename.int_rename_lookups
  cpu.rename.fp_rename_lookups
because they are now categorized on a per-operand basis
rather than a per-instruction basis.
That is, an instruction with mixed fp/int/misc operand
types will have each operand categorized independently,
where previously the lookup was categorized based on
the instruction type.
This commit is contained in:
Steve Reinhardt 2013-10-15 14:22:44 -04:00
parent 219c423f1f
commit 5526221847
11 changed files with 614 additions and 555 deletions

View file

@ -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')

View file

@ -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", &regFile),
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
// 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::NumFloatRegs,
params->numPhysFloatRegs,
freg_idx, //Index for Float Regs
commitRenameMap[tid].init(&regFile, TheISA::ZeroReg, fpZeroReg,
&freeList);
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,
TheISA::ZeroReg,
TheISA::ZeroReg,
tid,
bindRegs);
renameMap[tid].init(&regFile, 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);
}

View file

@ -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;

View file

@ -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. */

View file

@ -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);
}

View file

@ -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,13 +35,50 @@
#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
@ -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 object name, for DPRINTF. We have to declare this
* explicitly because Scoreboard is not a SimObject. */
const std::string _name;
/** The list of free integer registers. */
std::queue<PhysRegIndex> freeIntRegs;
SimpleFreeList intList;
/** The list of free floating point registers. */
std::queue<PhysRegIndex> freeFloatRegs;
SimpleFreeList floatList;
/** Number of logical integer registers. */
int numLogicalIntRegs;
/**
* The register file object is used only to distinguish integer
* from floating-point physical register indices.
*/
PhysRegFile *regFile;
/** Number of physical integer registers. */
int numPhysicalIntRegs;
/** Number of logical floating point registers. */
int numLogicalFloatRegs;
/** Number of physical floating point registers. */
int numPhysicalFloatRegs;
/** 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__

64
src/cpu/o3/regfile.cc Normal file
View file

@ -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++);
}
}

View file

@ -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__

View file

@ -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);
"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);
// 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);
// 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);
inst->flattenDestReg(dest_idx, flat_uni_dest_reg);
// Get the physical register that the destination will be
// renamed to.
rename_result = renameMap[tid]->rename(flat_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);

View file

@ -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,169 +36,45 @@
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,
RegIndex _intZeroReg,
RegIndex _floatZeroReg,
int map_id,
bool bindRegs)
SimpleRenameMap::init(unsigned size, SimpleFreeList *_freeList,
RegIndex _zeroReg)
{
id = map_id;
assert(freeList == NULL);
assert(map.empty());
numLogicalIntRegs = _numLogicalIntRegs;
numLogicalFloatRegs = _numLogicalFloatRegs;
numPhysicalIntRegs = _numPhysicalIntRegs;
numPhysicalFloatRegs = _numPhysicalFloatRegs;
numMiscRegs = _numMiscRegs;
intZeroReg = _intZeroReg;
floatZeroReg = _floatZeroReg;
DPRINTF(Rename, "Creating rename map %i. Phys: %i / %i, Float: "
"%i / %i.\n", id, numLogicalIntRegs, numPhysicalIntRegs,
numLogicalFloatRegs, numPhysicalFloatRegs);
numLogicalRegs = numLogicalIntRegs + numLogicalFloatRegs;
numPhysicalRegs = numPhysicalIntRegs + numPhysicalFloatRegs;
//Create the rename maps
intRenameMap.resize(numLogicalIntRegs);
floatRenameMap.resize(numLogicalRegs);
if (bindRegs) {
DPRINTF(Rename, "Binding registers into rename map %i\n",id);
// 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);
PhysRegIndex temp_ireg = ireg_idx;
for (RegIndex index = 0; index < numLogicalIntRegs; ++index)
{
intRenameMap[index].physical_reg = temp_ireg++;
}
PhysRegIndex temp_freg = freg_idx;
for (PhysRegIndex index = numLogicalIntRegs;
index < numLogicalRegs; ++index)
{
floatRenameMap[index].physical_reg = temp_freg++;
}
}
map.resize(size);
freeList = _freeList;
zeroReg = _zeroReg;
}
void
SimpleRenameMap::setFreeList(SimpleFreeList *fl_ptr)
{
freeList = fl_ptr;
}
SimpleRenameMap::RenameInfo
SimpleRenameMap::rename(RegIndex arch_reg)
{
PhysRegIndex renamed_reg;
PhysRegIndex prev_reg;
if (arch_reg < numLogicalIntRegs) {
// Record the current physical register that is renamed to the
// requested architected register.
PhysRegIndex prev_reg = map[arch_reg];
// 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 != zeroReg) {
renamed_reg = freeList->getReg();
// 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
map[arch_reg] = renamed_reg;
} else {
// Subtract off the base offset for miscellaneous registers.
arch_reg = arch_reg - numLogicalRegs;
DPRINTF(Rename, "Renamed misc reg %d\n", 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;
// 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;
// Otherwise return the zero register so nothing bad happens.
assert(prev_reg == zeroReg);
renamed_reg = zeroReg;
}
DPRINTF(Rename, "Renamed reg %d to physical reg %d old mapping was %d\n",
@ -206,51 +83,88 @@ SimpleRenameMap::rename(RegIndex 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;
/**** UnifiedRenameMap methods ****/
void
UnifiedRenameMap::init(PhysRegFile *_regFile,
RegIndex _intZeroReg,
RegIndex _floatZeroReg,
UnifiedFreeList *freeList)
{
regFile = _regFile;
intMap.init(TheISA::NumIntRegs, &(freeList->intList), _intZeroReg);
floatMap.init(TheISA::NumFloatRegs, &(freeList->floatList), _floatZeroReg);
}
UnifiedRenameMap::RenameInfo
UnifiedRenameMap::rename(RegIndex arch_reg)
{
RegIndex rel_arch_reg;
switch (regIdxToClass(arch_reg, &rel_arch_reg)) {
case IntRegClass:
return renameInt(rel_arch_reg);
case FloatRegClass:
return renameFloat(rel_arch_reg);
case MiscRegClass:
return renameMisc(rel_arch_reg);
default:
panic("rename rename(): unknown reg class %s\n",
RegClassStrings[regIdxToClass(arch_reg)]);
}
}
PhysRegIndex
UnifiedRenameMap::lookup(RegIndex arch_reg) const
{
RegIndex rel_arch_reg;
switch (regIdxToClass(arch_reg, &rel_arch_reg)) {
case IntRegClass:
return lookupInt(rel_arch_reg);
case FloatRegClass:
return lookupFloat(rel_arch_reg);
case MiscRegClass:
return lookupMisc(rel_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);
RegIndex rel_arch_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);
switch (regIdxToClass(arch_reg, &rel_arch_reg)) {
case IntRegClass:
return setIntEntry(rel_arch_reg, phys_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;
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)]);
}
}

View file

@ -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:
typedef TheISA::RegIndex RegIndex;
public:
typedef TheISA::RegIndex RegIndex;
private:
/** The acutal arch-to-phys register map */
std::vector<PhysRegIndex> map;
/**
* 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.
* Pointer to the free list from which new physical registers
* should be allocated in rename()
*/
typedef std::pair<RegIndex, PhysRegIndex> UnmapInfo;
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() {};
/**
* 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.
*/
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,
unsigned _numLogicalFloatRegs,
unsigned _numPhysicalFloatRegs,
PhysRegIndex &_float_reg_start,
unsigned _numMiscRegs,
RegIndex _intZeroReg,
RegIndex _floatZeroReg,
int id,
bool bindRegs);
/** Sets the free list used with this rename map. */
void setFreeList(SimpleFreeList *fl_ptr);
//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.
/**
* 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);
PhysRegIndex lookup(RegIndex phys_reg);
/**
* 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];
}
/**
* 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.
* 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 renamed_reg);
int numFreeEntries();
private:
/** Rename Map ID */
int id;
/** Number of logical integer registers. */
int numLogicalIntRegs;
/** Number of physical integer registers. */
int numPhysicalIntRegs;
/** Number of logical floating point registers. */
int numLogicalFloatRegs;
/** Number of physical floating point registers. */
int numPhysicalFloatRegs;
/** Number of miscellaneous registers. */
int numMiscRegs;
/** Number of logical integer + float registers. */
int numLogicalRegs;
/** Number of physical integer + float registers. */
int numPhysicalRegs;
/** The integer zero register. This implementation assumes it is always
* zero and never can be anything else.
*/
RegIndex intZeroReg;
/** The floating point zero register. This implementation assumes it is
* always zero and never can be anything else.
*/
RegIndex floatZeroReg;
class RenameEntry
void setEntry(RegIndex arch_reg, PhysRegIndex phys_reg)
{
public:
PhysRegIndex physical_reg;
bool valid;
map[arch_reg] = phys_reg;
}
RenameEntry()
: physical_reg(0), valid(false)
{ }
};
/** Return the number of free entries on the associated free list. */
unsigned numFreeEntries() const { return freeList->numFreeRegs(); }
};
/**
* 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:
/** Integer rename map. */
std::vector<RenameEntry> intRenameMap;
/** Floating point rename map. */
std::vector<RenameEntry> floatRenameMap;
/** The integer register rename map */
SimpleRenameMap intMap;
private:
/** Free list interface. */
SimpleFreeList *freeList;
/** The floating-point register rename map */
SimpleRenameMap floatMap;
/**
* 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.
*/
PhysRegFile *regFile;
public:
typedef TheISA::RegIndex RegIndex;
typedef SimpleRenameMap::RenameInfo RenameInfo;
/** Default constructor. init() must be called prior to use. */
UnifiedRenameMap() {};
/** Destructor. */
~UnifiedRenameMap() {};
/** Initializes rename map with given parameters. */
void init(PhysRegFile *_regFile,
RegIndex _intZeroReg,
RegIndex _floatZeroReg,
UnifiedFreeList *freeList);
/**
* 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);
/**
* 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;
}
/**
* 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);
}
/**
* 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;
/**
* Perform lookup() on an integer register, given a relative
* integer register index.
*/
PhysRegIndex lookupInt(RegIndex rel_arch_reg) const
{
PhysRegIndex phys_reg = intMap.lookup(rel_arch_reg);
assert(regFile->isIntPhysReg(phys_reg));
return phys_reg;
}
/**
* Perform lookup() on a floating-point register, given a relative
* floating-point register index.
*/
PhysRegIndex lookupFloat(RegIndex rel_arch_reg) const
{
PhysRegIndex phys_reg = floatMap.lookup(rel_arch_reg);
assert(regFile->isFloatPhysReg(phys_reg));
return phys_reg;
}
/**
* Perform lookup() on a misc register, given a relative
* misc register index.
*/
PhysRegIndex lookupMisc(RegIndex rel_arch_reg) const
{
// 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;
}
/**
* 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);
/**
* 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);
}
/**
* 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);
}
/**
* 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__