cpu: Simplify the rename interface and use RegId

With the hierarchical RegId there are a lot of functions that are
redundant now.

The idea behind the simplification is that instead of having the regId,
telling which kind of register read/write/rename/lookup/etc. and then
the function panic_if'ing if the regId is not of the appropriate type,
we provide an interface that decides what kind of register to read
depending on the register type of the given regId.

Change-Id: I7d52e9e21fc01205ae365d86921a4ceb67a57178
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
[ Fix RISCV build issues ]
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2702
This commit is contained in:
Rekai Gonzalez-Alberquilla
2017-04-05 13:14:34 -05:00
committed by Andreas Sandberg
parent 43d833246f
commit a473b5a6eb
64 changed files with 741 additions and 749 deletions

View File

@@ -38,6 +38,7 @@
#include "arch/alpha/registers.hh"
#include "arch/alpha/types.hh"
#include "base/types.hh"
#include "cpu/reg_class.hh"
#include "sim/sim_object.hh"
#include "sim/system.hh"
@@ -95,6 +96,8 @@ namespace AlphaISA
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
RegId flattenRegId(const RegId& regId) const { return regId; }
int
flattenIntIndex(int reg) const
{

View File

@@ -130,7 +130,7 @@ output decoder {{
Jump::branchTarget(ThreadContext *tc) const
{
PCState pc = tc->pcState();
uint64_t Rb = tc->readIntReg(_srcRegIdx[0].regIdx);
uint64_t Rb = tc->readIntReg(_srcRegIdx[0].index());
pc.set((Rb & ~3) | (pc.pc() & 1));
return pc;
}

View File

@@ -149,7 +149,7 @@ output decoder {{
#ifndef SS_COMPATIBLE_DISASSEMBLY
std::string suffix("");
suffix += ((_destRegIdx[0].regClass == FloatRegClass)
suffix += ((_destRegIdx[0].isFloatReg())
? fpTrappingModeSuffix[trappingMode]
: intTrappingModeSuffix[trappingMode]);
suffix += roundingModeSuffix[roundingMode];

View File

@@ -246,11 +246,11 @@ output decoder {{
void
AlphaStaticInst::printReg(std::ostream &os, RegId reg) const
{
if (reg.regClass == IntRegClass) {
ccprintf(os, "r%d", reg.regIdx);
if (reg.isIntReg()) {
ccprintf(os, "r%d", reg.index());
}
else {
ccprintf(os, "f%d", reg.regIdx);
ccprintf(os, "f%d", reg.index());
}
}

View File

@@ -51,16 +51,16 @@ MrsOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
ss << ", ";
bool foundPsr = false;
for (unsigned i = 0; i < numSrcRegs(); i++) {
RegId reg = srcRegIdx(i);
if (reg.regClass != MiscRegClass) {
const RegId& reg = srcRegIdx(i);
if (!reg.isMiscReg()) {
continue;
}
if (reg.regIdx == MISCREG_CPSR) {
if (reg.index() == MISCREG_CPSR) {
ss << "cpsr";
foundPsr = true;
break;
}
if (reg.regIdx == MISCREG_SPSR) {
if (reg.index() == MISCREG_SPSR) {
ss << "spsr";
foundPsr = true;
break;
@@ -79,16 +79,16 @@ MsrBase::printMsrBase(std::ostream &os) const
bool apsr = false;
bool foundPsr = false;
for (unsigned i = 0; i < numDestRegs(); i++) {
RegId reg = destRegIdx(i);
if (reg.regClass != MiscRegClass) {
const RegId& reg = destRegIdx(i);
if (!reg.isMiscReg()) {
continue;
}
if (reg.regIdx == MISCREG_CPSR) {
if (reg.index() == MISCREG_CPSR) {
os << "cpsr_";
foundPsr = true;
break;
}
if (reg.regIdx == MISCREG_SPSR) {
if (reg.index() == MISCREG_SPSR) {
if (bits(byteMask, 1, 0)) {
os << "spsr_";
} else {

View File

@@ -177,6 +177,22 @@ namespace ArmISA
void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
RegId
flattenRegId(const RegId& regId) const
{
switch (regId.classValue()) {
case IntRegClass:
return RegId(IntRegClass, flattenIntIndex(regId.index()));
case FloatRegClass:
return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
case CCRegClass:
return RegId(CCRegClass, flattenCCIndex(regId.index()));
case MiscRegClass:
return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
}
return RegId();
}
int
flattenIntIndex(int reg) const
{

View File

@@ -328,7 +328,7 @@ let {{
buildDataXImmInst("mrs", '''
MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->
flattenMiscIndex(op1);
flattenRegId(RegId(MiscRegClass, op1)).index();
CPSR cpsr = Cpsr;
ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
%s
@@ -346,7 +346,7 @@ let {{
buildDataXImmInst("msr", '''
MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->
flattenMiscIndex(dest);
flattenRegId(RegId(MiscRegClass, dest)).index();
CPSR cpsr = Cpsr;
ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
%s
@@ -362,7 +362,8 @@ let {{
''')
msrdczva_ea_code = '''
MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->flattenMiscIndex(dest);
MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->flattenRegId(
RegId(MiscRegClass, dest)).index();
CPSR cpsr = Cpsr;
ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
'''
@@ -391,7 +392,8 @@ let {{
buildDataXImmInst("msrSP", '''
if (!canWriteAArch64SysReg(
(MiscRegIndex) xc->tcBase()->flattenMiscIndex(dest),
(MiscRegIndex) xc->tcBase()->flattenRegId(
RegId(MiscRegClass, dest)).index(),
Scr64, Cpsr, xc->tcBase())) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
@@ -401,7 +403,8 @@ let {{
buildDataXImmInst("msrDAIFSet", '''
if (!canWriteAArch64SysReg(
(MiscRegIndex) xc->tcBase()->flattenMiscIndex(dest),
(MiscRegIndex) xc->tcBase()->flattenRegId(
RegId(MiscRegClass, dest)).index(),
Scr64, Cpsr, xc->tcBase())) {
return std::make_shared<UndefinedInstruction>(
machInst, 0, EC_TRAPPED_MSR_MRS_64,
@@ -414,7 +417,8 @@ let {{
buildDataXImmInst("msrDAIFClr", '''
if (!canWriteAArch64SysReg(
(MiscRegIndex) xc->tcBase()->flattenMiscIndex(dest),
(MiscRegIndex) xc->tcBase()->flattenRegId(
RegId(MiscRegClass, dest)).index(),
Scr64, Cpsr, xc->tcBase())) {
return std::make_shared<UndefinedInstruction>(
machInst, 0, EC_TRAPPED_MSR_MRS_64,

View File

@@ -224,7 +224,7 @@ let {{
if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
HCR hcr = Hcr;
bool hypTrap = false;
switch(xc->tcBase()->flattenMiscIndex(op1)) {
switch(xc->tcBase()->flattenRegId(RegId(MiscRegClass, op1)).index()) {
case MISCREG_FPSID:
hypTrap = hcr.tid0;
break;

View File

@@ -813,7 +813,8 @@ let {{
exec_output += PredOpExecute.subst(bfiIop)
mrc14code = '''
MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenMiscIndex(op1);
MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
RegId(MiscRegClass, op1)).index();
bool can_read, undefined;
std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
if (!can_read || undefined) {
@@ -837,7 +838,8 @@ let {{
mcr14code = '''
MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenMiscIndex(dest);
MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
RegId(MiscRegClass, dest)).index();
bool can_write, undefined;
std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
if (undefined || !can_write) {
@@ -862,7 +864,8 @@ let {{
mrc15code = '''
int preFlatOp1 = flattenMiscRegNsBanked(op1, xc->tcBase());
MiscRegIndex miscReg = (MiscRegIndex)
xc->tcBase()->flattenMiscIndex(preFlatOp1);
xc->tcBase()->flattenRegId(RegId(MiscRegClass,
preFlatOp1)).index();
bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr,
Hcptr, imm);
bool can_read, undefined;
@@ -893,7 +896,8 @@ let {{
mcr15code = '''
int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase());
MiscRegIndex miscReg = (MiscRegIndex)
xc->tcBase()->flattenMiscIndex(preFlatDest);
xc->tcBase()->flattenRegId(RegId(MiscRegClass,
preFlatDest)).index();
bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr,
Hcptr, imm);
bool can_write, undefined;
@@ -925,7 +929,8 @@ let {{
mrrc15code = '''
int preFlatOp1 = flattenMiscRegNsBanked(op1, xc->tcBase());
MiscRegIndex miscReg = (MiscRegIndex)
xc->tcBase()->flattenMiscIndex(preFlatOp1);
xc->tcBase()->flattenRegId(RegId(MiscRegClass,
preFlatOp1)).index();
bool hypTrap = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm);
bool can_read, undefined;
std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
@@ -955,7 +960,8 @@ let {{
mcrr15code = '''
int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase());
MiscRegIndex miscReg = (MiscRegIndex)
xc->tcBase()->flattenMiscIndex(preFlatDest);
xc->tcBase()->flattenRegId(RegId(MiscRegClass,
preFlatDest)).index();
bool hypTrap = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm);
bool can_write, undefined;
std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);

View File

@@ -37,6 +37,7 @@
#include "arch/mips/registers.hh"
#include "arch/mips/types.hh"
#include "cpu/reg_class.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
@@ -165,6 +166,8 @@ namespace MipsISA
ISA(Params *p);
RegId flattenRegId(const RegId& regId) const { return regId; }
int
flattenIntIndex(int reg) const
{

View File

@@ -72,11 +72,11 @@ output decoder {{
void MipsStaticInst::printReg(std::ostream &os, RegId reg) const
{
if (reg.regClass == IntRegClass) {
ccprintf(os, "r%d", reg.regIdx);
if (reg.isIntReg()) {
ccprintf(os, "r%d", reg.index());
}
else {
ccprintf(os, "f%d", reg.regIdx);
ccprintf(os, "f%d", reg.index());
}
}

View File

@@ -257,9 +257,9 @@ output decoder {{
ccprintf(ss, "%-10s ", mnemonic);
if (_numDestRegs > 0 && _destRegIdx[0].regIdx < 32) {
if (_numDestRegs > 0 && _destRegIdx[0].index() < 32) {
printReg(ss, _destRegIdx[0]);
} else if (_numSrcRegs > 0 && _srcRegIdx[0].regIdx < 32) {
} else if (_numSrcRegs > 0 && _srcRegIdx[0].index() < 32) {
printReg(ss, _srcRegIdx[0]);
}
@@ -272,9 +272,9 @@ output decoder {{
ccprintf(ss, "%-10s ", mnemonic);
if (_numDestRegs > 0 && _destRegIdx[0].regIdx < 32) {
if (_numDestRegs > 0 && _destRegIdx[0].index() < 32) {
printReg(ss, _destRegIdx[0]);
} else if (_numSrcRegs > 0 && _srcRegIdx[0].regIdx < 32) {
} else if (_numSrcRegs > 0 && _srcRegIdx[0].index() < 32) {
printReg(ss, _srcRegIdx[0]);
}
@@ -287,9 +287,9 @@ output decoder {{
ccprintf(ss, "%-10s ", mnemonic);
if (_numDestRegs > 0 && _destRegIdx[0].regIdx < 32) {
if (_numDestRegs > 0 && _destRegIdx[0].index() < 32) {
printReg(ss, _destRegIdx[0]);
} else if (_numSrcRegs > 0 && _srcRegIdx[0].regIdx < 32) {
} else if (_numSrcRegs > 0 && _srcRegIdx[0].index() < 32) {
printReg(ss, _srcRegIdx[0]);
}

View File

@@ -153,7 +153,7 @@ BranchNonPCRelCond::generateDisassembly(Addr pc,
PowerISA::PCState
BranchRegCond::branchTarget(ThreadContext *tc) const
{
uint32_t regVal = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1].regIdx);
uint32_t regVal = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1].index());
return regVal & 0xfffffffc;
}

View File

@@ -38,15 +38,12 @@ using namespace PowerISA;
void
PowerStaticInst::printReg(std::ostream &os, RegId reg) const
{
switch (reg.regClass) {
case IntRegClass:
ccprintf(os, "r%d", reg.regIdx);
break;
case FloatRegClass:
ccprintf(os, "f%d", reg.regIdx);
break;
case MiscRegClass:
switch (reg.regIdx) {
if (reg.isIntReg())
ccprintf(os, "r%d", reg.index());
else if (reg.isFloatReg())
ccprintf(os, "f%d", reg.index());
else if (reg.isMiscReg())
switch (reg.index()) {
case 0: ccprintf(os, "cr"); break;
case 1: ccprintf(os, "xer"); break;
case 2: ccprintf(os, "lr"); break;
@@ -54,9 +51,8 @@ PowerStaticInst::printReg(std::ostream &os, RegId reg) const
default: ccprintf(os, "unknown_reg");
break;
}
case CCRegClass:
else if (reg.isCCReg())
panic("printReg: POWER does not implement CCRegClass\n");
}
}
std::string

View File

@@ -36,6 +36,7 @@
#include "arch/power/registers.hh"
#include "arch/power/types.hh"
#include "base/misc.hh"
#include "cpu/reg_class.hh"
#include "sim/sim_object.hh"
struct PowerISAParams;
@@ -86,6 +87,8 @@ class ISA : public SimObject
fatal("Power does not currently have any misc regs defined\n");
}
RegId flattenRegId(const RegId& regId) const { return regId; }
int
flattenIntIndex(int reg) const
{

View File

@@ -44,6 +44,7 @@
#include "arch/riscv/registers.hh"
#include "arch/riscv/types.hh"
#include "base/misc.hh"
#include "cpu/reg_class.hh"
#include "sim/sim_object.hh"
struct RiscvISAParams;
@@ -78,6 +79,12 @@ class ISA : public SimObject
void
setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
RegId
flattenRegId(const RegId &regId) const
{
return regId;
}
int
flattenIntIndex(int reg) const
{

View File

@@ -70,13 +70,12 @@ output decoder {{
std::string
RiscvStaticInst::regName(RegId reg) const
{
switch (reg.regClass) {
case IntRegClass:
return std::string(RegisterNames[reg.regIdx]);
case FloatRegClass:
return std::string("f") + std::to_string(reg.regIdx);
default:
return csprintf("unknown[%i/%i]", reg.regClass, reg.regIdx);
if (reg.isIntReg()) {
return std::string(RegisterNames[reg.index()]);
} else if (reg.isFloatReg()) {
return std::string("f") + std::to_string(reg.index());
} else {
return csprintf("%s{%i}", reg.className(), reg.index());
}
}
}};

View File

@@ -210,7 +210,7 @@ output decoder {{
Jump::branchTarget(ThreadContext *tc) const
{
PCState pc = tc->pcState();
IntReg Rs1 = tc->readIntReg(_srcRegIdx[0].regIdx);
IntReg Rs1 = tc->readIntReg(_srcRegIdx[0].index());
pc.set((Rs1 + imm)&~0x1);
return pc;
}

View File

@@ -37,6 +37,7 @@
#include "arch/sparc/registers.hh"
#include "arch/sparc/types.hh"
#include "cpu/cpuevent.hh"
#include "cpu/reg_class.hh"
#include "sim/sim_object.hh"
class Checkpoint;
@@ -189,6 +190,22 @@ class ISA : public SimObject
void setMiscReg(int miscReg, const MiscReg val,
ThreadContext *tc);
RegId
flattenRegId(const RegId& regId) const
{
switch (regId.classValue()) {
case IntRegClass:
return RegId(IntRegClass, flattenIntIndex(regId.index()));
case FloatRegClass:
return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
case CCRegClass:
return RegId(CCRegClass, flattenCCIndex(regId.index()));
case MiscRegClass:
return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
}
return regId;
}
int
flattenIntIndex(int reg) const
{

View File

@@ -290,8 +290,8 @@ output decoder {{
const int MaxLocal = 24;
const int MaxInput = 32;
const int MaxMicroReg = 40;
RegIndex reg_idx = reg.regIdx;
if (reg.regClass == IntRegClass) {
RegIndex reg_idx = reg.index();
if (reg.isIntReg()) {
// If we used a register from the next or previous window,
// take out the offset.
while (reg_idx >= MaxMicroReg)
@@ -336,7 +336,7 @@ output decoder {{
break;
}
}
} else if (reg.regClass == FloatRegClass) {
} else if (reg.isFloatReg()) {
ccprintf(os, "%%f%d", reg_idx);
} else {
switch (reg_idx) {

View File

@@ -155,7 +155,7 @@ output decoder {{
IntOp::printPseudoOps(std::ostream &os, Addr pc,
const SymbolTable *symbab) const
{
if (!std::strcmp(mnemonic, "or") && _srcRegIdx[0].regIdx == 0) {
if (!std::strcmp(mnemonic, "or") && _srcRegIdx[0].index() == 0) {
printMnemonic(os, "mov");
printSrcReg(os, 1);
ccprintf(os, ", ");
@@ -170,7 +170,7 @@ output decoder {{
const SymbolTable *symbab) const
{
if (!std::strcmp(mnemonic, "or")) {
if (_numSrcRegs > 0 && _srcRegIdx[0].regIdx == 0) {
if (_numSrcRegs > 0 && _srcRegIdx[0].index() == 0) {
if (imm == 0) {
printMnemonic(os, "clr");
} else {

View File

@@ -84,7 +84,7 @@ output decoder {{
ccprintf(response, ", ");
}
ccprintf(response, "[");
if (_srcRegIdx[!store ? 0 : 1].regIdx != 0) {
if (_srcRegIdx[!store ? 0 : 1].index() != 0) {
printSrcReg(response, !store ? 0 : 1);
ccprintf(response, " + ");
}
@@ -111,7 +111,7 @@ output decoder {{
ccprintf(response, ", ");
}
ccprintf(response, "[");
if (_srcRegIdx[!save ? 0 : 1].regIdx != 0) {
if (_srcRegIdx[!save ? 0 : 1].index() != 0) {
printReg(response, _srcRegIdx[!save ? 0 : 1]);
ccprintf(response, " + ");
}

View File

@@ -155,7 +155,7 @@ output decoder {{
ccprintf(response, " ");
// If the first reg is %g0, don't print it.
// This improves readability
if (_srcRegIdx[0].regIdx != 0) {
if (_srcRegIdx[0].index() != 0) {
printSrcReg(response, 0);
ccprintf(response, ", ");
}
@@ -175,7 +175,7 @@ output decoder {{
ccprintf(response, " ");
// If the first reg is %g0, don't print it.
// This improves readability
if (_srcRegIdx[0].regIdx != 0) {
if (_srcRegIdx[0].index() != 0) {
printSrcReg(response, 0);
ccprintf(response, ", ");
}

View File

@@ -66,7 +66,7 @@ namespace X86ISA
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags,
__opClass),
src1(_src1.regIdx), src2(_src2.regIdx), dest(_dest.regIdx),
src1(_src1.index()), src2(_src2.index()), dest(_dest.index()),
dataSize(_dataSize), spm(_spm)
{}
/*

View File

@@ -75,12 +75,12 @@ namespace X86ISA
Request::FlagsType _memFlags,
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags, __opClass),
scale(_scale), index(_index.regIdx), base(_base.regIdx),
disp(_disp), segment(_segment.regIdx),
scale(_scale), index(_index.index()), base(_base.index()),
disp(_disp), segment(_segment.index()),
dataSize(_dataSize), addressSize(_addressSize),
memFlags(_memFlags | _segment.regIdx)
memFlags(_memFlags | _segment.index())
{
assert(_segment.regIdx < NUM_SEGMENTREGS);
assert(_segment.index() < NUM_SEGMENTREGS);
foldOBit =
(dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
foldABit =
@@ -110,7 +110,7 @@ namespace X86ISA
_scale, _index, _base, _disp, _segment,
_dataSize, _addressSize, _memFlags,
__opClass),
data(_data.regIdx)
data(_data.index())
{
}
@@ -143,8 +143,8 @@ namespace X86ISA
_scale, _index, _base, _disp, _segment,
_dataSize, _addressSize, _memFlags,
__opClass),
dataLow(_dataLow.regIdx),
dataHi(_dataHi.regIdx)
dataLow(_dataLow.index()),
dataHi(_dataHi.index())
{
}

View File

@@ -59,7 +59,7 @@ namespace X86ISA
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags,
__opClass),
src1(_src1.regIdx), dest(_dest.regIdx),
src1(_src1.index()), dest(_dest.index()),
srcSize(_srcSize), destSize(_destSize), ext(_ext)
{}
@@ -102,7 +102,7 @@ namespace X86ISA
MediaOpBase(_machInst, mnem, _instMnem, setFlags,
_src1, _dest, _srcSize, _destSize, _ext,
__opClass),
src2(_src2.regIdx)
src2(_src2.index())
{}
std::string generateDisassembly(Addr pc,

View File

@@ -64,7 +64,7 @@ namespace X86ISA
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags,
__opClass),
src1(_src1.regIdx), dest(_dest.regIdx),
src1(_src1.index()), dest(_dest.index()),
dataSize(_dataSize), ext(_ext)
{
foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
@@ -90,7 +90,7 @@ namespace X86ISA
RegOpBase(_machInst, mnem, _instMnem, setFlags,
_src1, _dest, _dataSize, _ext,
__opClass),
src2(_src2.regIdx)
src2(_src2.index())
{
}

View File

@@ -132,10 +132,9 @@ namespace X86ISA
static const char * microFormats[9] =
{"", "t%db", "t%dw", "", "t%dd", "", "", "", "t%d"};
RegIndex reg_idx = reg.regIdx;
RegIndex reg_idx = reg.index();
switch (reg.regClass) {
case IntRegClass: {
if (reg.isIntReg()) {
const char * suffix = "";
bool fold = reg_idx & IntFoldBit;
reg_idx &= ~IntFoldBit;
@@ -198,10 +197,8 @@ namespace X86ISA
ccprintf(os, microFormats[size], reg_idx - NUM_INTREGS);
}
ccprintf(os, suffix);
break;
}
case FloatRegClass: {
} else if (reg.isFloatReg()) {
if (reg_idx < NumMMXRegs) {
ccprintf(os, "%%mmx%d", reg_idx);
return;
@@ -219,19 +216,15 @@ namespace X86ISA
}
reg_idx -= NumMicroFpRegs;
ccprintf(os, "%%st(%d)", reg_idx);
break;
}
case CCRegClass:
} else if (reg.isCCReg()) {
ccprintf(os, "%%cc%d", reg_idx);
break;
case MiscRegClass:
} else if (reg.isMiscReg()) {
switch (reg_idx) {
default:
ccprintf(os, "%%ctrl%d", reg_idx);
}
break;
}
}

View File

@@ -107,7 +107,7 @@ namespace X86ISA
inline uint64_t merge(uint64_t into, uint64_t val, int size) const
{
X86IntReg reg = into;
if (_destRegIdx[0].regIdx & IntFoldBit)
if (_destRegIdx[0].index() & IntFoldBit)
{
reg.H = val;
return reg;
@@ -138,7 +138,7 @@ namespace X86ISA
{
X86IntReg reg = from;
DPRINTF(X86, "Picking with size %d\n", size);
if (_srcRegIdx[idx].regIdx & IntFoldBit)
if (_srcRegIdx[idx].index() & IntFoldBit)
return reg.H;
switch(size)
{
@@ -159,7 +159,7 @@ namespace X86ISA
{
X86IntReg reg = from;
DPRINTF(X86, "Picking with size %d\n", size);
if (_srcRegIdx[idx].regIdx & IntFoldBit)
if (_srcRegIdx[idx].index() & IntFoldBit)
return reg.SH;
switch(size)
{

View File

@@ -38,6 +38,7 @@
#include "arch/x86/regs/misc.hh"
#include "arch/x86/registers.hh"
#include "base/types.hh"
#include "cpu/reg_class.hh"
#include "sim/sim_object.hh"
class Checkpoint;
@@ -69,6 +70,22 @@ namespace X86ISA
void setMiscRegNoEffect(int miscReg, MiscReg val);
void setMiscReg(int miscReg, MiscReg val, ThreadContext *tc);
RegId
flattenRegId(const RegId& regId) const
{
switch (regId.classValue()) {
case IntRegClass:
return RegId(IntRegClass, flattenIntIndex(regId.index()));
case FloatRegClass:
return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
case CCRegClass:
return RegId(CCRegClass, flattenCCIndex(regId.index()));
case MiscRegClass:
return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
}
return regId;
}
int
flattenIntIndex(int reg) const
{

View File

@@ -95,7 +95,7 @@ def template MicroLimmOpConstructor {{
InstRegIndex _dest, uint64_t _imm, uint8_t _dataSize) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
setFlags, %(op_class)s),
dest(_dest.regIdx), imm(_imm), dataSize(_dataSize)
dest(_dest.index()), imm(_imm), dataSize(_dataSize)
{
foldOBit = (dataSize == 1 && !machInst.rex.present) ? 1 << 6 : 0;
%(constructor)s;

View File

@@ -383,7 +383,7 @@ class BaseDynInst : public ExecContext, public RefCounted
/** Returns the flattened register index of the i'th destination
* register.
*/
RegId flattenedDestRegIdx(int idx) const
const RegId& flattenedDestRegIdx(int idx) const
{
return _flatDestRegIdx[idx];
}
@@ -419,7 +419,7 @@ class BaseDynInst : public ExecContext, public RefCounted
/** Flattens a destination architectural register index into a logical
* index.
*/
void flattenDestReg(int idx, RegId flattened_dest)
void flattenDestReg(int idx, const RegId& flattened_dest)
{
_flatDestRegIdx[idx] = flattened_dest;
}
@@ -601,10 +601,10 @@ class BaseDynInst : public ExecContext, public RefCounted
int8_t numCCDestRegs() const { return staticInst->numCCDestRegs(); }
/** Returns the logical register index of the i'th destination register. */
RegId destRegIdx(int i) const { return staticInst->destRegIdx(i); }
const RegId& destRegIdx(int i) const { return staticInst->destRegIdx(i); }
/** Returns the logical register index of the i'th source register. */
RegId srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }
const RegId& srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }
/** Pops a result off the instResult queue */
template <class T>

View File

@@ -213,31 +213,31 @@ class CheckerCPU : public BaseCPU, public ExecContext
IntReg readIntRegOperand(const StaticInst *si, int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == IntRegClass);
return thread->readIntReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isIntReg());
return thread->readIntReg(reg.index());
}
FloatReg readFloatRegOperand(const StaticInst *si, int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == FloatRegClass);
return thread->readFloatReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isFloatReg());
return thread->readFloatReg(reg.index());
}
FloatRegBits readFloatRegOperandBits(const StaticInst *si,
int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == FloatRegClass);
return thread->readFloatRegBits(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isFloatReg());
return thread->readFloatRegBits(reg.index());
}
CCReg readCCRegOperand(const StaticInst *si, int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == CCRegClass);
return thread->readCCReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isCCReg());
return thread->readCCReg(reg.index());
}
template <class T>
@@ -251,35 +251,35 @@ class CheckerCPU : public BaseCPU, public ExecContext
void setIntRegOperand(const StaticInst *si, int idx,
IntReg val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == IntRegClass);
thread->setIntReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isIntReg());
thread->setIntReg(reg.index(), val);
setResult<uint64_t>(val);
}
void setFloatRegOperand(const StaticInst *si, int idx,
FloatReg val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == FloatRegClass);
thread->setFloatReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isFloatReg());
thread->setFloatReg(reg.index(), val);
setResult<double>(val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
FloatRegBits val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == FloatRegClass);
thread->setFloatRegBits(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isFloatReg());
thread->setFloatRegBits(reg.index(), val);
setResult<uint64_t>(val);
}
void setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == CCRegClass);
thread->setCCReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isCCReg());
thread->setCCReg(reg.index(), val);
setResult<uint64_t>(val);
}
@@ -327,27 +327,28 @@ class CheckerCPU : public BaseCPU, public ExecContext
MiscReg readMiscRegOperand(const StaticInst *si, int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == MiscRegClass);
return thread->readMiscReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isMiscReg());
return thread->readMiscReg(reg.index());
}
void setMiscRegOperand(const StaticInst *si, int idx,
const MiscReg &val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == MiscRegClass);
return this->setMiscReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isMiscReg());
return this->setMiscReg(reg.index(), val);
}
#if THE_ISA == MIPS_ISA
MiscReg readRegOtherThread(RegId misc_reg, ThreadID tid) override
MiscReg readRegOtherThread(const RegId& misc_reg, ThreadID tid) override
{
panic("MIPS MT not defined for CheckerCPU.\n");
return 0;
}
void setRegOtherThread(RegId misc_reg, MiscReg val, ThreadID tid) override
void setRegOtherThread(const RegId& misc_reg, MiscReg val,
ThreadID tid) override
{
panic("MIPS MT not defined for CheckerCPU.\n");
}

View File

@@ -595,40 +595,40 @@ Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val,
// We've already popped one dest off the queue,
// so do the fix-up then start with the next dest reg;
if (start_idx >= 0) {
RegId idx = inst->destRegIdx(start_idx);
switch (idx.regClass) {
const RegId& idx = inst->destRegIdx(start_idx);
switch (idx.classValue()) {
case IntRegClass:
thread->setIntReg(idx.regIdx, mismatch_val);
thread->setIntReg(idx.index(), mismatch_val);
break;
case FloatRegClass:
thread->setFloatRegBits(idx.regIdx, mismatch_val);
thread->setFloatRegBits(idx.index(), mismatch_val);
break;
case CCRegClass:
thread->setCCReg(idx.regIdx, mismatch_val);
thread->setCCReg(idx.index(), mismatch_val);
break;
case MiscRegClass:
thread->setMiscReg(idx.regIdx, mismatch_val);
thread->setMiscReg(idx.index(), mismatch_val);
break;
}
}
start_idx++;
uint64_t res = 0;
for (int i = start_idx; i < inst->numDestRegs(); i++) {
RegId idx = inst->destRegIdx(i);
const RegId& idx = inst->destRegIdx(i);
inst->template popResult<uint64_t>(res);
switch (idx.regClass) {
switch (idx.classValue()) {
case IntRegClass:
thread->setIntReg(idx.regIdx, res);
thread->setIntReg(idx.index(), res);
break;
case FloatRegClass:
thread->setFloatRegBits(idx.regIdx, res);
thread->setFloatRegBits(idx.index(), res);
break;
case CCRegClass:
thread->setCCReg(idx.regIdx, res);
thread->setCCReg(idx.index(), res);
break;
case MiscRegClass:
// Try to get the proper misc register index for ARM here...
thread->setMiscReg(idx.regIdx, res);
thread->setMiscReg(idx.index(), res);
break;
// else Register is out of range...
}

View File

@@ -301,10 +301,9 @@ class CheckerThreadContext : public ThreadContext
actualTC->setMiscReg(misc_reg, val);
}
int flattenIntIndex(int reg) { return actualTC->flattenIntIndex(reg); }
int flattenFloatIndex(int reg) { return actualTC->flattenFloatIndex(reg); }
int flattenCCIndex(int reg) { return actualTC->flattenCCIndex(reg); }
int flattenMiscIndex(int reg) { return actualTC->flattenMiscIndex(reg); }
RegId flattenRegId(const RegId& regId) const {
return actualTC->flattenRegId(regId);
}
unsigned readStCondFailures()
{ return actualTC->readStCondFailures(); }

View File

@@ -287,9 +287,9 @@ class ExecContext {
*/
#if THE_ISA == MIPS_ISA
virtual MiscReg readRegOtherThread(RegId reg,
virtual MiscReg readRegOtherThread(const RegId& reg,
ThreadID tid = InvalidThreadID) = 0;
virtual void setRegOtherThread(RegId reg, MiscReg val,
virtual void setRegOtherThread(const RegId& reg, MiscReg val,
ThreadID tid = InvalidThreadID) = 0;
#endif

View File

@@ -133,15 +133,13 @@ operator <<(std::ostream &os, const MinorDynInst &inst)
/** Print a register in the form r<n>, f<n>, m<n>(<name>), z for integer,
* float, misc and zero registers given an 'architectural register number' */
static void
printRegName(std::ostream &os, RegId reg)
printRegName(std::ostream &os, const RegId& reg)
{
RegClass reg_class = reg.regClass;
switch (reg_class)
switch (reg.classValue())
{
case MiscRegClass:
{
RegIndex misc_reg = reg.regIdx;
RegIndex misc_reg = reg.index();
/* This is an ugly test because not all archs. have miscRegName */
#if THE_ISA == ARM_ISA
@@ -153,17 +151,17 @@ printRegName(std::ostream &os, RegId reg)
}
break;
case FloatRegClass:
os << 'f' << static_cast<unsigned int>(reg.regIdx);
os << 'f' << static_cast<unsigned int>(reg.index());
break;
case IntRegClass:
if (reg.isZeroReg()) {
os << 'z';
} else {
os << 'r' << static_cast<unsigned int>(reg.regIdx);
os << 'r' << static_cast<unsigned int>(reg.index());
}
break;
case CCRegClass:
os << 'c' << static_cast<unsigned int>(reg.regIdx);
os << 'c' << static_cast<unsigned int>(reg.index());
}
}

View File

@@ -124,51 +124,51 @@ class ExecContext : public ::ExecContext
IntReg
readIntRegOperand(const StaticInst *si, int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == IntRegClass);
return thread.readIntReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isIntReg());
return thread.readIntReg(reg.index());
}
TheISA::FloatReg
readFloatRegOperand(const StaticInst *si, int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == FloatRegClass);
return thread.readFloatReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isFloatReg());
return thread.readFloatReg(reg.index());
}
TheISA::FloatRegBits
readFloatRegOperandBits(const StaticInst *si, int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == FloatRegClass);
return thread.readFloatRegBits(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isFloatReg());
return thread.readFloatRegBits(reg.index());
}
void
setIntRegOperand(const StaticInst *si, int idx, IntReg val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == IntRegClass);
thread.setIntReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isIntReg());
thread.setIntReg(reg.index(), val);
}
void
setFloatRegOperand(const StaticInst *si, int idx,
TheISA::FloatReg val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == FloatRegClass);
thread.setFloatReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isFloatReg());
thread.setFloatReg(reg.index(), val);
}
void
setFloatRegOperandBits(const StaticInst *si, int idx,
TheISA::FloatRegBits val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == FloatRegClass);
thread.setFloatRegBits(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isFloatReg());
thread.setFloatRegBits(reg.index(), val);
}
bool
@@ -216,18 +216,18 @@ class ExecContext : public ::ExecContext
TheISA::MiscReg
readMiscRegOperand(const StaticInst *si, int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == MiscRegClass);
return thread.readMiscReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isMiscReg());
return thread.readMiscReg(reg.index());
}
void
setMiscRegOperand(const StaticInst *si, int idx,
const TheISA::MiscReg &val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == MiscRegClass);
return thread.setMiscReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isMiscReg());
return thread.setMiscReg(reg.index(), val);
}
Fault
@@ -279,17 +279,17 @@ class ExecContext : public ::ExecContext
TheISA::CCReg
readCCRegOperand(const StaticInst *si, int idx) override
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == CCRegClass);
return thread.readCCReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isCCReg());
return thread.readCCReg(reg.index());
}
void
setCCRegOperand(const StaticInst *si, int idx, TheISA::CCReg val) override
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == CCRegClass);
thread.setCCReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isCCReg());
thread.setCCReg(reg.index(), val);
}
void
@@ -320,46 +320,46 @@ class ExecContext : public ::ExecContext
/* MIPS: other thread register reading/writing */
uint64_t
readRegOtherThread(RegId reg, ThreadID tid = InvalidThreadID)
readRegOtherThread(const RegId& reg, ThreadID tid = InvalidThreadID)
{
SimpleThread *other_thread = (tid == InvalidThreadID
? &thread : cpu.threads[tid]);
switch(reg.regClass) {
switch (reg.classValue()) {
case IntRegClass:
return other_thread->readIntReg(reg.regIdx);
return other_thread->readIntReg(reg.index());
break;
case FloatRegClass:
return other_thread->readFloatRegBits(reg.regIdx);
return other_thread->readFloatRegBits(reg.index());
break;
case MiscRegClass:
return other_thread->readMiscReg(reg.regIdx);
return other_thread->readMiscReg(reg.index());
default:
panic("Unexpected reg class! (%s)",
RegClassStrings[reg.regClass]);
reg.className());
return 0;
}
}
void
setRegOtherThread(RegId reg, const TheISA::MiscReg &val,
setRegOtherThread(const RegId& reg, const TheISA::MiscReg &val,
ThreadID tid = InvalidThreadID)
{
SimpleThread *other_thread = (tid == InvalidThreadID
? &thread : cpu.threads[tid]);
switch(reg.regClass) {
switch (reg.classValue()) {
case IntRegClass:
return other_thread->setIntReg(reg.regIdx, val);
return other_thread->setIntReg(reg.index(), val);
break;
case FloatRegClass:
return other_thread->setFloatRegBits(reg.regIdx, val);
return other_thread->setFloatRegBits(reg.index(), val);
break;
case MiscRegClass:
return other_thread->setMiscReg(reg.regIdx, val);
return other_thread->setMiscReg(reg.index(), val);
default:
panic("Unexpected reg class! (%s)",
RegClassStrings[reg.regClass]);
reg.className());
}
}

View File

@@ -48,7 +48,7 @@ namespace Minor
{
bool
Scoreboard::findIndex(RegId reg, Index &scoreboard_index)
Scoreboard::findIndex(const RegId& reg, Index &scoreboard_index)
{
bool ret = false;
@@ -56,19 +56,19 @@ Scoreboard::findIndex(RegId reg, Index &scoreboard_index)
/* Don't bother with the zero register */
ret = false;
} else {
switch (reg.regClass)
switch (reg.classValue())
{
case IntRegClass:
scoreboard_index = reg.regIdx;
scoreboard_index = reg.index();
ret = true;
break;
case FloatRegClass:
scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
reg.regIdx;
reg.index();
ret = true;
break;
case CCRegClass:
scoreboard_index = TheISA::NumIntRegs + reg.regIdx;
scoreboard_index = TheISA::NumIntRegs + reg.index();
ret = true;
break;
case MiscRegClass:
@@ -83,26 +83,9 @@ Scoreboard::findIndex(RegId reg, Index &scoreboard_index)
/** Flatten a RegId, irrespective of what reg type it's pointing to */
static RegId
flattenRegIndex(RegId reg, ThreadContext *thread_context)
flattenRegIndex(const RegId& reg, ThreadContext *thread_context)
{
switch (reg.regClass)
{
case IntRegClass:
reg.regIdx = thread_context->flattenIntIndex(reg.regIdx);
break;
case FloatRegClass:
reg.regIdx = thread_context->flattenFloatIndex(reg.regIdx);
break;
case CCRegClass:
reg.regIdx = thread_context->flattenCCIndex(reg.regIdx);
break;
case MiscRegClass:
/* Don't bother to flatten misc regs as we don't need them here */
/* return thread_context->flattenMiscIndex(reg); */
break;
}
return reg;
return thread_context->flattenRegId(reg);
}
void
@@ -143,7 +126,8 @@ Scoreboard::markupInstDests(MinorDynInstPtr inst, Cycles retire_time,
*inst, index, numResults[index], returnCycle[index]);
} else {
/* Use ZeroReg to mark invalid/untracked dests */
inst->flatDestRegIdx[dest_index] = RegId::zeroReg;
inst->flatDestRegIdx[dest_index] = RegId(IntRegClass,
TheISA::ZeroReg);
}
}
}
@@ -190,7 +174,7 @@ Scoreboard::clearInstDests(MinorDynInstPtr inst, bool clear_unpredictable)
for (unsigned int dest_index = 0; dest_index < num_dests;
dest_index++)
{
RegId reg = inst->flatDestRegIdx[dest_index];
const RegId& reg = inst->flatDestRegIdx[dest_index];
Index index;
if (findIndex(reg, index)) {

View File

@@ -106,7 +106,7 @@ class Scoreboard : public Named
/** Sets scoreboard_index to the index into numResults of the
* given register index. Returns true if the given register
* is in the scoreboard and false if it isn't */
bool findIndex(RegId reg, Index &scoreboard_index);
bool findIndex(const RegId& reg, Index &scoreboard_index);
/** Mark up an instruction's effects by incrementing
* numResults counts. If mark_unpredictable is true, the inst's

View File

@@ -52,47 +52,65 @@
#include "cpu/inst_seq.hh"
#include "sim/faults.hh"
// Typedef for physical register index type. Although the Impl would be the
// most likely location for this, there are a few classes that need this
// typedef yet are not templated on the Impl. For now it will be defined here.
typedef short int PhysRegIndex;
// Physical register ID
// Associate a physical register index to a register class and
// so it is easy to track which type of register are used.
// A flat index is also provided for when it is useful to have a unified
// indexing (for the dependency graph and the scoreboard for example)
struct PhysRegId {
RegClass regClass;
PhysRegIndex regIdx;
/** Physical register index type.
* Although the Impl might be a better for this, but there are a few classes
* that need this typedef yet are not templated on the Impl.
*/
using PhysRegIndex = short int;
/** Physical register ID.
* Like a register ID but physical. The inheritance is private because the
* only relationship between this types is functional, and it is done to
* prevent code replication. */
class PhysRegId : private RegId {
private:
PhysRegIndex flatIdx;
PhysRegId(RegClass _regClass, PhysRegIndex _regIdx,
public:
explicit PhysRegId() : RegId(IntRegClass, -1), flatIdx(-1) {}
/** Scalar PhysRegId constructor. */
explicit PhysRegId(RegClass _regClass, PhysRegIndex _regIdx,
PhysRegIndex _flatIdx)
: regClass(_regClass), regIdx(_regIdx), flatIdx(_flatIdx)
: RegId(_regClass, _regIdx), flatIdx(_flatIdx)
{}
/** Visible RegId methods */
/** @{ */
using RegId::index;
using RegId::classValue;
using RegId::isZeroReg;
using RegId::className;
/** @} */
/**
* Explicit forward methods, to prevent comparisons of PhysRegId with
* RegIds.
*/
/** @{ */
bool operator<(const PhysRegId& that) const {
return RegId::operator<(that);
}
bool operator==(const PhysRegId& that) const {
return regClass == that.regClass && regIdx == that.regIdx;
return RegId::operator==(that);
}
bool operator!=(const PhysRegId& that) const {
return !(*this==that);
}
bool isZeroReg() const
{
return (regIdx == TheISA::ZeroReg &&
(regClass == IntRegClass ||
(THE_ISA == ALPHA_ISA && regClass == FloatRegClass)));
return RegId::operator!=(that);
}
/** @} */
/** @return true if it is an integer physical register. */
bool isIntPhysReg() const { return regClass == IntRegClass; }
bool isIntPhysReg() const { return isIntReg(); }
/** @return true if it is a floating-point physical register. */
bool isFloatPhysReg() const { return regClass == FloatRegClass; }
bool isFloatPhysReg() const { return isFloatReg(); }
/** @Return true if it is a condition-code physical register. */
bool isCCPhysReg() const { return regClass == CCRegClass; }
bool isCCPhysReg() const { return isCCReg(); }
/** @Return true if it is a condition-code physical register. */
bool isMiscPhysReg() const { return isMiscReg(); }
/**
* Returns true if this register is always associated to the same
@@ -100,8 +118,11 @@ struct PhysRegId {
*/
bool isFixedMapping() const
{
return regClass == MiscRegClass;
return !isRenameable();
}
/** Flat index accessor */
const PhysRegIndex& flatIndex() const { return flatIdx; }
};
// PhysRegIds only need to be created once and then we can use the following

View File

@@ -300,20 +300,21 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
// 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();
renameMap[tid].setIntEntry(ridx, phys_reg);
commitRenameMap[tid].setIntEntry(ridx, phys_reg);
renameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg);
commitRenameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg);
}
for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) {
PhysRegIdPtr phys_reg = freeList.getFloatReg();
renameMap[tid].setFloatEntry(ridx, phys_reg);
commitRenameMap[tid].setFloatEntry(ridx, phys_reg);
renameMap[tid].setEntry(RegId(FloatRegClass, ridx), phys_reg);
commitRenameMap[tid].setEntry(
RegId(FloatRegClass, ridx), phys_reg);
}
for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) {
PhysRegIdPtr phys_reg = freeList.getCCReg();
renameMap[tid].setCCEntry(ridx, phys_reg);
commitRenameMap[tid].setCCEntry(ridx, phys_reg);
renameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg);
commitRenameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg);
}
}
@@ -788,24 +789,24 @@ FullO3CPU<Impl>::insertThread(ThreadID tid)
//Bind Int Regs to Rename Map
for (RegId reg_id(IntRegClass, 0); reg_id.regIdx < TheISA::NumIntRegs;
reg_id.regIdx++) {
for (RegId reg_id(IntRegClass, 0); reg_id.index() < TheISA::NumIntRegs;
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.regIdx < TheISA::NumFloatRegs;
reg_id.regIdx++) {
for (RegId reg_id(FloatRegClass, 0); reg_id.index() < TheISA::NumFloatRegs;
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.regIdx < TheISA::NumCCRegs;
reg_id.regIdx++) {
for (RegId reg_id(CCRegClass, 0); reg_id.index() < TheISA::NumCCRegs;
reg_id.index()++) {
PhysRegIdPtr phys_reg = freeList.getCCReg();
renameMap[tid].setEntry(reg_id, phys_reg);
scoreboard.setReg(phys_reg);
@@ -842,24 +843,24 @@ FullO3CPU<Impl>::removeThread(ThreadID tid)
// in SMT workloads.
// Unbind Int Regs from Rename Map
for (RegId reg_id(IntRegClass, 0); reg_id.regIdx < TheISA::NumIntRegs;
reg_id.regIdx++) {
for (RegId reg_id(IntRegClass, 0); reg_id.index() < TheISA::NumIntRegs;
reg_id.index()++) {
PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id);
scoreboard.unsetReg(phys_reg);
freeList.addReg(phys_reg);
}
// Unbind Float Regs from Rename Map
for (RegId reg_id(FloatRegClass, 0); reg_id.regIdx < TheISA::NumFloatRegs;
reg_id.regIdx++) {
for (RegId reg_id(FloatRegClass, 0); reg_id.index() < TheISA::NumFloatRegs;
reg_id.index()++) {
PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id);
scoreboard.unsetReg(phys_reg);
freeList.addReg(phys_reg);
}
// Unbind condition-code Regs from Rename Map
for (RegId reg_id(CCRegClass, 0); reg_id.regIdx < TheISA::NumCCRegs;
reg_id.regIdx++) {
for (RegId reg_id(CCRegClass, 0); reg_id.index() < TheISA::NumCCRegs;
reg_id.index()++) {
PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id);
scoreboard.unsetReg(phys_reg);
freeList.addReg(phys_reg);
@@ -1300,7 +1301,8 @@ uint64_t
FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid)
{
intRegfileReads++;
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupInt(reg_idx);
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
RegId(IntRegClass, reg_idx));
return regFile.readIntReg(phys_reg);
}
@@ -1310,7 +1312,8 @@ float
FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid)
{
fpRegfileReads++;
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
RegId(FloatRegClass, reg_idx));
return regFile.readFloatReg(phys_reg);
}
@@ -1320,7 +1323,8 @@ uint64_t
FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid)
{
fpRegfileReads++;
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
RegId(FloatRegClass, reg_idx));
return regFile.readFloatRegBits(phys_reg);
}
@@ -1330,7 +1334,8 @@ CCReg
FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid)
{
ccRegfileReads++;
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupCC(reg_idx);
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
RegId(CCRegClass, reg_idx));
return regFile.readCCReg(phys_reg);
}
@@ -1340,7 +1345,8 @@ void
FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid)
{
intRegfileWrites++;
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupInt(reg_idx);
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
RegId(IntRegClass, reg_idx));
regFile.setIntReg(phys_reg, val);
}
@@ -1350,7 +1356,8 @@ void
FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid)
{
fpRegfileWrites++;
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
RegId(FloatRegClass, reg_idx));
regFile.setFloatReg(phys_reg, val);
}
@@ -1360,7 +1367,8 @@ void
FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid)
{
fpRegfileWrites++;
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
RegId(FloatRegClass, reg_idx));
regFile.setFloatRegBits(phys_reg, val);
}
@@ -1370,7 +1378,8 @@ void
FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid)
{
ccRegfileWrites++;
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookupCC(reg_idx);
PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
RegId(CCRegClass, reg_idx));
regFile.setCCReg(phys_reg, val);
}

View File

@@ -123,7 +123,7 @@ class BaseO3DynInst : public BaseDynInst<Impl>
public:
#if TRACING_ON
/** Tick records used for the pipeline activity viewer. */
Tick fetchTick; // instruction fetch is completed.
Tick fetchTick; // instruction fetch is completed.
int32_t decodeTick; // instruction enters decode phase
int32_t renameTick; // instruction enters rename phase
int32_t dispatchTick;
@@ -170,9 +170,9 @@ class BaseO3DynInst : public BaseDynInst<Impl>
*/
TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx)
{
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == MiscRegClass);
return this->cpu->readMiscReg(reg.regIdx, this->threadNumber);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isMiscReg());
return this->cpu->readMiscReg(reg.index(), this->threadNumber);
}
/** Sets a misc. register, including any side-effects the write
@@ -181,9 +181,9 @@ class BaseO3DynInst : public BaseDynInst<Impl>
void setMiscRegOperand(const StaticInst *si, int idx,
const MiscReg &val)
{
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == MiscRegClass);
setMiscReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isMiscReg());
setMiscReg(reg.index(), val);
}
/** Called at the commit stage to update the misc. registers. */
@@ -208,9 +208,9 @@ class BaseO3DynInst : public BaseDynInst<Impl>
for (int idx = 0; idx < this->numDestRegs(); idx++) {
PhysRegIdPtr prev_phys_reg = this->prevDestRegIdx(idx);
RegId original_dest_reg =
const RegId& original_dest_reg =
this->staticInst->destRegIdx(idx);
switch (original_dest_reg.regClass) {
switch (original_dest_reg.classValue()) {
case IntRegClass:
this->setIntRegOperand(this->staticInst.get(), idx,
this->cpu->readIntReg(prev_phys_reg));
@@ -300,13 +300,13 @@ class BaseO3DynInst : public BaseDynInst<Impl>
}
#if THE_ISA == MIPS_ISA
MiscReg readRegOtherThread(RegId misc_reg, ThreadID tid)
MiscReg readRegOtherThread(const RegId& misc_reg, ThreadID tid)
{
panic("MIPS MT not defined for O3 CPU.\n");
return 0;
}
void setRegOtherThread(RegId misc_reg, MiscReg val, ThreadID tid)
void setRegOtherThread(const RegId& misc_reg, MiscReg val, ThreadID tid)
{
panic("MIPS MT not defined for O3 CPU.\n");
}

View File

@@ -183,11 +183,11 @@ class UnifiedFreeList
inline void
UnifiedFreeList::addReg(PhysRegIdPtr freed_reg)
{
DPRINTF(FreeList,"Freeing register %i (%s).\n", freed_reg->regIdx,
RegClassStrings[freed_reg->regClass]);
DPRINTF(FreeList,"Freeing register %i (%s).\n", freed_reg->index(),
freed_reg->className());
//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.
switch (freed_reg->regClass) {
switch (freed_reg->classValue()) {
case IntRegClass:
intList.addReg(freed_reg);
break;
@@ -199,7 +199,7 @@ UnifiedFreeList::addReg(PhysRegIdPtr freed_reg)
break;
default:
panic("Unexpected RegClass (%s)",
RegClassStrings[freed_reg->regClass]);
freed_reg->className());
}
// These assert conditions ensure that the number of free

View File

@@ -1434,8 +1434,8 @@ DefaultIEW<Impl>::writebackInsts()
for (int i = 0; i < inst->numDestRegs(); i++) {
//mark as Ready
DPRINTF(IEW,"Setting Destination Register %i (%s)\n",
inst->renamedDestRegIdx(i)->regIdx,
RegClassStrings[inst->renamedDestRegIdx(i)->regClass]);
inst->renamedDestRegIdx(i)->index(),
inst->renamedDestRegIdx(i)->className());
scoreboard->setReg(inst->renamedDestRegIdx(i));
}

View File

@@ -986,17 +986,17 @@ InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
// handled by the IQ and thus have no dependency graph entry.
if (dest_reg->isFixedMapping()) {
DPRINTF(IQ, "Reg %d [%s] is part of a fix mapping, skipping\n",
dest_reg->regIdx, RegClassStrings[dest_reg->regClass]);
dest_reg->index(), dest_reg->className());
continue;
}
DPRINTF(IQ, "Waking any dependents on register %i (%s).\n",
dest_reg->regIdx,
RegClassStrings[dest_reg->regClass]);
dest_reg->index(),
dest_reg->className());
//Go through the dependency chain, marking the registers as
//ready within the waiting instructions.
DynInstPtr dep_inst = dependGraph.pop(dest_reg->flatIdx);
DynInstPtr dep_inst = dependGraph.pop(dest_reg->flatIndex());
while (dep_inst) {
DPRINTF(IQ, "Waking up a dependent instruction, [sn:%lli] "
@@ -1010,18 +1010,18 @@ InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
addIfReady(dep_inst);
dep_inst = dependGraph.pop(dest_reg->flatIdx);
dep_inst = dependGraph.pop(dest_reg->flatIndex());
++dependents;
}
// Reset the head node now that all of its dependents have
// been woken up.
assert(dependGraph.empty(dest_reg->flatIdx));
dependGraph.clearInst(dest_reg->flatIdx);
assert(dependGraph.empty(dest_reg->flatIndex()));
dependGraph.clearInst(dest_reg->flatIndex());
// Mark the scoreboard as having that register ready.
regScoreboard[dest_reg->flatIdx] = true;
regScoreboard[dest_reg->flatIndex()] = true;
}
return dependents;
}
@@ -1233,7 +1233,8 @@ InstructionQueue<Impl>::doSquash(ThreadID tid)
if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
!src_reg->isFixedMapping()) {
dependGraph.remove(src_reg->flatIdx, squashed_inst);
dependGraph.remove(src_reg->flatIndex(),
squashed_inst);
}
@@ -1308,13 +1309,13 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
// it be added to the dependency graph.
if (src_reg->isFixedMapping()) {
continue;
} else if (!regScoreboard[src_reg->flatIdx]) {
} else if (!regScoreboard[src_reg->flatIndex()]) {
DPRINTF(IQ, "Instruction PC %s has src reg %i (%s) that "
"is being added to the dependency chain.\n",
new_inst->pcState(), src_reg->regIdx,
RegClassStrings[src_reg->regClass]);
new_inst->pcState(), src_reg->index(),
src_reg->className());
dependGraph.insert(src_reg->flatIdx, new_inst);
dependGraph.insert(src_reg->flatIndex(), new_inst);
// Change the return value to indicate that something
// was added to the dependency graph.
@@ -1322,8 +1323,8 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
} else {
DPRINTF(IQ, "Instruction PC %s has src reg %i (%s) that "
"became ready before it reached the IQ.\n",
new_inst->pcState(), src_reg->regIdx,
RegClassStrings[src_reg->regClass]);
new_inst->pcState(), src_reg->index(),
src_reg->className());
// Mark a register ready within the instruction.
new_inst->markSrcRegReady(src_reg_idx);
}
@@ -1355,17 +1356,17 @@ InstructionQueue<Impl>::addToProducers(DynInstPtr &new_inst)
continue;
}
if (!dependGraph.empty(dest_reg->flatIdx)) {
if (!dependGraph.empty(dest_reg->flatIndex())) {
dependGraph.dump();
panic("Dependency graph %i (%s) (flat: %i) not empty!",
dest_reg->regIdx, RegClassStrings[dest_reg->regClass],
dest_reg->flatIdx);
dest_reg->index(), dest_reg->className(),
dest_reg->flatIndex());
}
dependGraph.setInst(dest_reg->flatIdx, new_inst);
dependGraph.setInst(dest_reg->flatIndex(), new_inst);
// Mark the scoreboard to say it's not yet ready.
regScoreboard[dest_reg->flatIdx] = false;
regScoreboard[dest_reg->flatIndex()] = false;
}
}

View File

@@ -242,8 +242,8 @@ ElasticTrace::updateRegDep(const DynInstPtr &dyn_inst)
PhysRegIdPtr src_reg = dyn_inst->renamedSrcRegIdx(src_idx);
DPRINTFR(ElasticTrace, "[sn:%lli] Check map for src reg"
" %i (%s)\n", seq_num,
src_reg->regIdx, RegClassStrings[src_reg->regClass]);
auto itr_last_writer = physRegDepMap.find(src_reg->flatIdx);
src_reg->index(), src_reg->className());
auto itr_last_writer = physRegDepMap.find(src_reg->flatIndex());
if (itr_last_writer != physRegDepMap.end()) {
InstSeqNum last_writer = itr_last_writer->second;
// Additionally the dependency distance is kept less than the window
@@ -263,16 +263,16 @@ ElasticTrace::updateRegDep(const DynInstPtr &dyn_inst)
for (int dest_idx = 0; dest_idx < max_regs; dest_idx++) {
// For data dependency tracking the register must be an int, float or
// CC register and not a Misc register.
RegId dest_reg = dyn_inst->destRegIdx(dest_idx);
if (dest_reg.isRenameable() &&
const RegId& dest_reg = dyn_inst->destRegIdx(dest_idx);
if (!dest_reg.isMiscReg() &&
!dest_reg.isZeroReg()) {
// Get the physical register index of the i'th destination
// register.
PhysRegIdPtr phys_dest_reg = dyn_inst->renamedDestRegIdx(dest_idx);
DPRINTFR(ElasticTrace, "[sn:%lli] Update map for dest reg"
" %i (%s)\n", seq_num, dest_reg.regIdx,
RegClassStrings[dest_reg.regClass]);
physRegDepMap[phys_dest_reg->flatIdx] = seq_num;
" %i (%s)\n", seq_num, dest_reg.index(),
dest_reg.className());
physRegDepMap[phys_dest_reg->flatIndex()] = seq_num;
}
}
maxPhysRegDepMapSize = std::max(physRegDepMap.size(),

View File

@@ -89,21 +89,21 @@ PhysRegFile::initFreeList(UnifiedFreeList *freeList)
// The initial batch of registers are the integer ones
for (reg_idx = 0; reg_idx < numPhysicalIntRegs; reg_idx++) {
assert(intRegIds[reg_idx].regIdx == reg_idx);
assert(intRegIds[reg_idx].index() == reg_idx);
freeList->addIntReg(&intRegIds[reg_idx]);
}
// The next batch of the registers are the floating-point physical
// registers; put them onto the floating-point free list.
for (reg_idx = 0; reg_idx < numPhysicalFloatRegs; reg_idx++) {
assert(floatRegIds[reg_idx].regIdx == reg_idx);
assert(floatRegIds[reg_idx].index() == reg_idx);
freeList->addFloatReg(&floatRegIds[reg_idx]);
}
// The rest of the registers are the condition-code physical
// registers; put them onto the condition-code free list.
for (reg_idx = 0; reg_idx < numPhysicalCCRegs; reg_idx++) {
assert(ccRegIds[reg_idx].regIdx == reg_idx);
assert(ccRegIds[reg_idx].index() == reg_idx);
freeList->addCCReg(&ccRegIds[reg_idx]);
}
}

View File

@@ -135,8 +135,8 @@ class PhysRegFile
assert(phys_reg->isIntPhysReg());
DPRINTF(IEW, "RegFile: Access to int register %i, has data "
"%#x\n", phys_reg->regIdx, intRegFile[phys_reg->regIdx]);
return intRegFile[phys_reg->regIdx];
"%#x\n", phys_reg->index(), intRegFile[phys_reg->index()]);
return intRegFile[phys_reg->index()];
}
/** Reads a floating point register (double precision). */
@@ -145,20 +145,20 @@ class PhysRegFile
assert(phys_reg->isFloatPhysReg());
DPRINTF(IEW, "RegFile: Access to float register %i, has "
"data %#x\n", phys_reg->regIdx,
floatRegFile[phys_reg->regIdx].q);
"data %#x\n", phys_reg->index(),
floatRegFile[phys_reg->index()].q);
return floatRegFile[phys_reg->regIdx].d;
return floatRegFile[phys_reg->index()].d;
}
FloatRegBits readFloatRegBits(PhysRegIdPtr phys_reg) const
{
assert(phys_reg->isFloatPhysReg());
FloatRegBits floatRegBits = floatRegFile[phys_reg->regIdx].q;
FloatRegBits floatRegBits = floatRegFile[phys_reg->index()].q;
DPRINTF(IEW, "RegFile: Access to float register %i as int, "
"has data %#x\n", phys_reg->regIdx,
"has data %#x\n", phys_reg->index(),
(uint64_t)floatRegBits);
return floatRegBits;
@@ -170,10 +170,10 @@ class PhysRegFile
assert(phys_reg->isCCPhysReg());
DPRINTF(IEW, "RegFile: Access to cc register %i, has "
"data %#x\n", phys_reg->regIdx,
ccRegFile[phys_reg->regIdx]);
"data %#x\n", phys_reg->index(),
ccRegFile[phys_reg->index()]);
return ccRegFile[phys_reg->regIdx];
return ccRegFile[phys_reg->index()];
}
/** Sets an integer register to the given value. */
@@ -182,10 +182,10 @@ class PhysRegFile
assert(phys_reg->isIntPhysReg());
DPRINTF(IEW, "RegFile: Setting int register %i to %#x\n",
phys_reg->regIdx, val);
phys_reg->index(), val);
if (!phys_reg->isZeroReg())
intRegFile[phys_reg->regIdx] = val;
intRegFile[phys_reg->index()] = val;
}
/** Sets a double precision floating point register to the given value. */
@@ -194,10 +194,10 @@ class PhysRegFile
assert(phys_reg->isFloatPhysReg());
DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n",
phys_reg->regIdx, (uint64_t)val);
phys_reg->index(), (uint64_t)val);
if (!phys_reg->isZeroReg())
floatRegFile[phys_reg->regIdx].d = val;
floatRegFile[phys_reg->index()].d = val;
}
void setFloatRegBits(PhysRegIdPtr phys_reg, FloatRegBits val)
@@ -205,9 +205,9 @@ class PhysRegFile
assert(phys_reg->isFloatPhysReg());
DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n",
phys_reg->regIdx, (uint64_t)val);
phys_reg->index(), (uint64_t)val);
floatRegFile[phys_reg->regIdx].q = val;
floatRegFile[phys_reg->index()].q = val;
}
/** Sets a condition-code register to the given value. */
@@ -216,9 +216,9 @@ class PhysRegFile
assert(phys_reg->isCCPhysReg());
DPRINTF(IEW, "RegFile: Setting cc register %i to %#x\n",
phys_reg->regIdx, (uint64_t)val);
phys_reg->index(), (uint64_t)val);
ccRegFile[phys_reg->regIdx] = val;
ccRegFile[phys_reg->index()] = val;
}
};

View File

@@ -298,7 +298,7 @@ class DefaultRename
* register for that arch. register, and the new physical register.
*/
struct RenameHistory {
RenameHistory(InstSeqNum _instSeqNum, RegId _archReg,
RenameHistory(InstSeqNum _instSeqNum, const RegId& _archReg,
PhysRegIdPtr _newPhysReg,
PhysRegIdPtr _prevPhysReg)
: instSeqNum(_instSeqNum), archReg(_archReg),

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2012, 2014-2015 ARM Limited
* Copyright (c) 2010-2012, 2014-2016 ARM Limited
* Copyright (c) 2013 Advanced Micro Devices, Inc.
* All rights reserved.
*
@@ -985,8 +985,8 @@ DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid)
DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i (%s), "
"[sn:%lli].\n",
tid, hb_it->prevPhysReg->regIdx,
RegClassStrings[hb_it->prevPhysReg->regClass],
tid, hb_it->prevPhysReg->index(),
hb_it->prevPhysReg->className(),
hb_it->instSeqNum);
// Don't free special phys regs like misc and zero regs, which
@@ -1013,59 +1013,46 @@ DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid)
// Get the architectual register numbers from the source and
// operands, and redirect them to the right physical register.
for (int src_idx = 0; src_idx < num_src_regs; src_idx++) {
RegId src_reg = inst->srcRegIdx(src_idx);
RegIndex flat_src_reg;
const RegId& src_reg = inst->srcRegIdx(src_idx);
PhysRegIdPtr renamed_reg;
switch (src_reg.regClass) {
renamed_reg = map->lookup(tc->flattenRegId(src_reg));
switch (src_reg.classValue()) {
case IntRegClass:
flat_src_reg = tc->flattenIntIndex(src_reg.regIdx);
renamed_reg = map->lookupInt(flat_src_reg);
intRenameLookups++;
break;
case FloatRegClass:
flat_src_reg = tc->flattenFloatIndex(src_reg.regIdx);
renamed_reg = map->lookupFloat(flat_src_reg);
fpRenameLookups++;
break;
case CCRegClass:
flat_src_reg = tc->flattenCCIndex(src_reg.regIdx);
renamed_reg = map->lookupCC(flat_src_reg);
break;
case MiscRegClass:
// misc regs don't get flattened
flat_src_reg = src_reg.regIdx;
renamed_reg = map->lookupMisc(flat_src_reg);
break;
default:
panic("Invalid register class: %d.", src_reg.regClass);
panic("Invalid register class: %d.", src_reg.classValue());
}
DPRINTF(Rename, "[tid:%u]: Looking up %s arch reg %i"
" (flattened %i), got phys reg %i (%s)\n", tid,
RegClassStrings[src_reg.regClass], src_reg.regIdx,
flat_src_reg, renamed_reg->regIdx,
RegClassStrings[renamed_reg->regClass]);
", got phys reg %i (%s)\n", tid,
src_reg.className(), src_reg.index(),
renamed_reg->index(),
renamed_reg->className());
inst->renameSrcReg(src_idx, renamed_reg);
// See if the register is ready or not.
if (scoreboard->getReg(renamed_reg)) {
DPRINTF(Rename, "[tid:%u]: Register %d (flat: %d) (%s)"
" is ready.\n", tid, renamed_reg->regIdx,
renamed_reg->flatIdx,
RegClassStrings[renamed_reg->regClass]);
" is ready.\n", tid, renamed_reg->index(),
renamed_reg->flatIndex(),
renamed_reg->className());
inst->markSrcRegReady(src_idx);
} else {
DPRINTF(Rename, "[tid:%u]: Register %d (flat: %d) (%s)"
" is not ready.\n", tid, renamed_reg->regIdx,
renamed_reg->flatIdx,
RegClassStrings[renamed_reg->regClass]);
" is not ready.\n", tid, renamed_reg->index(),
renamed_reg->flatIndex(),
renamed_reg->className());
}
++renameRenameLookups;
@@ -1082,51 +1069,26 @@ DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid)
// Rename the destination registers.
for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) {
RegId dest_reg = inst->destRegIdx(dest_idx);
RegIndex flat_dest_reg;
const RegId& dest_reg = inst->destRegIdx(dest_idx);
typename RenameMap::RenameInfo rename_result;
switch (dest_reg.regClass) {
case IntRegClass:
flat_dest_reg = tc->flattenIntIndex(dest_reg.regIdx);
rename_result = map->renameInt(flat_dest_reg);
break;
RegId flat_dest_regid = tc->flattenRegId(dest_reg);
case FloatRegClass:
flat_dest_reg = tc->flattenFloatIndex(dest_reg.regIdx);
rename_result = map->renameFloat(flat_dest_reg);
break;
rename_result = map->rename(flat_dest_regid);
case CCRegClass:
flat_dest_reg = tc->flattenCCIndex(dest_reg.regIdx);
rename_result = map->renameCC(flat_dest_reg);
break;
case MiscRegClass:
// misc regs don't get flattened
flat_dest_reg = dest_reg.regIdx;
rename_result = map->renameMisc(dest_reg.regIdx);
break;
default:
panic("Invalid register class: %d.", dest_reg.regClass);
}
RegId flat_uni_dest_reg(dest_reg.regClass, flat_dest_reg);
inst->flattenDestReg(dest_idx, flat_uni_dest_reg);
inst->flattenDestReg(dest_idx, flat_dest_regid);
// Mark Scoreboard entry as not ready
scoreboard->unsetReg(rename_result.first);
DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i (%s) to physical "
"reg %i (%i).\n", tid, dest_reg.regIdx,
RegClassStrings[dest_reg.regClass],
rename_result.first->regIdx,
rename_result.first->flatIdx);
"reg %i (%i).\n", tid, dest_reg.index(),
dest_reg.className(),
rename_result.first->index(),
rename_result.first->flatIndex());
// Record the rename information so that a history can be kept.
RenameHistory hb_entry(inst->seqNum, flat_uni_dest_reg,
RenameHistory hb_entry(inst->seqNum, flat_dest_regid,
rename_result.first,
rename_result.second);
@@ -1439,12 +1401,12 @@ DefaultRename<Impl>::dumpHistory()
cprintf("Seq num: %i\nArch reg[%s]: %i New phys reg:"
" %i[%s] Old phys reg: %i[%s]\n",
(*buf_it).instSeqNum,
RegClassStrings[(*buf_it).archReg.regClass],
(*buf_it).archReg.regIdx,
(*buf_it).newPhysReg->regIdx,
RegClassStrings[(*buf_it).newPhysReg->regClass],
(*buf_it).prevPhysReg->regIdx,
RegClassStrings[(*buf_it).prevPhysReg->regClass]);
(*buf_it).archReg.className(),
(*buf_it).archReg.index(),
(*buf_it).newPhysReg->index(),
(*buf_it).newPhysReg->className(),
(*buf_it).prevPhysReg->index(),
(*buf_it).prevPhysReg->className());
buf_it++;
}

