arch-gcn3, gpu-compute: Fix issue when reading const operands
authorTony Gutierrez <anthony.gutierrez@amd.com>
Thu, 26 Jul 2018 21:28:39 +0000 (17:28 -0400)
committerAnthony Gutierrez <anthony.gutierrez@amd.com>
Mon, 22 Jun 2020 16:14:35 +0000 (16:14 +0000)
Currently, when an instruction has an operand that reads a const
value, it goes thru the same readMiscReg() api call as other
misc registers (real HW registers, not constant values). There
is an issue, however, when casting from the const values (which are
32b) to higher precision values, like 64b.

This change creates a separate, templated function call to the GPU's
ISA state that will return the correct type.

Change-Id: I41965ebeeed20bb70e919fce5ad94d957b3af802
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/29927
Reviewed-by: Anthony Gutierrez <anthony.gutierrez@amd.com>
Maintainer: Anthony Gutierrez <anthony.gutierrez@amd.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/arch/gcn3/gpu_isa.hh
src/arch/gcn3/isa.cc
src/arch/gcn3/operand.hh
src/arch/gcn3/registers.cc
src/arch/gcn3/registers.hh
src/gpu-compute/gpu_exec_context.hh

index 26b79c7c620d3c0f216a53459c8de9870b514f63..228c3fe36c3b8f256a5dbf9ab9d383db7c8199c1 100644 (file)
@@ -37,6 +37,7 @@
 #define __ARCH_GCN3_GPU_ISA_HH__
 
 #include <array>
+#include <type_traits>
 
 #include "arch/gcn3/registers.hh"
 #include "gpu-compute/dispatcher.hh"
@@ -52,6 +53,24 @@ namespace Gcn3ISA
       public:
         GPUISA(Wavefront &wf);
 
+        template<typename T> T
+        readConstVal(int opIdx) const
+        {
+            panic_if(!std::is_integral<T>::value, "Constant values must "
+                     "be an integer.\n");
+            T val(0);
+
+            if (isPosConstVal(opIdx)) {
+                val = (T)readPosConstReg(opIdx);
+            }
+
+            if (isNegConstVal(opIdx)) {
+                val = (T)readNegConstReg(opIdx);
+            }
+
+            return val;
+        }
+
         ScalarRegU32 readMiscReg(int opIdx) const;
         void writeMiscReg(int opIdx, ScalarRegU32 operandVal);
         bool hasScalarUnit() const { return true; }
@@ -63,10 +82,9 @@ namespace Gcn3ISA
             return posConstRegs[opIdx - REG_INT_CONST_POS_MIN];
         }
 
-        ScalarRegU32 readNegConstReg(int opIdx) const
+        ScalarRegI32 readNegConstReg(int opIdx) const
         {
-            return *((ScalarRegU32*)
-                &negConstRegs[opIdx - REG_INT_CONST_NEG_MIN]);
+            return negConstRegs[opIdx - REG_INT_CONST_NEG_MIN];
         }
 
         static const std::array<const ScalarRegU32, NumPosConstRegs>
index 036c771e1972fc040dd1ed8c7c065d9c02dc8361..3bd122dd0699b87eea048a65c69fcf5c57863ab6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 Advanced Micro Devices, Inc.
+ * Copyright (c) 2016-2018 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * For use for simulation and test purposes only
@@ -49,14 +49,6 @@ namespace Gcn3ISA
     ScalarRegU32
     GPUISA::readMiscReg(int opIdx) const
     {
-        if (opIdx >= REG_INT_CONST_POS_MIN && opIdx <= REG_INT_CONST_POS_MAX) {
-            return readPosConstReg(opIdx);
-        }
-
-        if (opIdx >= REG_INT_CONST_NEG_MIN && opIdx <= REG_INT_CONST_NEG_MAX) {
-            return readNegConstReg(opIdx);
-        }
-
         switch (opIdx) {
           case REG_M0:
             return m0;
index 218faf8cc60af67420c4f85fd95f30be5fcf239c..7f70fab747eaab4c35ef19900edf4532a271907c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Advanced Micro Devices, Inc.
+ * Copyright (c) 2017-2018 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * For use for simulation and test purposes only
@@ -583,10 +583,15 @@ namespace Gcn3ISA
               default:
                 {
                     assert(sizeof(DataType) <= sizeof(srfData));
-                    DataType misc_val
-                        = (DataType)_gpuDynInst->readMiscReg(_opIdx);
+                    DataType misc_val(0);
+                    if (isConstVal(_opIdx)) {
+                        misc_val = (DataType)_gpuDynInst
+                            ->readConstVal<DataType>(_opIdx);
+                    } else {
+                        misc_val = (DataType)_gpuDynInst->readMiscReg(_opIdx);
+                    }
                     std::memcpy((void*)srfData.data(), (void*)&misc_val,
-                        sizeof(DataType));
+                                sizeof(DataType));
                 }
             }
         }
index 0872ff9f8671fe2134303eba7887ab9ea08b042e..016160f544f1f5657c499f5162eeb77f812e513d 100644 (file)
@@ -162,6 +162,31 @@ namespace Gcn3ISA
         return regIdx;
     }
 
+    bool
+    isPosConstVal(int opIdx)
+    {
+        bool is_pos_const_val = (opIdx >= REG_INT_CONST_POS_MIN
+            && opIdx <= REG_INT_CONST_POS_MAX);
+
+        return is_pos_const_val;
+    }
+
+    bool
+    isNegConstVal(int opIdx)
+    {
+        bool is_neg_const_val = (opIdx >= REG_INT_CONST_NEG_MIN
+            && opIdx <= REG_INT_CONST_NEG_MAX);
+
+        return is_neg_const_val;
+    }
+
+    bool
+    isConstVal(int opIdx)
+    {
+        bool is_const_val = isPosConstVal(opIdx) || isNegConstVal(opIdx);
+        return is_const_val;
+    }
+
     bool
     isLiteral(int opIdx)
     {
index 9922e5d7ac9e6213987e2fbab9faabcd69249517..6e95807a575dc672d754ad8ec47b6852c289c7b5 100644 (file)
@@ -238,6 +238,9 @@ namespace Gcn3ISA
 
     std::string opSelectorToRegSym(int opIdx, int numRegs=0);
     int opSelectorToRegIdx(int opIdx, int numScalarRegs);
+    bool isPosConstVal(int opIdx);
+    bool isNegConstVal(int opIdx);
+    bool isConstVal(int opIdx);
     bool isLiteral(int opIdx);
     bool isScalarReg(int opIdx);
     bool isVectorReg(int opIdx);
index 6fc71f0fd035adb0c7bf21bf3430218f01a19872..15cbd550dba03f45496f9ff0ca4a8a21277c5392 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Advanced Micro Devices, Inc.
+ * Copyright (c) 2015-2018 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * For use for simulation and test purposes only
@@ -48,6 +48,12 @@ class GPUExecContext
     Wavefront* wavefront();
     ComputeUnit* computeUnit();
 
+    template<typename T> T
+    readConstVal(int opIdx) const
+    {
+        return gpuISA->readConstVal<T>(opIdx);
+    }
+
     RegVal readMiscReg(int opIdx) const;
     void writeMiscReg(int opIdx, RegVal operandVal);