From 91f7486482b8262b7562afad6b83ef9d11233600 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 9 Aug 2021 01:19:27 -0700 Subject: [PATCH] cpu: Use std::variant to simplify InstResult. std::variant is a similar to (and also modestly superior to) MultiResult. Use it instead to simplify InstResult. Change-Id: I22338f5e89814c6d13538129757158126013a414 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/49127 Reviewed-by: Giacomo Travaglini Maintainer: Giacomo Travaglini Tested-by: kokoro --- src/cpu/checker/cpu.hh | 9 +-- src/cpu/checker/cpu_impl.hh | 5 +- src/cpu/inst_res.hh | 131 +++++++++++------------------------- src/cpu/o3/dyn_inst.hh | 9 +-- 4 files changed, 47 insertions(+), 107 deletions(-) diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 4ed21f5452..e32d12d560 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -248,24 +248,21 @@ class CheckerCPU : public BaseCPU, public ExecContext void setScalarResult(T&& t) { - result.push(InstResult(std::forward(t), - InstResult::ResultType::Scalar)); + result.push(InstResult(std::forward(t))); } template void setVecResult(T&& t) { - result.push(InstResult(std::forward(t), - InstResult::ResultType::VecReg)); + result.push(InstResult(std::forward(t))); } template void setVecPredResult(T&& t) { - result.push(InstResult(std::forward(t), - InstResult::ResultType::VecPredReg)); + result.push(InstResult(std::forward(t))); } void diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 26c22a5d3d..638a7371b1 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -477,15 +477,14 @@ Checker::validateExecution(const DynInstPtr &inst) // Unverifiable instructions assume they were executed // properly by the CPU. Grab the result from the // instruction and write it to the register. - copyResult(inst, InstResult(0ul, InstResult::ResultType::Scalar), idx); + copyResult(inst, InstResult((RegVal)0), idx); } else if (inst->numDestRegs() > 0 && !result.empty()) { DPRINTF(Checker, "Dest regs %d, number of checker dest regs %d\n", inst->numDestRegs(), result.size()); for (int i = 0; i < inst->numDestRegs() && !result.empty(); i++) { checker_val = result.front(); result.pop(); - inst_val = inst->popResult( - InstResult(0ul, InstResult::ResultType::Scalar)); + inst_val = inst->popResult(InstResult((RegVal)0)); if (checker_val != inst_val) { result_mismatch = true; idx = i; diff --git a/src/cpu/inst_res.hh b/src/cpu/inst_res.hh index 1a774c9dd6..19ce640e64 100644 --- a/src/cpu/inst_res.hh +++ b/src/cpu/inst_res.hh @@ -39,8 +39,9 @@ #define __CPU_INST_RES_HH__ #include +#include -#include "arch/generic/vec_reg.hh" +#include "arch/vecregs.hh" #include "base/types.hh" namespace gem5 @@ -48,81 +49,26 @@ namespace gem5 class InstResult { - public: - union MultiResult - { - RegVal integer; - TheISA::VecRegContainer vector; - TheISA::VecPredRegContainer pred; - MultiResult() {} - }; - - enum class ResultType - { - Scalar, - VecReg, - VecPredReg, - NumResultTypes, - Invalid - }; - private: - MultiResult result; - ResultType type; + std::variant result; public: /** Default constructor creates an invalid result. */ - InstResult() : type(ResultType::Invalid) { } + InstResult() = default; InstResult(const InstResult &) = default; - /** Scalar result from scalar. */ - template - explicit InstResult(T i, const ResultType& t) : type(t) - { - static_assert(std::is_integral_v ^ std::is_floating_point_v, - "Parameter type is neither integral nor fp, or it is both"); - if constexpr (std::is_integral_v) { - result.integer = i; - } else if constexpr (std::is_floating_point_v) { - result.integer = floatToBits(i); - } - } - /** Vector result. */ - explicit InstResult(const TheISA::VecRegContainer& v, const ResultType& t) - : type(t) - { - result.vector = v; - } - /** Predicate result. */ - explicit InstResult(const TheISA::VecPredRegContainer& v, - const ResultType& t) - : type(t) - { - result.pred = v; - } - InstResult& + template + explicit InstResult(T val) : result(val) {} + + template >> + explicit InstResult(T val) : result(floatToBits(val)) {} + + InstResult & operator=(const InstResult& that) { - type = that.type; - switch (type) { - // Given that misc regs are not written to, there may be invalids in - //the result stack. - case ResultType::Invalid: - break; - case ResultType::Scalar: - result.integer = that.result.integer; - break; - case ResultType::VecReg: - result.vector = that.result.vector; - break; - case ResultType::VecPredReg: - result.pred = that.result.pred; - break; - - default: - panic("Assigning result from unknown result type"); - break; - } + result = that.result; return *this; } @@ -133,20 +79,7 @@ class InstResult bool operator==(const InstResult& that) const { - if (this->type != that.type) - return false; - switch (type) { - case ResultType::Scalar: - return result.integer == that.result.integer; - case ResultType::VecReg: - return result.vector == that.result.vector; - case ResultType::VecPredReg: - return result.pred == that.result.pred; - case ResultType::Invalid: - return false; - default: - panic("Unknown type of result: %d\n", (int)type); - } + return result == that.result; } bool @@ -158,45 +91,59 @@ class InstResult /** Checks */ /** @{ */ /** Is this a scalar result?. */ - bool isScalar() const { return type == ResultType::Scalar; } + bool + isScalar() const + { + return std::holds_alternative(result); + } /** Is this a vector result?. */ - bool isVector() const { return type == ResultType::VecReg; } + bool + isVector() const + { + return std::holds_alternative(result); + } /** Is this a predicate result?. */ - bool isPred() const { return type == ResultType::VecPredReg; } + bool + isPred() const + { + return std::holds_alternative(result); + } + /** Is this a valid result?. */ - bool isValid() const { return type != ResultType::Invalid; } + bool isValid() const { return result.index() != 0; } /** @} */ /** Explicit cast-like operations. */ /** @{ */ - const uint64_t& + RegVal asInteger() const { assert(isScalar()); - return result.integer; + return std::get(result); } /** Cast to integer without checking type. * This is required to have the o3 cpu checker happy, as it * compares results as integers without being fully aware of * their nature. */ - const uint64_t& + RegVal asIntegerNoAssert() const { - return result.integer; + const RegVal *ptr = std::get_if(&result); + return ptr ? *ptr : 0; } const TheISA::VecRegContainer& asVector() const { panic_if(!isVector(), "Converting scalar (or invalid) to vector!!"); - return result.vector; + return std::get(result); } const TheISA::VecPredRegContainer& asPred() const { panic_if(!isPred(), "Converting scalar (or invalid) to predicate!!"); - return result.pred; + return std::get(result); } /** @} */ diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index a23be389c1..24c34b05b1 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -777,8 +777,7 @@ class DynInst : public ExecContext, public RefCounted setScalarResult(T &&t) { if (instFlags[RecordResult]) { - instResult.push(InstResult(std::forward(t), - InstResult::ResultType::Scalar)); + instResult.push(InstResult(std::forward(t))); } } @@ -788,8 +787,7 @@ class DynInst : public ExecContext, public RefCounted setVecResult(T &&t) { if (instFlags[RecordResult]) { - instResult.push(InstResult(std::forward(t), - InstResult::ResultType::VecReg)); + instResult.push(InstResult(std::forward(t))); } } @@ -799,8 +797,7 @@ class DynInst : public ExecContext, public RefCounted setVecPredResult(T &&t) { if (instFlags[RecordResult]) { - instResult.push(InstResult(std::forward(t), - InstResult::ResultType::VecPredReg)); + instResult.push(InstResult(std::forward(t))); } } /** @} */