View File

@@ -33,6 +33,7 @@
#include <vector>
#include "cpu/reg_class_impl.hh"
#include "debug/Rename.hh"
using namespace std;
@@ -40,7 +41,7 @@ using namespace std;
/**** SimpleRenameMap methods ****/
SimpleRenameMap::SimpleRenameMap()
: freeList(NULL), zeroReg(0)
: freeList(NULL), zeroReg(IntRegClass,0)
{
}
@@ -54,24 +55,23 @@ SimpleRenameMap::init(unsigned size, SimpleFreeList *_freeList,
map.resize(size);
freeList = _freeList;
zeroReg = _zeroReg;
zeroReg = RegId(IntRegClass, _zeroReg);
}
SimpleRenameMap::RenameInfo
SimpleRenameMap::rename(RegIndex arch_reg)
SimpleRenameMap::rename(const RegId& arch_reg)
{
PhysRegIdPtr renamed_reg;
// Record the current physical register that is renamed to the
// requested architected register.
PhysRegIdPtr prev_reg = map[arch_reg];
PhysRegIdPtr prev_reg = map[arch_reg.index()];
// If it's not referencing the zero register, then rename the
// register.
if (arch_reg != zeroReg) {
renamed_reg = freeList->getReg();
map[arch_reg] = renamed_reg;
map[arch_reg.index()] = renamed_reg;
} else {
// Otherwise return the zero register so nothing bad happens.
assert(prev_reg->isZeroReg());
@@ -80,8 +80,8 @@ SimpleRenameMap::rename(RegIndex arch_reg)
DPRINTF(Rename, "Renamed reg %d to physical reg %d (%d) old mapping was"
" %d (%d)\n",
arch_reg, renamed_reg->regIdx, renamed_reg->flatIdx,
prev_reg->regIdx, prev_reg->flatIdx);
arch_reg, renamed_reg->index(), renamed_reg->flatIndex(),
prev_reg->index(), prev_reg->flatIndex());
return RenameInfo(renamed_reg, prev_reg);
}
@@ -105,75 +105,3 @@ UnifiedRenameMap::init(PhysRegFile *_regFile,
}
UnifiedRenameMap::RenameInfo
UnifiedRenameMap::rename(RegId arch_reg)
{
switch (arch_reg.regClass) {
case IntRegClass:
return renameInt(arch_reg.regIdx);
case FloatRegClass:
return renameFloat(arch_reg.regIdx);
case CCRegClass:
return renameCC(arch_reg.regIdx);
case MiscRegClass:
return renameMisc(arch_reg.regIdx);
default:
panic("rename rename(): unknown reg class %s\n",
RegClassStrings[arch_reg.regClass]);
}
}
PhysRegIdPtr
UnifiedRenameMap::lookup(RegId arch_reg) const
{
switch (arch_reg.regClass) {
case IntRegClass:
return lookupInt(arch_reg.regIdx);
case FloatRegClass:
return lookupFloat(arch_reg.regIdx);
case CCRegClass:
return lookupCC(arch_reg.regIdx);
case MiscRegClass:
return lookupMisc(arch_reg.regIdx);
default:
panic("rename lookup(): unknown reg class %s\n",
RegClassStrings[arch_reg.regClass]);
}
}
void
UnifiedRenameMap::setEntry(RegId arch_reg, PhysRegIdPtr phys_reg)
{
switch (arch_reg.regClass) {
case IntRegClass:
return setIntEntry(arch_reg.regIdx, phys_reg);
case FloatRegClass:
return setFloatEntry(arch_reg.regIdx, phys_reg);
case CCRegClass:
return setCCEntry(arch_reg.regIdx, 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(arch_reg.regIdx));
return;
default:
panic("rename setEntry(): unknown reg class %s\n",
RegClassStrings[arch_reg.regClass]);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 ARM Limited
* Copyright (c) 2015-2016 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
@@ -65,9 +65,9 @@
class SimpleRenameMap
{
private:
using Arch2PhysMap = std::vector<PhysRegIdPtr>;
/** The acutal arch-to-phys register map */
std::vector<PhysRegIdPtr> map;
Arch2PhysMap map;
/**
* Pointer to the free list from which new physical registers
@@ -82,7 +82,7 @@ class SimpleRenameMap
* table, it should be set to an invalid index so that it never
* matches.
*/
RegIndex zeroReg;
RegId zeroReg;
public:
@@ -112,17 +112,17 @@ class SimpleRenameMap
* @return A RenameInfo pair indicating both the new and previous
* physical registers.
*/
RenameInfo rename(RegIndex arch_reg);
RenameInfo rename(const RegId& arch_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.
*/
PhysRegIdPtr lookup(RegIndex arch_reg) const
PhysRegIdPtr lookup(const RegId& arch_reg) const
{
assert(arch_reg < map.size());
return map[arch_reg];
assert(arch_reg.flatIndex() <= map.size());
return map[arch_reg.flatIndex()];
}
/**
@@ -131,9 +131,10 @@ class SimpleRenameMap
* @param arch_reg The architectural register to remap.
* @param phys_reg The physical register to remap it to.
*/
void setEntry(RegIndex arch_reg, PhysRegIdPtr phys_reg)
void setEntry(const RegId& arch_reg, PhysRegIdPtr phys_reg)
{
map[arch_reg] = phys_reg;
assert(arch_reg.flatIndex() <= map.size());
map[arch_reg.flatIndex()] = phys_reg;
}
/** Return the number of free entries on the associated free list. */
@@ -186,55 +187,35 @@ class UnifiedRenameMap
/**
* Tell rename map to get a new free physical register to remap
* the specified architectural register. This version takes a
* flattened architectural register id and calls the
* appropriate class-specific rename table.
* @param arch_reg The architectural register index to remap.
* RegId and reads the appropriate class-specific rename table.
* @param arch_reg The architectural register id to remap.
* @return A RenameInfo pair indicating both the new and previous
* physical registers.
*/
RenameInfo rename(RegId arch_reg);
/**
* Perform rename() on an integer register, given a
* integer register index.
*/
RenameInfo renameInt(RegIndex rel_arch_reg)
RenameInfo rename(const RegId& arch_reg)
{
return intMap.rename(rel_arch_reg);
}
switch (arch_reg.classValue()) {
case IntRegClass:
return intMap.rename(arch_reg);
case FloatRegClass:
return floatMap.rename(arch_reg);
case CCRegClass:
return ccMap.rename(arch_reg);
case MiscRegClass:
{
// misc regs aren't really renamed, just remapped
PhysRegIdPtr phys_reg = lookup(arch_reg);
// Set the new register to the previous one to keep the same
// mapping throughout the execution.
return RenameInfo(phys_reg, phys_reg);
}
/**
* Perform rename() on a floating-point register, given a
* floating-point register index.
*/
RenameInfo renameFloat(RegIndex rel_arch_reg)
{
return floatMap.rename(rel_arch_reg);
default:
panic("rename rename(): unknown reg class %s\n",
arch_reg.className());
}
}
/**
* Perform rename() on a condition-code register, given a
* condition-code register index.
*/
RenameInfo renameCC(RegIndex rel_arch_reg)
{
return ccMap.rename(rel_arch_reg);
}
/**
* Perform rename() on a misc register, given a
* misc register index.
*/
RenameInfo renameMisc(RegIndex rel_arch_reg)
{
// misc regs aren't really renamed, just remapped
PhysRegIdPtr phys_reg = lookupMisc(rel_arch_reg);
// Set the new register to the previous one to keep the same
// mapping throughout the execution.
return RenameInfo(phys_reg, phys_reg);
}
/**
* Look up the physical register mapped to an architectural register.
* This version takes a flattened architectural register id
@@ -242,44 +223,27 @@ class UnifiedRenameMap
* @param arch_reg The architectural register to look up.
* @return The physical register it is currently mapped to.
*/
PhysRegIdPtr lookup(RegId arch_reg) const;
/**
* Perform lookup() on an integer register, given a
* integer register index.
*/
PhysRegIdPtr lookupInt(RegIndex rel_arch_reg) const
PhysRegIdPtr lookup(const RegId& arch_reg) const
{
return intMap.lookup(rel_arch_reg);
}
switch (arch_reg.classValue()) {
case IntRegClass:
return intMap.lookup(arch_reg);
/**
* Perform lookup() on a floating-point register, given a
* floating-point register index.
*/
PhysRegIdPtr lookupFloat(RegIndex rel_arch_reg) const
{
return floatMap.lookup(rel_arch_reg);
}
case FloatRegClass:
return floatMap.lookup(arch_reg);
/**
* Perform lookup() on a condition-code register, given a
* condition-code register index.
*/
PhysRegIdPtr lookupCC(RegIndex rel_arch_reg) const
{
return ccMap.lookup(rel_arch_reg);
}
case CCRegClass:
return ccMap.lookup(arch_reg);
/**
* Perform lookup() on a misc register, given a relative
* misc register index.
*/
PhysRegIdPtr lookupMisc(RegIndex rel_arch_reg) const
{
// misc regs aren't really renamed, they keep the same
// mapping throughout the execution.
return regFile->getMiscRegId(rel_arch_reg);
case MiscRegClass:
// misc regs aren't really renamed, they keep the same
// mapping throughout the execution.
return regFile->getMiscRegId(arch_reg.flatIndex());
default:
panic("rename lookup(): unknown reg class %s\n",
arch_reg.className());
}
}
/**
@@ -290,36 +254,33 @@ class UnifiedRenameMap
* @param arch_reg The architectural register to remap.
* @param phys_reg The physical register to remap it to.
*/
void setEntry(RegId arch_reg, PhysRegIdPtr phys_reg);
/**
* Perform setEntry() on an integer register, given a
* integer register index.
*/
void setIntEntry(RegIndex arch_reg, PhysRegIdPtr phys_reg)
void setEntry(const RegId& arch_reg, PhysRegIdPtr phys_reg)
{
assert(phys_reg->isIntPhysReg());
intMap.setEntry(arch_reg, phys_reg);
}
switch (arch_reg.classValue()) {
case IntRegClass:
assert(phys_reg->isIntPhysReg());
return intMap.setEntry(arch_reg, phys_reg);
/**
* Perform setEntry() on a floating-point register, given a
* floating-point register index.
*/
void setFloatEntry(RegIndex arch_reg, PhysRegIdPtr phys_reg)
{
assert(phys_reg->isFloatPhysReg());
floatMap.setEntry(arch_reg, phys_reg);
}
case FloatRegClass:
assert(phys_reg->isFloatPhysReg());
return floatMap.setEntry(arch_reg, phys_reg);
/**
* Perform setEntry() on a condition-code register, given a
* condition-code register index.
*/
void setCCEntry(RegIndex arch_reg, PhysRegIdPtr phys_reg)
{
assert(phys_reg->isCCPhysReg());
ccMap.setEntry(arch_reg, phys_reg);
case CCRegClass:
assert(phys_reg->isCCPhysReg());
return ccMap.setEntry(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 == lookup(arch_reg));
return;
default:
panic("rename setEntry(): unknown reg class %s\n",
arch_reg.className());
}
}
/**

View File

@@ -80,14 +80,14 @@ class Scoreboard
/** Checks if the register is ready. */
bool getReg(PhysRegIdPtr phys_reg) const
{
assert(phys_reg->flatIdx < numPhysRegs);
assert(phys_reg->flatIndex() < numPhysRegs);
if (phys_reg->isFixedMapping()) {
// Fixed mapping regs are always ready
return true;
}
bool ready = regScoreBoard[phys_reg->flatIdx];
bool ready = regScoreBoard[phys_reg->flatIndex()];
if (phys_reg->isZeroReg())
assert(ready);
@@ -98,7 +98,7 @@ class Scoreboard
/** Sets the register as ready. */
void setReg(PhysRegIdPtr phys_reg)
{
assert(phys_reg->flatIdx < numPhysRegs);
assert(phys_reg->flatIndex() < numPhysRegs);
if (phys_reg->isFixedMapping()) {
// Fixed mapping regs are always ready, ignore attempts to change
@@ -106,16 +106,16 @@ class Scoreboard
return;
}
DPRINTF(Scoreboard, "Setting reg %i (%s) as ready\n", phys_reg->regIdx,
RegClassStrings[phys_reg->regClass]);
DPRINTF(Scoreboard, "Setting reg %i (%s) as ready\n",
phys_reg->index(), phys_reg->className());
regScoreBoard[phys_reg->flatIdx] = true;
regScoreBoard[phys_reg->flatIndex()] = true;
}
/** Sets the register as not ready. */
void unsetReg(PhysRegIdPtr phys_reg)
{
assert(phys_reg->flatIdx < numPhysRegs);
assert(phys_reg->flatIndex() < numPhysRegs);
if (phys_reg->isFixedMapping()) {
// Fixed mapping regs are always ready, ignore attempts to
@@ -127,7 +127,7 @@ class Scoreboard
if (phys_reg->isZeroReg())
return;
regScoreBoard[phys_reg->flatIdx] = false;
regScoreBoard[phys_reg->flatIndex()] = false;
}
};

View File

@@ -175,37 +175,47 @@ class O3ThreadContext : public ThreadContext
virtual void clearArchRegs();
/** Reads an integer register. */
virtual uint64_t readReg(int reg_idx) {
return readIntRegFlat(flattenRegId(RegId(IntRegClass,
reg_idx)).index());
}
virtual uint64_t readIntReg(int reg_idx) {
return readIntRegFlat(flattenIntIndex(reg_idx));
return readIntRegFlat(flattenRegId(RegId(IntRegClass,
reg_idx)).index());
}
virtual FloatReg readFloatReg(int reg_idx) {
return readFloatRegFlat(flattenFloatIndex(reg_idx));
return readFloatRegFlat(flattenRegId(RegId(FloatRegClass,
reg_idx)).index());
}
virtual FloatRegBits readFloatRegBits(int reg_idx) {
return readFloatRegBitsFlat(flattenFloatIndex(reg_idx));
return readFloatRegBitsFlat(flattenRegId(RegId(FloatRegClass,
reg_idx)).index());
}
virtual CCReg readCCReg(int reg_idx) {
return readCCRegFlat(flattenCCIndex(reg_idx));
return readCCRegFlat(flattenRegId(RegId(CCRegClass,
reg_idx)).index());
}
/** Sets an integer register to a value. */
virtual void setIntReg(int reg_idx, uint64_t val) {
setIntRegFlat(flattenIntIndex(reg_idx), val);
setIntRegFlat(flattenRegId(RegId(IntRegClass, reg_idx)).index(), val);
}
virtual void setFloatReg(int reg_idx, FloatReg val) {
setFloatRegFlat(flattenFloatIndex(reg_idx), val);
setFloatRegFlat(flattenRegId(RegId(FloatRegClass,
reg_idx)).index(), val);
}
virtual void setFloatRegBits(int reg_idx, FloatRegBits val) {
setFloatRegBitsFlat(flattenFloatIndex(reg_idx), val);
setFloatRegBitsFlat(flattenRegId(RegId(FloatRegClass,
reg_idx)).index(), val);
}
virtual void setCCReg(int reg_idx, CCReg val) {
setCCRegFlat(flattenCCIndex(reg_idx), val);
setCCRegFlat(flattenRegId(RegId(CCRegClass, reg_idx)).index(), val);
}
/** Reads this thread's PC state. */
@@ -245,10 +255,7 @@ class O3ThreadContext : public ThreadContext
* write might have as defined by the architecture. */
virtual void setMiscReg(int misc_reg, const MiscReg &val);
virtual int flattenIntIndex(int reg);
virtual int flattenFloatIndex(int reg);
virtual int flattenCCIndex(int reg);
virtual int flattenMiscIndex(int reg);
virtual RegId flattenRegId(const RegId& regId) const;
/** Returns the number of consecutive store conditional failures. */
// @todo: Figure out where these store cond failures should go.

View File

@@ -270,31 +270,10 @@ O3ThreadContext<Impl>::pcStateNoRecord(const TheISA::PCState &val)
}
template <class Impl>
int
O3ThreadContext<Impl>::flattenIntIndex(int reg)
RegId
O3ThreadContext<Impl>::flattenRegId(const RegId& regId) const
{
return cpu->isa[thread->threadId()]->flattenIntIndex(reg);
}
template <class Impl>
int
O3ThreadContext<Impl>::flattenFloatIndex(int reg)
{
return cpu->isa[thread->threadId()]->flattenFloatIndex(reg);
}
template <class Impl>
int
O3ThreadContext<Impl>::flattenCCIndex(int reg)
{
return cpu->isa[thread->threadId()]->flattenCCIndex(reg);
}
template <class Impl>
int
O3ThreadContext<Impl>::flattenMiscIndex(int reg)
{
return cpu->isa[thread->threadId()]->flattenMiscIndex(reg);
return cpu->isa[thread->threadId()]->flattenRegId(regId);
}
template <class Impl>

View File

@@ -30,11 +30,10 @@
#include "cpu/reg_class.hh"
const char *RegClassStrings[] = {
const char *RegId::regClassStrings[] = {
"IntRegClass",
"FloatRegClass",
"CCRegClass",
"MiscRegClass"
};
const RegId RegId::zeroReg = RegId(IntRegClass, TheISA::ZeroReg);

View File

@@ -51,7 +51,7 @@
#include "arch/registers.hh"
#include "config/the_isa.hh"
/// Enumerate the classes of registers.
/** Enumerate the classes of registers. */
enum RegClass {
IntRegClass, ///< Integer register
FloatRegClass, ///< Floating-point register
@@ -59,54 +59,91 @@ enum RegClass {
MiscRegClass ///< Control (misc) register
};
/// 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.
/** 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.
*/
const int NumRegClasses = MiscRegClass + 1;
/// Register ID: describe an architectural register with its class and index.
/// This structure is used instead of just the register index to disambiguate
/// between different classes of registers.
/// For example, a integer register with index 3 is represented by
/// Regid(IntRegClass, 3).
struct RegId {
/** Register ID: describe an architectural register with its class and index.
* This structure is used instead of just the register index to disambiguate
* between different classes of registers. For example, a integer register with
* index 3 is represented by Regid(IntRegClass, 3).
*/
class RegId {
private:
static const char* regClassStrings[];
RegClass regClass;
RegIndex regIdx;
public:
RegId() {};
RegId(RegClass reg_class, RegIndex reg_idx)
: regClass(reg_class), regIdx(reg_idx)
{}
bool operator==(const RegId& that) const {
return regClass == that.regClass && regIdx == that.regIdx;
return regClass == that.classValue() && regIdx == that.index();
}
bool operator!=(const RegId& that) const {
return !(*this==that);
}
/**
* Returns true if this register is a zero register (needs to have a
* constant zero value throughout the execution)
/** Order operator.
* The order is required to implement maps with key type RegId
*/
bool isZeroReg() const
{
return (regIdx == TheISA::ZeroReg &&
(regClass == IntRegClass ||
(THE_ISA == ALPHA_ISA && regClass == FloatRegClass)));
bool operator<(const RegId& that) const {
return regClass < that.classValue() ||
(regClass == that.classValue() && regIdx < that.index());
}
/**
* Return true if this register can be renamed
*/
bool isRenameable()
bool isRenameable() const
{
return regClass != MiscRegClass;
}
static const RegId zeroReg;
};
/**
* Check if this is the zero register.
* Returns true if this register is a zero register (needs to have a
* constant zero value throughout the execution).
*/
/// Map enum values to strings for debugging
extern const char *RegClassStrings[];
inline bool isZeroReg() const;
/** @return true if it is an integer physical register. */
bool isIntReg() const { return regClass == IntRegClass; }
/** @return true if it is a floating-point physical register. */
bool isFloatReg() const { return regClass == FloatRegClass; }
/** @Return true if it is a condition-code physical register. */
bool isCCReg() const { return regClass == CCRegClass; }
/** @Return true if it is a condition-code physical register. */
bool isMiscReg() const { return regClass == MiscRegClass; }
/** Index accessors */
/** @{ */
const RegIndex& index() const { return regIdx; }
RegIndex& index() { return regIdx; }
/** Index flattening.
* Required to be able to use a vector for the register mapping.
*/
inline RegIndex flatIndex() const;
/** @} */
/** Class accessor */
const RegClass& classValue() const { return regClass; }
/** Return a const char* with the register class name. */
const char* className() const { return regClassStrings[regClass]; }
friend std::ostream&
operator<<(std::ostream& os, const RegId& rid) {
return os << rid.className() << "{" << rid.index() << "}";
}
};
#endif // __CPU__REG_CLASS_HH__

70
src/cpu/reg_class_impl.hh Normal file
View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2016 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* 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: Rekai Gonzalez
*/
#ifndef __CPU__REG_CLASS_IMPL_HH__
#define __CPU__REG_CLASS_IMPL_HH__
#include <cassert>
#include <cstddef>
#include <iostream>
#include "arch/registers.hh"
#include "config/the_isa.hh"
#include "cpu/reg_class.hh"
bool RegId::isZeroReg() const
{
return ((regClass == IntRegClass && regIdx == TheISA::ZeroReg) ||
(THE_ISA == ALPHA_ISA && regClass == FloatRegClass &&
regIdx == TheISA::ZeroReg));
}
RegIndex RegId::flatIndex() const {
switch (regClass) {
case IntRegClass:
case FloatRegClass:
case CCRegClass:
case MiscRegClass:
return regIdx;
}
panic("Trying to flatten a register without class!");
return -1;
}
#endif // __CPU__REG_CLASS_IMPL_HH__

View File

@@ -165,27 +165,27 @@ class SimpleExecContext : public ExecContext {
IntReg readIntRegOperand(const StaticInst *si, int idx) override
{
numIntRegReads++;
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == IntRegClass);
return thread->readIntReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isIntReg());
return thread->readIntReg(reg.index());
}
/** Sets an integer register to a value. */
void setIntRegOperand(const StaticInst *si, int idx, IntReg val) override
{
numIntRegWrites++;
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == IntRegClass);
thread->setIntReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isIntReg());
thread->setIntReg(reg.index(), val);
}
/** Reads a floating point register of single register width. */
FloatReg readFloatRegOperand(const StaticInst *si, int idx) override
{
numFpRegReads++;
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == FloatRegClass);
return thread->readFloatReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isFloatReg());
return thread->readFloatReg(reg.index());
}
/** Reads a floating point register in its binary format, instead
@@ -193,9 +193,9 @@ class SimpleExecContext : public ExecContext {
FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) override
{
numFpRegReads++;
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == FloatRegClass);
return thread->readFloatRegBits(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isFloatReg());
return thread->readFloatRegBits(reg.index());
}
/** Sets a floating point register of single width to a value. */
@@ -203,9 +203,9 @@ class SimpleExecContext : public ExecContext {
FloatReg val) override
{
numFpRegWrites++;
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == FloatRegClass);
thread->setFloatReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isFloatReg());
thread->setFloatReg(reg.index(), val);
}
/** Sets the bits of a floating point register of single width
@@ -214,42 +214,42 @@ class SimpleExecContext : public ExecContext {
FloatRegBits val) override
{
numFpRegWrites++;
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == FloatRegClass);
thread->setFloatRegBits(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isFloatReg());
thread->setFloatRegBits(reg.index(), val);
}
CCReg readCCRegOperand(const StaticInst *si, int idx) override
{
numCCRegReads++;
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == CCRegClass);
return thread->readCCReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isCCReg());
return thread->readCCReg(reg.index());
}
void setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
{
numCCRegWrites++;
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == CCRegClass);
thread->setCCReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isCCReg());
thread->setCCReg(reg.index(), val);
}
MiscReg readMiscRegOperand(const StaticInst *si, int idx) override
{
numIntRegReads++;
RegId reg = si->srcRegIdx(idx);
assert(reg.regClass == MiscRegClass);
return thread->readMiscReg(reg.regIdx);
const RegId& reg = si->srcRegIdx(idx);
assert(reg.isMiscReg());
return thread->readMiscReg(reg.index());
}
void setMiscRegOperand(const StaticInst *si, int idx,
const MiscReg &val) override
{
numIntRegWrites++;
RegId reg = si->destRegIdx(idx);
assert(reg.regClass == MiscRegClass);
thread->setMiscReg(reg.regIdx, val);
const RegId& reg = si->destRegIdx(idx);
assert(reg.isMiscReg());
thread->setMiscReg(reg.index(), val);
}
/**
@@ -411,14 +411,15 @@ class SimpleExecContext : public ExecContext {
}
#if THE_ISA == MIPS_ISA
MiscReg readRegOtherThread(RegId reg, ThreadID tid = InvalidThreadID)
MiscReg readRegOtherThread(const RegId& reg,
ThreadID tid = InvalidThreadID)
override
{
panic("Simple CPU models do not support multithreaded "
"register access.");
}
void setRegOtherThread(RegId reg, MiscReg val,
void setRegOtherThread(const RegId& reg, MiscReg val,
ThreadID tid = InvalidThreadID) override
{
panic("Simple CPU models do not support multithreaded "

View File

@@ -401,28 +401,10 @@ class SimpleThread : public ThreadState
return isa->setMiscReg(misc_reg, val, tc);
}
int
flattenIntIndex(int reg)
RegId
flattenRegId(const RegId& regId) const
{
return isa->flattenIntIndex(reg);
}
int
flattenFloatIndex(int reg)
{
return isa->flattenFloatIndex(reg);
}
int
flattenCCIndex(int reg)
{
return isa->flattenCCIndex(reg);
}
int
flattenMiscIndex(int reg)
{
return isa->flattenMiscIndex(reg);
return isa->flattenRegId(regId);
}
unsigned readStCondFailures() { return storeCondFailures; }

View File

@@ -43,6 +43,7 @@
#include "config/the_isa.hh"
#include "cpu/op_class.hh"
#include "cpu/reg_class.hh"
#include "cpu/reg_class_impl.hh"
#include "cpu/static_inst_fwd.hh"
#include "cpu/thread_context.hh"
#include "enums/StaticInstFlags.hh"
@@ -184,11 +185,11 @@ class StaticInst : public RefCounted, public StaticInstFlags
/// Return logical index (architectural reg num) of i'th destination reg.
/// Only the entries from 0 through numDestRegs()-1 are valid.
RegId destRegIdx(int i) const { return _destRegIdx[i]; }
const RegId& destRegIdx(int i) const { return _destRegIdx[i]; }
/// Return logical index (architectural reg num) of i'th source reg.
/// Only the entries from 0 through numSrcRegs()-1 are valid.
RegId srcRegIdx(int i) const { return _srcRegIdx[i]; }
const RegId& srcRegIdx(int i) const { return _srcRegIdx[i]; }
/// Pointer to a statically allocated "null" instruction object.
/// Used to give eaCompInst() and memAccInst() something to return

View File

@@ -250,19 +250,16 @@ class ThreadContext
virtual void setMiscReg(int misc_reg, const MiscReg &val) = 0;
virtual int flattenIntIndex(int reg) = 0;
virtual int flattenFloatIndex(int reg) = 0;
virtual int flattenCCIndex(int reg) = 0;
virtual int flattenMiscIndex(int reg) = 0;
virtual RegId flattenRegId(const RegId& regId) const = 0;
virtual uint64_t
readRegOtherThread(RegId misc_reg, ThreadID tid)
readRegOtherThread(const RegId& misc_reg, ThreadID tid)
{
return 0;
}
virtual void
setRegOtherThread(RegId misc_reg, const MiscReg &val, ThreadID tid)
setRegOtherThread(const RegId& misc_reg, const MiscReg &val, ThreadID tid)
{
}
@@ -291,7 +288,7 @@ class ThreadContext
*
* Some architectures have different registers visible in
* different modes. Such architectures "flatten" a register (see
* flattenIntIndex() and flattenFloatIndex()) to map it into the
* flattenRegId()) to map it into the
* gem5 register file. This interface provides a flat interface to
* the underlying register file, which allows for example
* serialization code to access all registers.
@@ -466,17 +463,8 @@ class ProxyThreadContext : public ThreadContext
void setMiscReg(int misc_reg, const MiscReg &val)
{ return actualTC->setMiscReg(misc_reg, val); }
int flattenIntIndex(int reg)
{ return actualTC->flattenIntIndex(reg); }
int flattenFloatIndex(int reg)
{ return actualTC->flattenFloatIndex(reg); }
int flattenCCIndex(int reg)
{ return actualTC->flattenCCIndex(reg); }
int flattenMiscIndex(int reg)
{ return actualTC->flattenMiscIndex(reg); }
RegId flattenRegId(const RegId& regId) const
{ return actualTC->flattenRegId(regId); }
unsigned readStCondFailures()
{ return actualTC->readStCondFailures(); }

View File

@@ -58,7 +58,7 @@ TimingExprEvalContext::TimingExprEvalContext(const StaticInstPtr &inst_,
uint64_t TimingExprSrcReg::eval(TimingExprEvalContext &context)
{
return context.inst->srcRegIdx(index).regIdx;
return context.inst->srcRegIdx(index).index();
}
uint64_t TimingExprReadIntReg::eval(TimingExprEvalContext &context)