arch-riscv: Fix fflags behavior of float inst. in O3 CPU (#868)

According to the RISC-V spec [1]. Any float-point instructions
accumulate FFLAGS register rather than write it to reflect the CSR
behavior.

In the previous implementation. We read the FFLAGS, set the exception
flags, and write the result back to the FFLAGS. This works in the gem5
simple and minor CPU model as they are actually written to `regFile`
after executing the instructions. However, in the gem5 O3 CPU model, it
will record in the `destMiscReg` buffer until the commit stage when
writing to the `miscReg` in the execution stage. The next instruction
will get the old FFLAGS and cause the incorrect result.

The CL introduced the `MISCREG_FFLAGS_EXE` and used the same size of
`miscRegFile` because the `MISCREG_FFLAGS_EXE` and `MISCREG_FFLAGS`
shared the same space. When executing the float-pointing instruction,
any exception flags should be updated via `MISCREG_FFLAGS_EXE` to
accumulate the FFLAGS in `setMiscReg` method. For the MISCREG_FFLAGS, it
should only be called in the CSROp.

[1] Syntactic Dependencies: Appendix A

c80ecada1c/src/mm-eplan.adoc (syntactic-dependencies-rules-9-11)

gem5 issue: https://github.com/gem5/gem5/issues/755

Change-Id: Ib7f13d95b8a921c37766a54a217a5a4b1ef17c6f
This commit is contained in:
Yu-Cheng Chang
2024-02-23 00:33:34 +08:00
committed by GitHub
parent 0f79b15b2f
commit 816ef46c78
4 changed files with 24 additions and 11 deletions

View File

@@ -240,6 +240,8 @@ namespace RiscvISA
[MISCREG_HPMCOUNTER29H] = "HPMCOUNTER29H",
[MISCREG_HPMCOUNTER30H] = "HPMCOUNTER30H",
[MISCREG_HPMCOUNTER31H] = "HPMCOUNTER31H",
[MISCREG_FFLAGS_EXE] = "FFLAGS_EXE",
}};
namespace
@@ -276,7 +278,7 @@ ISA::ISA(const Params &p) : BaseISA(p),
p.vlen, p.elen);
miscRegFile.resize(NUM_MISCREGS);
miscRegFile.resize(NUM_PHYS_MISCREGS);
clear();
}
@@ -304,7 +306,7 @@ ISA::copyRegsFrom(ThreadContext *src)
}
// Copying Misc Regs
for (int i = 0; i < NUM_MISCREGS; i++)
for (int i = 0; i < NUM_PHYS_MISCREGS; i++)
tc->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
// Lastly copy PC/NPC
@@ -409,7 +411,7 @@ RegVal
ISA::readMiscRegNoEffect(RegIndex idx) const
{
// Illegal CSR
panic_if(idx > NUM_MISCREGS, "Illegal CSR index %#x\n", idx);
panic_if(idx > NUM_PHYS_MISCREGS, "Illegal CSR index %#x\n", idx);
DPRINTF(RiscvMisc, "Reading MiscReg %s (%d): %#x.\n",
MiscRegNames[idx], idx, miscRegFile[idx]);
return miscRegFile[idx];
@@ -571,6 +573,10 @@ ISA::readMiscReg(RegIndex idx)
(readMiscRegNoEffect(MISCREG_VXRM) << 1);
}
break;
case MISCREG_FFLAGS_EXE:
{
return readMiscRegNoEffect(MISCREG_FFLAGS) & FFLAGS_MASK;
}
default:
// Try reading HPM counters
// As a placeholder, all HPM counters are just cycle counters
@@ -603,7 +609,7 @@ void
ISA::setMiscRegNoEffect(RegIndex idx, RegVal val)
{
// Illegal CSR
panic_if(idx > NUM_MISCREGS, "Illegal CSR index %#x\n", idx);
panic_if(idx > NUM_PHYS_MISCREGS, "Illegal CSR index %#x\n", idx);
DPRINTF(RiscvMisc, "Setting MiscReg %s (%d) to %#x.\n",
MiscRegNames[idx], idx, val);
miscRegFile[idx] = val;
@@ -770,6 +776,13 @@ ISA::setMiscReg(RegIndex idx, RegVal val)
setMiscRegNoEffect(MISCREG_VXRM, (val & 0x6) >> 1);
}
break;
case MISCREG_FFLAGS_EXE:
{
RegVal new_val = readMiscRegNoEffect(MISCREG_FFLAGS);
new_val |= (val & FFLAGS_MASK);
setMiscRegNoEffect(MISCREG_FFLAGS, new_val);
}
break;
default:
setMiscRegNoEffect(idx, val);
}

View File

@@ -46,13 +46,10 @@ def template FloatExecute {{
%(op_decl)s;
%(op_rd)s;
RegVal FFLAGS = xc->readMiscReg(MISCREG_FFLAGS);
std::feclearexcept(FE_ALL_EXCEPT);
%(code)s;
FFLAGS |= softfloat_exceptionFlags;
xc->setMiscReg(MISCREG_FFLAGS_EXE, softfloat_exceptionFlags);
softfloat_exceptionFlags = 0;
xc->setMiscReg(MISCREG_FFLAGS, FFLAGS);
%(op_wb)s;

View File

@@ -114,12 +114,10 @@ let {{
def fflags_wrapper(code):
return '''
RegVal FFLAGS = xc->readMiscReg(MISCREG_FFLAGS);
std::feclearexcept(FE_ALL_EXCEPT);
''' + code + '''
FFLAGS |= softfloat_exceptionFlags;
xc->setMiscReg(MISCREG_FFLAGS_EXE, softfloat_exceptionFlags);
softfloat_exceptionFlags = 0;
xc->setMiscReg(MISCREG_FFLAGS, FFLAGS);
'''
def declareVArithTemplate(

View File

@@ -246,6 +246,11 @@ enum MiscRegIndex
MISCREG_HPMCOUNTER30H,
MISCREG_HPMCOUNTER31H,
NUM_PHYS_MISCREGS,
// This CSR shared the same space with MISCREG_FFLAGS
MISCREG_FFLAGS_EXE = NUM_PHYS_MISCREGS,
NUM_MISCREGS
};