summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/cpu/o3/SConscript1
-rw-r--r--src/cpu/o3/cpu.cc86
-rw-r--r--src/cpu/o3/cpu.hh3
-rw-r--r--src/cpu/o3/cpu_policy.hh9
-rw-r--r--src/cpu/o3/free_list.cc41
-rw-r--r--src/cpu/o3/free_list.hh176
-rw-r--r--src/cpu/o3/regfile.cc64
-rw-r--r--src/cpu/o3/regfile.hh38
-rw-r--r--src/cpu/o3/rename_impl.hh135
-rw-r--r--src/cpu/o3/rename_map.cc272
-rw-r--r--src/cpu/o3/rename_map.hh302
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", &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
-
- 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(&regFile, TheISA::ZeroReg, fpZeroReg,
+ &freeList);
- 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);
}
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__