fastmodel: Implement flattened int reg reading and writing.
Because the fast models (or at least the one we've looked at) give access to the integer registers mostly based on the current view of those registers, it does its own flattening and prevents accessing most of the raw storage locations without this extra level of mapping. To store to the flattened locations, we need to unflatten the indexes and in one case shift the mode so that we get the right values. Some registers which have irrelevant values for fast model (the "PC" which is actually diverted elsewhere, the zero register, microcode registers, and the "dummy" register), and those are left out of the mapping so that they return 0 and blow up gem5 when someone attempts to set them. Change-Id: Ia2d315d5ca4c8a65b17ad52beff3a366ca8b3d46 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23791 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-by: Chun-Chen TK Hsu <chunchenhsu@google.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
@@ -93,11 +93,55 @@ CortexA76TC::initFromIrisInstance(const ResourceMap &resources)
|
||||
extractResourceMap(intReg32Ids, resources, intReg32IdxNameMap);
|
||||
extractResourceMap(intReg64Ids, resources, intReg64IdxNameMap);
|
||||
|
||||
extractResourceMap(flattenedIntIds, resources, flattenedIntIdxNameMap);
|
||||
|
||||
extractResourceMap(ccRegIds, resources, ccRegIdxNameMap);
|
||||
|
||||
extractResourceMap(vecRegIds, resources, vecRegIdxNameMap);
|
||||
}
|
||||
|
||||
RegVal
|
||||
CortexA76TC::readIntRegFlat(RegIndex idx) const
|
||||
{
|
||||
ArmISA::CPSR orig_cpsr;
|
||||
|
||||
auto *non_const_this = const_cast<CortexA76TC *>(this);
|
||||
|
||||
if (idx == ArmISA::INTREG_R13_MON || idx == ArmISA::INTREG_R14_MON) {
|
||||
orig_cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
ArmISA::CPSR new_cpsr = orig_cpsr;
|
||||
new_cpsr.mode = MODE_MON;
|
||||
non_const_this->setMiscReg(ArmISA::MISCREG_CPSR, new_cpsr);
|
||||
}
|
||||
|
||||
RegVal val = ThreadContext::readIntRegFlat(idx);
|
||||
|
||||
if (idx == ArmISA::INTREG_R13_MON || idx == ArmISA::INTREG_R14_MON) {
|
||||
non_const_this->setMiscReg(ArmISA::MISCREG_CPSR, orig_cpsr);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
CortexA76TC::setIntRegFlat(RegIndex idx, RegVal val)
|
||||
{
|
||||
ArmISA::CPSR orig_cpsr;
|
||||
|
||||
if (idx == ArmISA::INTREG_R13_MON || idx == ArmISA::INTREG_R14_MON) {
|
||||
orig_cpsr = readMiscRegNoEffect(ArmISA::MISCREG_CPSR);
|
||||
ArmISA::CPSR new_cpsr = orig_cpsr;
|
||||
new_cpsr.mode = MODE_MON;
|
||||
setMiscReg(ArmISA::MISCREG_CPSR, new_cpsr);
|
||||
}
|
||||
|
||||
ThreadContext::setIntRegFlat(idx, val);
|
||||
|
||||
if (idx == ArmISA::INTREG_R13_MON || idx == ArmISA::INTREG_R14_MON) {
|
||||
setMiscReg(ArmISA::MISCREG_CPSR, orig_cpsr);
|
||||
}
|
||||
}
|
||||
|
||||
RegVal
|
||||
CortexA76TC::readCCRegFlat(RegIndex idx) const
|
||||
{
|
||||
@@ -840,6 +884,48 @@ Iris::ThreadContext::IdxNameMap CortexA76TC::intReg64IdxNameMap({
|
||||
{ ArmISA::INTREG_SPX, "SP" },
|
||||
});
|
||||
|
||||
Iris::ThreadContext::IdxNameMap CortexA76TC::flattenedIntIdxNameMap({
|
||||
{ ArmISA::INTREG_R0, "X0" },
|
||||
{ ArmISA::INTREG_R1, "X1" },
|
||||
{ ArmISA::INTREG_R2, "X2" },
|
||||
{ ArmISA::INTREG_R3, "X3" },
|
||||
{ ArmISA::INTREG_R4, "X4" },
|
||||
{ ArmISA::INTREG_R5, "X5" },
|
||||
{ ArmISA::INTREG_R6, "X6" },
|
||||
{ ArmISA::INTREG_R7, "X7" },
|
||||
{ ArmISA::INTREG_R8, "X8" },
|
||||
{ ArmISA::INTREG_R9, "X9" },
|
||||
{ ArmISA::INTREG_R10, "X10" },
|
||||
{ ArmISA::INTREG_R11, "X11" },
|
||||
{ ArmISA::INTREG_R12, "X12" },
|
||||
{ ArmISA::INTREG_R13, "X13" },
|
||||
{ ArmISA::INTREG_R14, "X14" },
|
||||
// Skip PC.
|
||||
{ ArmISA::INTREG_R13_SVC, "X19" },
|
||||
{ ArmISA::INTREG_R14_SVC, "X18" },
|
||||
{ ArmISA::INTREG_R13_MON, "R13" }, // Need to be in monitor mode?
|
||||
{ ArmISA::INTREG_R14_MON, "R14" }, // Need to be in monitor mode?
|
||||
{ ArmISA::INTREG_R13_HYP, "X15" },
|
||||
{ ArmISA::INTREG_R13_ABT, "X21" },
|
||||
{ ArmISA::INTREG_R14_ABT, "X20" },
|
||||
{ ArmISA::INTREG_R13_UND, "X23" },
|
||||
{ ArmISA::INTREG_R14_UND, "X22" },
|
||||
{ ArmISA::INTREG_R13_IRQ, "X17" },
|
||||
{ ArmISA::INTREG_R14_IRQ, "X16" },
|
||||
{ ArmISA::INTREG_R8_FIQ, "X24" },
|
||||
{ ArmISA::INTREG_R9_FIQ, "X25" },
|
||||
{ ArmISA::INTREG_R10_FIQ, "X26" },
|
||||
{ ArmISA::INTREG_R11_FIQ, "X27" },
|
||||
{ ArmISA::INTREG_R12_FIQ, "X28" },
|
||||
{ ArmISA::INTREG_R13_FIQ, "X29" },
|
||||
{ ArmISA::INTREG_R14_FIQ, "X30" },
|
||||
// Skip zero, ureg0-2, and dummy regs.
|
||||
{ INTREG_SP0, "SP_EL0" },
|
||||
{ INTREG_SP1, "SP_EL1" },
|
||||
{ INTREG_SP2, "SP_EL2" },
|
||||
{ INTREG_SP3, "SP_EL3" },
|
||||
});
|
||||
|
||||
Iris::ThreadContext::IdxNameMap CortexA76TC::ccRegIdxNameMap({
|
||||
{ ArmISA::CCREG_NZ, "CPSR" },
|
||||
{ ArmISA::CCREG_C, "CPSR.C" },
|
||||
|
||||
@@ -43,6 +43,7 @@ class CortexA76TC : public Iris::ThreadContext
|
||||
static IdxNameMap miscRegIdxNameMap;
|
||||
static IdxNameMap intReg32IdxNameMap;
|
||||
static IdxNameMap intReg64IdxNameMap;
|
||||
static IdxNameMap flattenedIntIdxNameMap;
|
||||
static IdxNameMap ccRegIdxNameMap;
|
||||
static IdxNameMap vecRegIdxNameMap;
|
||||
static iris::MemorySpaceId bpSpaceId;
|
||||
@@ -57,6 +58,9 @@ class CortexA76TC : public Iris::ThreadContext
|
||||
|
||||
void initFromIrisInstance(const ResourceMap &resources) override;
|
||||
|
||||
RegVal readIntRegFlat(RegIndex idx) const override;
|
||||
void setIntRegFlat(RegIndex idx, RegVal val) override;
|
||||
|
||||
RegVal readCCRegFlat(RegIndex idx) const override;
|
||||
void setCCRegFlat(RegIndex idx, RegVal val) override;
|
||||
|
||||
|
||||
@@ -520,6 +520,35 @@ ThreadContext::setIntReg(RegIndex reg_idx, RegVal val)
|
||||
call().resource_write(_instId, result, intReg64Ids.at(reg_idx), val);
|
||||
}
|
||||
|
||||
/*
|
||||
* The 64 bit version of registers gives us a pre-flattened view of the reg
|
||||
* file, no matter what mode we're in or if we're currently 32 or 64 bit.
|
||||
*/
|
||||
RegVal
|
||||
ThreadContext::readIntRegFlat(RegIndex idx) const
|
||||
{
|
||||
if (idx >= flattenedIntIds.size())
|
||||
return 0;
|
||||
iris::ResourceId res_id = flattenedIntIds.at(idx);
|
||||
if (res_id == iris::IRIS_UINT64_MAX)
|
||||
return 0;
|
||||
iris::ResourceReadResult result;
|
||||
call().resource_read(_instId, result, res_id);
|
||||
return result.data.at(0);
|
||||
}
|
||||
|
||||
void
|
||||
ThreadContext::setIntRegFlat(RegIndex idx, uint64_t val)
|
||||
{
|
||||
iris::ResourceId res_id =
|
||||
(idx >= flattenedIntIds.size()) ? iris::IRIS_UINT64_MAX :
|
||||
flattenedIntIds.at(idx);
|
||||
panic_if(res_id == iris::IRIS_UINT64_MAX,
|
||||
"Int reg %d is not supported by fast model.", idx);
|
||||
iris::ResourceWriteResult result;
|
||||
call().resource_write(_instId, result, flattenedIntIds.at(idx), val);
|
||||
}
|
||||
|
||||
RegVal
|
||||
ThreadContext::readCCRegFlat(RegIndex idx) const
|
||||
{
|
||||
|
||||
@@ -83,6 +83,7 @@ class ThreadContext : public ::ThreadContext
|
||||
ResourceIds miscRegIds;
|
||||
ResourceIds intReg32Ids;
|
||||
ResourceIds intReg64Ids;
|
||||
ResourceIds flattenedIntIds;
|
||||
ResourceIds ccRegIds;
|
||||
|
||||
iris::ResourceId pcRscId = iris::IRIS_UINT64_MAX;
|
||||
@@ -490,16 +491,8 @@ class ThreadContext : public ::ThreadContext
|
||||
* serialization code to access all registers.
|
||||
*/
|
||||
|
||||
uint64_t
|
||||
readIntRegFlat(RegIndex idx) const override
|
||||
{
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
void
|
||||
setIntRegFlat(RegIndex idx, uint64_t val) override
|
||||
{
|
||||
panic("%s not implemented.", __FUNCTION__);
|
||||
}
|
||||
RegVal readIntRegFlat(RegIndex idx) const override;
|
||||
void setIntRegFlat(RegIndex idx, uint64_t val) override;
|
||||
|
||||
RegVal
|
||||
readFloatRegFlat(RegIndex idx) const override
|
||||
|
||||
Reference in New Issue
Block a user