arch,cpu: Create register class descriptors.

These currently only hold the number of registers in a particular class,
but can be extended in the future to hold other information about each
class. The ISA class holds a vector of descriptors which other parts of
gem5 can retrieve to set up storage for each class, etc.

Currently, the RegClass enum is used to explicitly index into the vector
of descriptors to get information about a particular class. Once enough
information is stored in the descriptors, the other parts of gem5 should
be able to set up for each register class generically, and the ISAs will
be able to leave out or create new register classes without having to
set up global plumbing for it.

The more immediate benefit is that this should (mostly) parameterize
away the ISA register constants to break another TheISA style
dependency. Currently a global set of descriptors are set up in the
BaseISA class using the old TheISA constants, but it should be easy to
break those out and make the ISAs set up their own descriptors. That
will bring arch/registers.hh significantly closer to being eliminated.

Change-Id: I6d6d1256288f880391246b71045482a4a03c4198
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/41733
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-02-21 06:39:04 -08:00
parent e837fdc65c
commit 49082c971f
15 changed files with 247 additions and 165 deletions

View File

@@ -40,23 +40,44 @@
#ifndef __ARCH_GENERIC_ISA_HH__
#define __ARCH_GENERIC_ISA_HH__
#include <vector>
#include "arch/registers.hh"
#include "cpu/reg_class.hh"
#include "sim/sim_object.hh"
class ThreadContext;
class BaseISA : public SimObject
{
public:
typedef std::vector<RegClassInfo> RegClasses;
protected:
using SimObject::SimObject;
ThreadContext *tc = nullptr;
RegClasses _regClasses = {
#if THE_ISA != NULL_ISA
{ TheISA::NumIntRegs },
{ TheISA::NumFloatRegs },
{ TheISA::NumVecRegs },
{ TheISA::NumVecRegs * TheISA::NumVecElemPerVecReg },
{ TheISA::NumVecPredRegs },
{ TheISA::NumCCRegs },
{ TheISA::NumMiscRegs }
#endif // THE_ISA != NULL_ISA
};
public:
virtual void takeOverFrom(ThreadContext *new_tc, ThreadContext *old_tc) {}
virtual void setThreadContext(ThreadContext *_tc) { tc = _tc; }
virtual uint64_t getExecutingAsid() const { return 0; }
virtual bool inUserMode() const = 0;
const RegClasses &regClasses() const { return _regClasses; }
};
#endif // __ARCH_GENERIC_ISA_HH__

View File

@@ -175,8 +175,10 @@ Execute::Execute(const std::string &name_,
name_ + ".inputBuffer" + tid_str, "insts",
params.executeInputBufferSize));
const auto &regClasses = cpu.threads[tid]->getIsaPtr()->regClasses();
/* Scoreboards */
scoreboard.push_back(Scoreboard(name_ + ".scoreboard" + tid_str));
scoreboard.emplace_back(name_ + ".scoreboard" + tid_str, regClasses);
/* In-flight instruction records */
executeInfo[tid].inFlightInsts = new Queue<QueuedInst,

View File

@@ -61,27 +61,20 @@ Scoreboard::findIndex(const RegId& reg, Index &scoreboard_index)
ret = true;
break;
case FloatRegClass:
scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
reg.index();
scoreboard_index = floatRegOffset + reg.index();
ret = true;
break;
case VecRegClass:
scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
TheISA::NumFloatRegs + reg.index();
ret = true;
break;
case VecElemClass:
scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
TheISA::NumFloatRegs + reg.flatIndex();
scoreboard_index = vecRegOffset + reg.index();
ret = true;
break;
case VecPredRegClass:
scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
TheISA::NumFloatRegs + TheISA::NumVecRegs + reg.index();
scoreboard_index = vecPredRegOffset + reg.index();
ret = true;
break;
case CCRegClass:
scoreboard_index = TheISA::NumIntRegs + reg.index();
scoreboard_index = ccRegOffset + reg.index();
ret = true;
break;
case MiscRegClass:

View File

