fastmodel: Implement flattened int reg reading and writing.
authorGabe Black <gabeblack@google.com>
Wed, 13 Nov 2019 00:52:05 +0000 (16:52 -0800)
committerGabe Black <gabeblack@google.com>
Thu, 6 Feb 2020 01:07:16 +0000 (01:07 +0000)
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>

src/arch/arm/fastmodel/CortexA76/thread_context.cc
src/arch/arm/fastmodel/CortexA76/thread_context.hh
src/arch/arm/fastmodel/iris/thread_context.cc
src/arch/arm/fastmodel/iris/thread_context.hh

index 281c70aca6d89265cebe96226b75a0335cf242b5..70a95ede10453d53f9a7903375b869ac9e4b5729 100644 (file)
@@ -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" },
index af031140c5746591cb814759af507747101a60f2..a112cf0114ed284d7c2af4115d06f5e38f79049c 100644 (file)
@@ -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;
 
index c18a5cd7dbc32f74a064419cc112e42f24d58ea4..f487ebc7ce9f651b4036808ba0d626738a198bd9 100644 (file)
@@ -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
 {
index 5590f7fd278d62f8dd606c4a15baf27ad495344e..84d1f79fde87c8b1dbb5d196cd5bc22af083a39a 100644 (file)
@@ -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