@@ -50,6 +50,7 @@
#include "cpu/minor/cpu.hh"
#include "cpu/minor/dyn_inst.hh"
#include "cpu/minor/trace.hh"
#include "cpu/reg_class.hh"
namespace Minor
{
@@ -60,6 +61,14 @@ namespace Minor
class Scoreboard : public Named
{
public:
const BaseISA::RegClasses regClasses;
const unsigned intRegOffset;
const unsigned floatRegOffset;
const unsigned ccRegOffset;
const unsigned vecRegOffset;
const unsigned vecPredRegOffset;
/** The number of registers in the Scoreboard. These
* are just the integer, CC and float registers packed
* together with integer regs in the range [0,NumIntRegs-1],
@@ -92,12 +101,16 @@ class Scoreboard : public Named
std::vector<InstSeqNum> writingInst;
public:
Scoreboard(const std::string &name) :
Scoreboard(const std::string &name,
const BaseISA::RegClasses& reg_classes) :
Named(name),
numRegs(TheISA::NumIntRegs + TheISA::NumCCRegs +
TheISA::NumFloatRegs +
(TheISA::NumVecRegs * TheISA::NumVecElemPerVecReg) +
TheISA::NumVecPredRegs),
regClasses(reg_classes),
intRegOffset(0),
floatRegOffset(intRegOffset + reg_classes.at(IntRegClass).size()),
ccRegOffset(floatRegOffset + reg_classes.at(FloatRegClass).size()),
vecRegOffset(ccRegOffset + reg_classes.at(CCRegClass).size()),
vecPredRegOffset(vecRegOffset + reg_classes.at(VecElemClass).size()),
numRegs(vecPredRegOffset + reg_classes.at(VecPredRegClass).size()),
numResults(numRegs, 0),
numUnpredictableResults(numRegs, 0),
fuIndices(numRegs, 0),

View File

@@ -95,6 +95,7 @@ FullO3CPU<Impl>::FullO3CPU(const DerivO3CPUParams &params)
params.numPhysVecRegs,
params.numPhysVecPredRegs,
params.numPhysCCRegs,
params.isa[0]->regClasses().at(MiscRegClass).size(),
vecMode),
freeList(name() + ".freelist", &regFile),
@@ -194,12 +195,26 @@ FullO3CPU<Impl>::FullO3CPU(const DerivO3CPUParams &params)
}
}
//Make Sure That this a Valid Architeture
assert(params.numPhysIntRegs >= numThreads * TheISA::NumIntRegs);
assert(params.numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
assert(params.numPhysVecRegs >= numThreads * TheISA::NumVecRegs);
assert(params.numPhysVecPredRegs >= numThreads * TheISA::NumVecPredRegs);
assert(params.numPhysCCRegs >= numThreads * TheISA::NumCCRegs);
// Make Sure That this a Valid Architeture
assert(numThreads);
const auto &regClasses = params.isa[0]->regClasses();
assert(params.numPhysIntRegs >=
numThreads * regClasses.at(IntRegClass).size());
assert(params.numPhysFloatRegs >=
numThreads * regClasses.at(FloatRegClass).size());
assert(params.numPhysVecRegs >=
numThreads * regClasses.at(VecRegClass).size());
assert(params.numPhysVecPredRegs >=
numThreads * regClasses.at(VecPredRegClass).size());
assert(params.numPhysCCRegs >=
numThreads * regClasses.at(CCRegClass).size());
// Just make this a warning and go ahead anyway, to keep from having to
// add checks everywhere.
warn_if(regClasses.at(CCRegClass).size() == 0 && params.numPhysCCRegs != 0,
"Non-zero number of physical CC regs specified, even though\n"
" ISA does not use them.");
rename.setScoreboard(&scoreboard);
iew.setScoreboard(&scoreboard);
@@ -213,19 +228,20 @@ FullO3CPU<Impl>::FullO3CPU(const DerivO3CPUParams &params)
// 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 invalidFPReg = regClasses.at(FloatRegClass).size() + 1;
commitRenameMap[tid].init(&regFile, TheISA::ZeroReg, invalidFPReg,
&freeList, vecMode);
commitRenameMap[tid].init(regClasses, &regFile, TheISA::ZeroReg,
invalidFPReg, &freeList, vecMode);
renameMap[tid].init(&regFile, TheISA::ZeroReg, invalidFPReg,
&freeList, vecMode);
renameMap[tid].init(regClasses, &regFile, TheISA::ZeroReg,
invalidFPReg, &freeList, vecMode);
}
// 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) {
for (RegIndex ridx = 0; ridx < regClasses.at(IntRegClass).size();
++ridx) {
// Note that we can't use the rename() method because we don't
// want special treatment for the zero register at this point
PhysRegIdPtr phys_reg = freeList.getIntReg();
@@ -233,7 +249,8 @@ FullO3CPU<Impl>::FullO3CPU(const DerivO3CPUParams &params)
commitRenameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg);
}
for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) {
for (RegIndex ridx = 0; ridx < regClasses.at(FloatRegClass).size();
++ridx) {
PhysRegIdPtr phys_reg = freeList.getFloatReg();
renameMap[tid].setEntry(RegId(FloatRegClass, ridx), phys_reg);
commitRenameMap[tid].setEntry(
@@ -243,9 +260,10 @@ FullO3CPU<Impl>::FullO3CPU(const DerivO3CPUParams &params)
/* Here we need two 'interfaces' the 'whole register' and the
* 'register element'. At any point only one of them will be
* active. */
const size_t numVecs = regClasses.at(VecRegClass).size();
if (vecMode == Enums::Full) {
/* Initialize the full-vector interface */
for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) {
for (RegIndex ridx = 0; ridx < numVecs; ++ridx) {
RegId rid = RegId(VecRegClass, ridx);
PhysRegIdPtr phys_reg = freeList.getVecReg();
renameMap[tid].setEntry(rid, phys_reg);
@@ -253,9 +271,10 @@ FullO3CPU<Impl>::FullO3CPU(const DerivO3CPUParams &params)
}
} else {
/* Initialize the vector-element interface */
for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) {
for (ElemIndex ldx = 0; ldx < TheISA::NumVecElemPerVecReg;
++ldx) {
const size_t numElems = regClasses.at(VecElemClass).size();
const size_t elemsPerVec = numElems / numVecs;
for (RegIndex ridx = 0; ridx < numVecs; ++ridx) {
for (ElemIndex ldx = 0; ldx < elemsPerVec; ++ldx) {
RegId lrid = RegId(VecElemClass, ridx, ldx);
PhysRegIdPtr phys_elem = freeList.getVecElem();
renameMap[tid].setEntry(lrid, phys_elem);
@@ -264,14 +283,16 @@ FullO3CPU<Impl>::FullO3CPU(const DerivO3CPUParams &params)
}
}
for (RegIndex ridx = 0; ridx < TheISA::NumVecPredRegs; ++ridx) {
for (RegIndex ridx = 0; ridx < regClasses.at(VecPredRegClass).size();
++ridx) {
PhysRegIdPtr phys_reg = freeList.getVecPredReg();
renameMap[tid].setEntry(RegId(VecPredRegClass, ridx), phys_reg);
commitRenameMap[tid].setEntry(
RegId(VecPredRegClass, ridx), phys_reg);
}
for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) {
for (RegIndex ridx = 0; ridx < regClasses.at(CCRegClass).size();
++ridx) {
PhysRegIdPtr phys_reg = freeList.getCCReg();
renameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg);
commitRenameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg);
@@ -750,25 +771,29 @@ FullO3CPU<Impl>::insertThread(ThreadID tid)
src_tc = tcBase(tid);
//Bind Int Regs to Rename Map
const auto &regClasses = isa[tid]->regClasses();
for (RegId reg_id(IntRegClass, 0); reg_id.index() < TheISA::NumIntRegs;
reg_id.index()++) {
for (RegId reg_id(IntRegClass, 0);
reg_id.index() < regClasses.at(IntRegClass).size();
reg_id.index()++) {
PhysRegIdPtr phys_reg = freeList.getIntReg();
renameMap[tid].setEntry(reg_id, phys_reg);
scoreboard.setReg(phys_reg);
}
//Bind Float Regs to Rename Map
for (RegId reg_id(FloatRegClass, 0); reg_id.index() < TheISA::NumFloatRegs;
reg_id.index()++) {
for (RegId reg_id(FloatRegClass, 0);
reg_id.index() < regClasses.at(FloatRegClass).size();
reg_id.index()++) {
PhysRegIdPtr phys_reg = freeList.getFloatReg();
renameMap[tid].setEntry(reg_id, phys_reg);
scoreboard.setReg(phys_reg);
}
//Bind condition-code Regs to Rename Map
for (RegId reg_id(CCRegClass, 0); reg_id.index() < TheISA::NumCCRegs;
reg_id.index()++) {
for (RegId reg_id(CCRegClass, 0);
reg_id.index() < regClasses.at(CCRegClass).size();
reg_id.index()++) {
PhysRegIdPtr phys_reg = freeList.getCCReg();
renameMap[tid].setEntry(reg_id, phys_reg);
scoreboard.setReg(phys_reg);
@@ -845,21 +870,23 @@ template <class Impl>
void
FullO3CPU<Impl>::setVectorsAsReady(ThreadID tid)
{
const auto &regClasses = isa[tid]->regClasses();
const size_t numVecs = regClasses.at(VecRegClass).size();
if (vecMode == Enums::Elem) {
for (auto v = 0; v < TheISA::NumVecRegs; v++)
for (auto e = 0; e < TheISA::NumVecElemPerVecReg; e++)
scoreboard.setReg(
commitRenameMap[tid].lookup(
RegId(VecElemClass, v, e)
)
);
const size_t numElems = regClasses.at(VecElemClass).size();
const size_t elemsPerVec = numElems / numVecs;
for (auto v = 0; v < numVecs; v++) {
for (auto e = 0; e < elemsPerVec; e++) {
scoreboard.setReg(commitRenameMap[tid].lookup(
RegId(VecElemClass, v, e)));
}
}
} else if (vecMode == Enums::Full) {
for (auto v = 0; v < TheISA::NumVecRegs; v++)
scoreboard.setReg(
commitRenameMap[tid].lookup(
RegId(VecRegClass, v)
)
);
for (auto v = 0; v < numVecs; v++) {
scoreboard.setReg(commitRenameMap[tid].lookup(
RegId(VecRegClass, v)));
}
}
}

View File

@@ -29,9 +29,7 @@
#include "cpu/o3/free_list.hh"
#include "arch/registers.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
#include "debug/FreeList.hh"
UnifiedFreeList::UnifiedFreeList(const std::string &_my_name,

View File

@@ -50,6 +50,7 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs,
unsigned _numPhysicalVecRegs,
unsigned _numPhysicalVecPredRegs,
unsigned _numPhysicalCCRegs,
unsigned _numPhysicalMiscRegs,
VecMode vmode)
: intRegFile(_numPhysicalIntRegs),
floatRegFile(_numPhysicalFloatRegs),
@@ -74,12 +75,6 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs,
PhysRegIndex phys_reg;
PhysRegIndex flat_reg_idx = 0;
if (TheISA::NumCCRegs == 0 && _numPhysicalCCRegs != 0) {
// Just make this a warning and go ahead and allocate them
// anyway, to keep from having to add checks everywhere
warn("Non-zero number of physical CC regs specified, even though\n"
" ISA does not use them.\n");
}
// The initial batch of registers are the integer ones
for (phys_reg = 0; phys_reg < numPhysicalIntRegs; phys_reg++) {
intRegIds.emplace_back(IntRegClass, phys_reg, flat_reg_idx++);
@@ -121,7 +116,7 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs,
}
// Misc regs have a fixed mapping but still need PhysRegIds.
for (phys_reg = 0; phys_reg < TheISA::NumMiscRegs; phys_reg++) {
for (phys_reg = 0; phys_reg < _numPhysicalMiscRegs; phys_reg++) {
miscRegIds.emplace_back(MiscRegClass, phys_reg, 0);
}
}

View File

@@ -136,6 +136,7 @@ class PhysRegFile
unsigned _numPhysicalVecRegs,
unsigned _numPhysicalVecPredRegs,
unsigned _numPhysicalCCRegs,
unsigned _numPhysicalMiscRegs,
VecMode vmode
);

View File

@@ -44,8 +44,6 @@
#include <list>
#include "arch/registers.hh"
#include "config/the_isa.hh"
#include "cpu/o3/rename.hh"
#include "cpu/reg_class.hh"
#include "debug/Activity.hh"

View File

@@ -43,25 +43,26 @@
#include <vector>
#include "arch/registers.hh"
#include "cpu/reg_class.hh"
#include "debug/Rename.hh"
/**** SimpleRenameMap methods ****/
SimpleRenameMap::SimpleRenameMap()
: freeList(NULL), zeroReg(IntRegClass,0)
: freeList(NULL), zeroReg(IntRegClass, 0)
{
}
void
SimpleRenameMap::init(unsigned size, SimpleFreeList *_freeList,
RegIndex _zeroReg)
SimpleRenameMap::init(const RegClassInfo &reg_class_info,
SimpleFreeList *_freeList, RegIndex _zeroReg)
{
assert(freeList == NULL);
assert(map.empty());
map.resize(size);
map.resize(reg_class_info.size());
freeList = _freeList;
zeroReg = RegId(IntRegClass, _zeroReg);
}
@@ -105,7 +106,8 @@ SimpleRenameMap::rename(const RegId& arch_reg)
/**** UnifiedRenameMap methods ****/
void
UnifiedRenameMap::init(PhysRegFile *_regFile,
UnifiedRenameMap::init(const BaseISA::RegClasses &regClasses,
PhysRegFile *_regFile,
RegIndex _intZeroReg,
RegIndex _floatZeroReg,
UnifiedFreeList *freeList,
@@ -114,18 +116,21 @@ UnifiedRenameMap::init(PhysRegFile *_regFile,
regFile = _regFile;
vecMode = _mode;
intMap.init(TheISA::NumIntRegs, &(freeList->intList), _intZeroReg);
intMap.init(regClasses.at(IntRegClass), &(freeList->intList), _intZeroReg);
floatMap.init(TheISA::NumFloatRegs, &(freeList->floatList), _floatZeroReg);
floatMap.init(regClasses.at(FloatRegClass), &(freeList->floatList),
_floatZeroReg);
vecMap.init(TheISA::NumVecRegs, &(freeList->vecList), (RegIndex)-1);
vecMap.init(regClasses.at(VecRegClass), &(freeList->vecList),
(RegIndex)-1);
vecElemMap.init(TheISA::NumVecRegs * TheISA::NumVecElemPerVecReg,
&(freeList->vecElemList), (RegIndex)-1);
vecElemMap.init(regClasses.at(VecElemClass), &(freeList->vecElemList),
(RegIndex)-1);
predMap.init(TheISA::NumVecPredRegs, &(freeList->predList), (RegIndex)-1);
predMap.init(regClasses.at(VecPredRegClass), &(freeList->predList),
(RegIndex)-1);
ccMap.init(TheISA::NumCCRegs, &(freeList->ccList), (RegIndex)-1);
ccMap.init(regClasses.at(CCRegClass), &(freeList->ccList), (RegIndex)-1);
}
@@ -138,7 +143,7 @@ UnifiedRenameMap::switchFreeList(UnifiedFreeList* freeList)
panic_if(freeList->hasFreeVecElems(),
"The free list is already tracking Vec elems");
panic_if(freeList->numFreeVecRegs() !=
regFile->numVecPhysRegs() - TheISA::NumVecRegs,
regFile->numVecPhysRegs() - vecMap.numArchRegs(),
"The free list has lost vector registers");
/* Split the free regs. */
@@ -154,12 +159,11 @@ UnifiedRenameMap::switchFreeList(UnifiedFreeList* freeList)
panic_if(freeList->hasFreeVecRegs(),
"The free list is already tracking full Vec");
panic_if(freeList->numFreeVecElems() !=
regFile->numVecElemPhysRegs() -
TheISA::NumVecRegs * TheISA::NumVecElemPerVecReg,
regFile->numVecElemPhysRegs() - vecElemMap.numArchRegs(),
"The free list has lost vector register elements");
auto range = regFile->getRegIds(VecRegClass);
freeList->addRegs(range.first + TheISA::NumVecRegs, range.second);
freeList->addRegs(range.first + vecMap.numArchRegs(), range.second);
/* We remove the elems from the free list. */
while (freeList->hasFreeVecElems())
@@ -198,23 +202,26 @@ UnifiedRenameMap::switchMode(VecMode newVecMode)
* 2.- Replace the contents of the register file with the vectors
* 3.- Set the remaining registers as free
*/
TheISA::VecRegContainer new_RF[TheISA::NumVecRegs];
for (uint32_t i = 0; i < TheISA::NumVecRegs; i++) {
TheISA::VecRegContainer new_RF[vecMap.numArchRegs()];
const size_t numVecs = vecMap.numArchRegs();
const size_t numElems = vecElemMap.numArchRegs();
const size_t elemsPerVec = numElems / numVecs;
for (uint32_t i = 0; i < numVecs; i++) {
TheISA::VecReg dst = new_RF[i].as<TheISA::VecElem>();
for (uint32_t l = 0; l < TheISA::NumVecElemPerVecReg; l++) {
for (uint32_t l = 0; l < elemsPerVec; l++) {
RegId s_rid(VecElemClass, i, l);
PhysRegIdPtr s_prid = vecElemMap.lookup(s_rid);
dst[l] = regFile->readVecElem(s_prid);
}
}
for (uint32_t i = 0; i < TheISA::NumVecRegs; i++) {
for (uint32_t i = 0; i < numVecs; i++) {
PhysRegId pregId(VecRegClass, i, 0);
regFile->setVecReg(regFile->getTrueId(&pregId), new_RF[i]);
}
auto range = regFile->getRegIds(VecRegClass);
for (uint32_t i = 0; i < TheISA::NumVecRegs; i++) {
for (uint32_t i = 0; i < numVecs; i++) {
setEntry(RegId(VecRegClass, i), &(*(range.first + i)));
}

View File

@@ -90,14 +90,13 @@ class SimpleRenameMap
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);
void init(const RegClassInfo &reg_class_info, SimpleFreeList *_freeList,
RegIndex _zeroReg);
/**
* Pair of a physical register and a physical register. Used to
@@ -144,6 +143,8 @@ class SimpleRenameMap
/** Return the number of free entries on the associated free list. */
unsigned numFreeEntries() const { return freeList->numFreeRegs(); }
size_t numArchRegs() const { return map.size(); }
/** Forward begin/cbegin to the map. */
/** @{ */
iterator begin() { return map.begin(); }
@@ -207,7 +208,8 @@ class UnifiedRenameMap
~UnifiedRenameMap() {};
/** Initializes rename map with given parameters. */
void init(PhysRegFile *_regFile,
void init(const BaseISA::RegClasses &regClasses,
PhysRegFile *_regFile,
RegIndex _intZeroReg,
RegIndex _floatZeroReg,
UnifiedFreeList *freeList,

View File

@@ -61,6 +61,17 @@ enum RegClass {
MiscRegClass ///< Control (misc) register
};
class RegClassInfo
{
private:
size_t _size;
public:
RegClassInfo(size_t new_size) : _size(new_size) {}
size_t size() const { return _size; }
};
/** Number of register classes.
* This value is not part of the enum, because putting it there makes the
* compiler complain about unhandled cases in some switch statements.

View File

@@ -74,22 +74,19 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
htmTransactionStarts(0), htmTransactionStops(0)
{
assert(isa);
const auto &regClasses = isa->regClasses();
intRegs.resize(regClasses.at(IntRegClass).size());
floatRegs.resize(regClasses.at(FloatRegClass).size());
vecRegs.resize(regClasses.at(VecRegClass).size());
vecPredRegs.resize(regClasses.at(VecPredRegClass).size());
ccRegs.resize(regClasses.at(CCRegClass).size());
clearArchRegs();
}
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
BaseMMU *_mmu, BaseISA *_isa)
: ThreadState(_cpu, _thread_num, NULL),
isa(dynamic_cast<TheISA::ISA *>(_isa)),
predicate(true), memAccPredicate(true),
comInstEventQueue("instruction-based event queue"),
system(_sys), mmu(_mmu), decoder(isa),
htmTransactionStarts(0), htmTransactionStops(0)
{
assert(isa);
clearArchRegs();
}
: SimpleThread(_cpu, _thread_num, _sys, nullptr, _mmu, _isa)
{}
void
SimpleThread::takeOverFrom(ThreadContext *oldContext)

View File

@@ -42,7 +42,8 @@
#ifndef __CPU_SIMPLE_THREAD_HH__
#define __CPU_SIMPLE_THREAD_HH__
#include <array>
#include <algorithm>
#include <vector>
#include "arch/decoder.hh"
#include "arch/generic/htm.hh"
@@ -93,12 +94,11 @@ class SimpleThread : public ThreadState, public ThreadContext
typedef ThreadContext::Status Status;
protected:
std::array<RegVal, TheISA::NumFloatRegs> floatRegs;
std::array<RegVal, TheISA::NumIntRegs> intRegs;
std::array<TheISA::VecRegContainer, TheISA::NumVecRegs> vecRegs;
std::array<TheISA::VecPredRegContainer, TheISA::NumVecPredRegs>
vecPredRegs;
std::array<RegVal, TheISA::NumCCRegs> ccRegs;
std::vector<RegVal> floatRegs;
std::vector<RegVal> intRegs;
std::vector<TheISA::VecRegContainer> vecRegs;
std::vector<TheISA::VecPredRegContainer> vecPredRegs;
std::vector<RegVal> ccRegs;
TheISA::ISA *const isa; // one "instance" of the current ISA.
TheISA::PCState _pcState;
@@ -253,13 +253,13 @@ class SimpleThread : public ThreadState, public ThreadContext
clearArchRegs() override
{
_pcState = 0;
intRegs.fill(0);
floatRegs.fill(0);
std::fill(intRegs.begin(), intRegs.end(), 0);
std::fill(floatRegs.begin(), floatRegs.end(), 0);
for (auto &vec_reg: vecRegs)
vec_reg.zero();
for (auto &pred_reg: vecPredRegs)
pred_reg.reset();
ccRegs.fill(0);
std::fill(ccRegs.begin(), ccRegs.end(), 0);
isa->clear();
}
@@ -270,8 +270,8 @@ class SimpleThread : public ThreadState, public ThreadContext
readIntReg(RegIndex reg_idx) const override
{
int flatIndex = isa->flattenIntIndex(reg_idx);
assert(flatIndex < TheISA::NumIntRegs);
uint64_t regVal(readIntRegFlat(flatIndex));
assert(flatIndex < intRegs.size());
uint64_t regVal = readIntRegFlat(flatIndex);
DPRINTF(IntRegs, "Reading int reg %d (%d) as %#x.\n",
reg_idx, flatIndex, regVal);
return regVal;
@@ -281,8 +281,8 @@ class SimpleThread : public ThreadState, public ThreadContext
readFloatReg(RegIndex reg_idx) const override
{
int flatIndex = isa->flattenFloatIndex(reg_idx);
assert(flatIndex < TheISA::NumFloatRegs);
RegVal regVal(readFloatRegFlat(flatIndex));
assert(flatIndex < floatRegs.size());
RegVal regVal = readFloatRegFlat(flatIndex);
DPRINTF(FloatRegs, "Reading float reg %d (%d) bits as %#x.\n",
reg_idx, flatIndex, regVal);
return regVal;
@@ -292,7 +292,7 @@ class SimpleThread : public ThreadState, public ThreadContext
readVecReg(const RegId& reg) const override
{
int flatIndex = isa->flattenVecIndex(reg.index());
assert(flatIndex < TheISA::NumVecRegs);
assert(flatIndex < vecRegs.size());
const TheISA::VecRegContainer& regVal = readVecRegFlat(flatIndex);
DPRINTF(VecRegs, "Reading vector reg %d (%d) as %s.\n",
reg.index(), flatIndex, regVal);
@@ -303,7 +303,7 @@ class SimpleThread : public ThreadState, public ThreadContext
getWritableVecReg(const RegId& reg) override
{
int flatIndex = isa->flattenVecIndex(reg.index());
assert(flatIndex < TheISA::NumVecRegs);
assert(flatIndex < vecRegs.size());
TheISA::VecRegContainer& regVal = getWritableVecRegFlat(flatIndex);
DPRINTF(VecRegs, "Reading vector reg %d (%d) as %s for modify.\n",
reg.index(), flatIndex, regVal);
@@ -314,7 +314,7 @@ class SimpleThread : public ThreadState, public ThreadContext
readVecElem(const RegId &reg) const override
{
int flatIndex = isa->flattenVecElemIndex(reg.index());
assert(flatIndex < TheISA::NumVecRegs);
assert(flatIndex < vecRegs.size());
const TheISA::VecElem& regVal =
readVecElemFlat(flatIndex, reg.elemIndex());
DPRINTF(VecRegs, "Reading element %d of vector reg %d (%d) as"
@@ -326,7 +326,7 @@ class SimpleThread : public ThreadState, public ThreadContext
readVecPredReg(const RegId &reg) const override
{
int flatIndex = isa->flattenVecPredIndex(reg.index());
assert(flatIndex < TheISA::NumVecPredRegs);
assert(flatIndex < vecPredRegs.size());
const TheISA::VecPredRegContainer& regVal =
readVecPredRegFlat(flatIndex);
DPRINTF(VecPredRegs, "Reading predicate reg %d (%d) as %s.\n",
@@ -338,7 +338,7 @@ class SimpleThread : public ThreadState, public ThreadContext
getWritableVecPredReg(const RegId &reg) override
{
int flatIndex = isa->flattenVecPredIndex(reg.index());
assert(flatIndex < TheISA::NumVecPredRegs);
assert(flatIndex < vecPredRegs.size());
TheISA::VecPredRegContainer& regVal =
getWritableVecPredRegFlat(flatIndex);
DPRINTF(VecPredRegs,
@@ -352,7 +352,7 @@ class SimpleThread : public ThreadState, public ThreadContext
{
int flatIndex = isa->flattenCCIndex(reg_idx);
assert(0 <= flatIndex);
assert(flatIndex < TheISA::NumCCRegs);
assert(flatIndex < ccRegs.size());
uint64_t regVal(readCCRegFlat(flatIndex));
DPRINTF(CCRegs, "Reading CC reg %d (%d) as %#x.\n",
reg_idx, flatIndex, regVal);
@@ -363,7 +363,7 @@ class SimpleThread : public ThreadState, public ThreadContext
setIntReg(RegIndex reg_idx, RegVal val) override
{
int flatIndex = isa->flattenIntIndex(reg_idx);
assert(flatIndex < TheISA::NumIntRegs);
assert(flatIndex < intRegs.size());
DPRINTF(IntRegs, "Setting int reg %d (%d) to %#x.\n",
reg_idx, flatIndex, val);
setIntRegFlat(flatIndex, val);
@@ -373,10 +373,10 @@ class SimpleThread : public ThreadState, public ThreadContext
setFloatReg(RegIndex reg_idx, RegVal val) override
{
int flatIndex = isa->flattenFloatIndex(reg_idx);
assert(flatIndex < TheISA::NumFloatRegs);
assert(flatIndex < floatRegs.size());
// XXX: Fix array out of bounds compiler error for gem5.fast
// when checkercpu enabled
if (flatIndex < TheISA::NumFloatRegs)
if (flatIndex < floatRegs.size())
setFloatRegFlat(flatIndex, val);
DPRINTF(FloatRegs, "Setting float reg %d (%d) bits to %#x.\n",
reg_idx, flatIndex, val);
@@ -386,7 +386,7 @@ class SimpleThread : public ThreadState, public ThreadContext
setVecReg(const RegId &reg, const TheISA::VecRegContainer &val) override
{
int flatIndex = isa->flattenVecIndex(reg.index());
assert(flatIndex < TheISA::NumVecRegs);
assert(flatIndex < vecRegs.size());
setVecRegFlat(flatIndex, val);
DPRINTF(VecRegs, "Setting vector reg %d (%d) to %s.\n",
reg.index(), flatIndex, val);
@@ -396,7 +396,7 @@ class SimpleThread : public ThreadState, public ThreadContext
setVecElem(const RegId &reg, const TheISA::VecElem &val) override
{
int flatIndex = isa->flattenVecElemIndex(reg.index());
assert(flatIndex < TheISA::NumVecRegs);
assert(flatIndex < vecRegs.size());
setVecElemFlat(flatIndex, reg.elemIndex(), val);
DPRINTF(VecRegs, "Setting element %d of vector reg %d (%d) to"
" %#x.\n", reg.elemIndex(), reg.index(), flatIndex, val);
@@ -407,7 +407,7 @@ class SimpleThread : public ThreadState, public ThreadContext
const TheISA::VecPredRegContainer &val) override
{
int flatIndex = isa->flattenVecPredIndex(reg.index());
assert(flatIndex < TheISA::NumVecPredRegs);
assert(flatIndex < vecPredRegs.size());
setVecPredRegFlat(flatIndex, val);
DPRINTF(VecPredRegs, "Setting predicate reg %d (%d) to %s.\n",
reg.index(), flatIndex, val.print());
@@ -417,7 +417,7 @@ class SimpleThread : public ThreadState, public ThreadContext
setCCReg(RegIndex reg_idx, RegVal val) override
{
int flatIndex = isa->flattenCCIndex(reg_idx);
assert(flatIndex < TheISA::NumCCRegs);
assert(flatIndex < ccRegs.size());
DPRINTF(CCRegs, "Setting CC reg %d (%d) to %#x.\n",
reg_idx, flatIndex, val);
setCCRegFlat(flatIndex, val);

View File

@@ -54,10 +54,12 @@
void
ThreadContext::compare(ThreadContext *one, ThreadContext *two)
{
const auto &regClasses = one->getIsaPtr()->regClasses();
DPRINTF(Context, "Comparing thread contexts\n");
// First loop through the integer registers.
for (int i = 0; i < TheISA::NumIntRegs; ++i) {
for (int i = 0; i < regClasses.at(IntRegClass).size(); ++i) {
RegVal t1 = one->readIntReg(i);
RegVal t2 = two->readIntReg(i);
if (t1 != t2)
@@ -66,7 +68,7 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two)
}
// Then loop through the floating point registers.
for (int i = 0; i < TheISA::NumFloatRegs; ++i) {
for (int i = 0; i < regClasses.at(FloatRegClass).size(); ++i) {
RegVal t1 = one->readFloatReg(i);
RegVal t2 = two->readFloatReg(i);
if (t1 != t2)
@@ -75,7 +77,7 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two)
}
// Then loop through the vector registers.
for (int i = 0; i < TheISA::NumVecRegs; ++i) {
for (int i = 0; i < regClasses.at(VecRegClass).size(); ++i) {
RegId rid(VecRegClass, i);
const TheISA::VecRegContainer& t1 = one->readVecReg(rid);
const TheISA::VecRegContainer& t2 = two->readVecReg(rid);
@@ -85,7 +87,7 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two)
}
// Then loop through the predicate registers.
for (int i = 0; i < TheISA::NumVecPredRegs; ++i) {
for (int i = 0; i < regClasses.at(VecPredRegClass).size(); ++i) {
RegId rid(VecPredRegClass, i);
const TheISA::VecPredRegContainer& t1 = one->readVecPredReg(rid);
const TheISA::VecPredRegContainer& t2 = two->readVecPredReg(rid);
@@ -94,7 +96,7 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two)
i, t1, t2);
}
for (int i = 0; i < TheISA::NumMiscRegs; ++i) {
for (int i = 0; i < regClasses.at(MiscRegClass).size(); ++i) {
RegVal t1 = one->readMiscRegNoEffect(i);
RegVal t2 = two->readMiscRegNoEffect(i);
if (t1 != t2)
@@ -103,7 +105,7 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two)
}
// loop through the Condition Code registers.
for (int i = 0; i < TheISA::NumCCRegs; ++i) {
for (int i = 0; i < regClasses.at(CCRegClass).size(); ++i) {
RegVal t1 = one->readCCReg(i);
RegVal t2 = two->readCCReg(i);
if (t1 != t2)
@@ -141,36 +143,45 @@ ThreadContext::quiesceTick(Tick resume)
void
serialize(const ThreadContext &tc, CheckpointOut &cp)
{
RegVal floatRegs[TheISA::NumFloatRegs];
for (int i = 0; i < TheISA::NumFloatRegs; ++i)
// Cast away the const so we can get the non-const ISA ptr, which we then
// use to get the const register classes.
auto &nc_tc = const_cast<ThreadContext &>(tc);
const auto &regClasses = nc_tc.getIsaPtr()->regClasses();
const size_t numFloats = regClasses.at(FloatRegClass).size();
RegVal floatRegs[numFloats];
for (int i = 0; i < numFloats; ++i)
floatRegs[i] = tc.readFloatRegFlat(i);
// This is a bit ugly, but needed to maintain backwards
// compatibility.
arrayParamOut(cp, "floatRegs.i", floatRegs, TheISA::NumFloatRegs);
arrayParamOut(cp, "floatRegs.i", floatRegs, numFloats);
std::vector<TheISA::VecRegContainer> vecRegs(TheISA::NumVecRegs);
for (int i = 0; i < TheISA::NumVecRegs; ++i) {
const size_t numVecs = regClasses.at(VecRegClass).size();
std::vector<TheISA::VecRegContainer> vecRegs(numVecs);
for (int i = 0; i < numVecs; ++i) {
vecRegs[i] = tc.readVecRegFlat(i);
}
SERIALIZE_CONTAINER(vecRegs);
std::vector<TheISA::VecPredRegContainer>
vecPredRegs(TheISA::NumVecPredRegs);
for (int i = 0; i < TheISA::NumVecPredRegs; ++i) {
const size_t numPreds = regClasses.at(VecPredRegClass).size();
std::vector<TheISA::VecPredRegContainer> vecPredRegs(numPreds);
for (int i = 0; i < numPreds; ++i) {
vecPredRegs[i] = tc.readVecPredRegFlat(i);
}
SERIALIZE_CONTAINER(vecPredRegs);
RegVal intRegs[TheISA::NumIntRegs];
for (int i = 0; i < TheISA::NumIntRegs; ++i)
const size_t numInts = regClasses.at(IntRegClass).size();
RegVal intRegs[numInts];
for (int i = 0; i < numInts; ++i)
intRegs[i] = tc.readIntRegFlat(i);
SERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
SERIALIZE_ARRAY(intRegs, numInts);
if (TheISA::NumCCRegs) {
RegVal ccRegs[TheISA::NumCCRegs];
for (int i = 0; i < TheISA::NumCCRegs; ++i)
const size_t numCcs = regClasses.at(CCRegClass).size();
if (numCcs) {
RegVal ccRegs[numCcs];
for (int i = 0; i < numCcs; ++i)
ccRegs[i] = tc.readCCRegFlat(i);
SERIALIZE_ARRAY(ccRegs, TheISA::NumCCRegs);
SERIALIZE_ARRAY(ccRegs, numCcs);
}
tc.pcState().serialize(cp);
@@ -181,35 +192,41 @@ serialize(const ThreadContext &tc, CheckpointOut &cp)
void
unserialize(ThreadContext &tc, CheckpointIn &cp)
{
RegVal floatRegs[TheISA::NumFloatRegs];
const auto &regClasses = tc.getIsaPtr()->regClasses();
const size_t numFloats = regClasses.at(FloatRegClass).size();
RegVal floatRegs[numFloats];
// This is a bit ugly, but needed to maintain backwards
// compatibility.
arrayParamIn(cp, "floatRegs.i", floatRegs, TheISA::NumFloatRegs);
for (int i = 0; i < TheISA::NumFloatRegs; ++i)
arrayParamIn(cp, "floatRegs.i", floatRegs, numFloats);
for (int i = 0; i < numFloats; ++i)
tc.setFloatRegFlat(i, floatRegs[i]);
std::vector<TheISA::VecRegContainer> vecRegs(TheISA::NumVecRegs);
const size_t numVecs = regClasses.at(VecRegClass).size();
std::vector<TheISA::VecRegContainer> vecRegs(numVecs);
UNSERIALIZE_CONTAINER(vecRegs);
for (int i = 0; i < TheISA::NumVecRegs; ++i) {
for (int i = 0; i < numVecs; ++i) {
tc.setVecRegFlat(i, vecRegs[i]);
}
std::vector<TheISA::VecPredRegContainer>
vecPredRegs(TheISA::NumVecPredRegs);
const size_t numPreds = regClasses.at(VecPredRegClass).size();
std::vector<TheISA::VecPredRegContainer> vecPredRegs(numPreds);
UNSERIALIZE_CONTAINER(vecPredRegs);
for (int i = 0; i < TheISA::NumVecPredRegs; ++i) {
for (int i = 0; i < numPreds; ++i) {
tc.setVecPredRegFlat(i, vecPredRegs[i]);
}
RegVal intRegs[TheISA::NumIntRegs];
UNSERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
for (int i = 0; i < TheISA::NumIntRegs; ++i)
const size_t numInts = regClasses.at(IntRegClass).size();
RegVal intRegs[numInts];
UNSERIALIZE_ARRAY(intRegs, numInts);
for (int i = 0; i < numInts; ++i)
tc.setIntRegFlat(i, intRegs[i]);
if (TheISA::NumCCRegs) {
RegVal ccRegs[TheISA::NumCCRegs];
UNSERIALIZE_ARRAY(ccRegs, TheISA::NumCCRegs);
for (int i = 0; i < TheISA::NumCCRegs; ++i)
const size_t numCcs = regClasses.at(CCRegClass).size();
if (numCcs) {
RegVal ccRegs[numCcs];
UNSERIALIZE_ARRAY(ccRegs, numCcs);
for (int i = 0; i < numCcs; ++i)
tc.setCCRegFlat(i, ccRegs[i]);
}