cpu: Generalize the vec reg types out of InstResult.

Use templates to delegate knowing what these types are to whatever is using
InstResult. This will need to be even more generalized at these call
sights so that we don't just push around the dependencies, but that will
have to be handled later.

Change-Id: I45915d70ea06caed06f0ccf356f9e2e1acbd6c61
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/49131
Reviewed-by: Yu-hsin Wang <yuhsingw@google.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-08-09 02:41:05 -07:00
parent a1fa9f94b8
commit abf6b8b7b6
2 changed files with 48 additions and 67 deletions

View File

@@ -471,7 +471,6 @@ Checker<DynInstPtr>::validateExecution(const DynInstPtr &inst)
int idx = -1;
bool result_mismatch = false;
bool scalar_mismatch = false;
bool vector_mismatch = false;
if (inst->isUnverifiable()) {
// Unverifiable instructions assume they were executed
@@ -488,10 +487,7 @@ Checker<DynInstPtr>::validateExecution(const DynInstPtr &inst)
if (checker_val != inst_val) {
result_mismatch = true;
idx = i;
scalar_mismatch = checker_val.isScalar();
vector_mismatch = checker_val.isVector();
panic_if(!(scalar_mismatch || vector_mismatch),
"Unknown type of result\n");
scalar_mismatch = checker_val.is<RegVal>();
}
}
} // Checker CPU checks all the saved results in the dyninst passed by
@@ -504,8 +500,8 @@ Checker<DynInstPtr>::validateExecution(const DynInstPtr &inst)
if (scalar_mismatch) {
warn("%lli: Instruction results (%i) do not match! (Values may"
" not actually be integers) Inst: %#x, checker: %#x",
curTick(), idx, inst_val.asIntegerNoAssert(),
checker_val.asInteger());
curTick(), idx, inst_val.asNoAssert<RegVal>(),
checker_val.as<RegVal>());
}
// It's useful to verify load values from memory, but in MP
@@ -590,28 +586,22 @@ Checker<DynInstPtr>::copyResult(
const RegId& idx = inst->destRegIdx(start_idx);
switch (idx.classValue()) {
case IntRegClass:
panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
thread->setIntReg(idx.index(), mismatch_val.asInteger());
thread->setIntReg(idx.index(), mismatch_val.as<RegVal>());
break;
case FloatRegClass:
panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
thread->setFloatReg(idx.index(), mismatch_val.asInteger());
thread->setFloatReg(idx.index(), mismatch_val.as<RegVal>());
break;
case VecRegClass:
panic_if(!mismatch_val.isVector(), "Unexpected type of result");
thread->setVecReg(idx, mismatch_val.asVector());
thread->setVecReg(idx, mismatch_val.as<TheISA::VecRegContainer>());
break;
case VecElemClass:
panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
thread->setVecElem(idx, mismatch_val.asInteger());
thread->setVecElem(idx, mismatch_val.as<RegVal>());
break;
case CCRegClass:
panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
thread->setCCReg(idx.index(), mismatch_val.asInteger());
thread->setCCReg(idx.index(), mismatch_val.as<RegVal>());
break;
case MiscRegClass:
panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
thread->setMiscReg(idx.index(), mismatch_val.asInteger());
thread->setMiscReg(idx.index(), mismatch_val.as<RegVal>());
break;
default:
panic("Unknown register class: %d", (int)idx.classValue());
@@ -624,27 +614,21 @@ Checker<DynInstPtr>::copyResult(
res = inst->popResult();
switch (idx.classValue()) {
case IntRegClass:
panic_if(!res.isScalar(), "Unexpected type of result");
thread->setIntReg(idx.index(), res.asInteger());
thread->setIntReg(idx.index(), res.as<RegVal>());
break;
case FloatRegClass:
panic_if(!res.isScalar(), "Unexpected type of result");
thread->setFloatReg(idx.index(), res.asInteger());
thread->setFloatReg(idx.index(), res.as<RegVal>());
break;
case VecRegClass:
panic_if(!res.isVector(), "Unexpected type of result");
thread->setVecReg(idx, res.asVector());
thread->setVecReg(idx, res.as<TheISA::VecRegContainer>());
break;
case VecElemClass:
panic_if(!res.isScalar(), "Unexpected type of result");
thread->setVecElem(idx, res.asInteger());
thread->setVecElem(idx, res.as<RegVal>());
break;
case CCRegClass:
panic_if(!res.isScalar(), "Unexpected type of result");
thread->setCCReg(idx.index(), res.asInteger());
thread->setCCReg(idx.index(), res.as<RegVal>());
break;
case MiscRegClass:
panic_if(res.isValid(), "MiscReg expecting invalid result");
// Try to get the proper misc register index for ARM here...
thread->setMiscReg(idx.index(), 0);
break;

View File

@@ -41,7 +41,6 @@
#include <any>
#include <type_traits>
#include "arch/vecregs.hh"
#include "base/logging.hh"
#include "base/types.hh"
@@ -88,6 +87,10 @@ class InstResult
{
static_assert(!std::is_pointer_v<T>,
"InstResult shouldn't point to external data.");
// Floating point values should be converted to/from ints using
// floatToBits and bitsToFloat, and not stored in InstResult directly.
static_assert(!std::is_floating_point_v<T>,
"Floating point values should be converted to/from ints.");
}
// Convert floating point values to integers.
@@ -127,23 +130,21 @@ class InstResult
/** Checks */
/** @{ */
/** Is this a scalar result?. */
template <typename T>
bool
isScalar() const
is() const
{
return result.type() == typeid(RegVal);
static_assert(!std::is_floating_point_v<T>,
"Floating point values should be converted to/from ints.");
return result.type() == typeid(T);
}
/** Is this a vector result?. */
bool
isVector() const
template <typename T>
std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, RegVal>, bool>
is() const
{
return result.type() == typeid(TheISA::VecRegContainer);
}
/** Is this a predicate result?. */
bool
isPred() const
{
return result.type() == typeid(TheISA::VecPredRegContainer);
return is<RegVal>();
}
/** Is this a valid result?. */
@@ -152,37 +153,33 @@ class InstResult
/** Explicit cast-like operations. */
/** @{ */
RegVal
asInteger() const
template <typename T>
T
as() const
{
panic_if(!isScalar(), "Converting non-scalar to scalar!!");
return std::any_cast<RegVal>(result);
assert(is<T>());
return std::any_cast<T>(result);
}
template <typename T>
std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, RegVal>,
RegVal>
as() const
{
return as<RegVal>();
}
/** 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. */
RegVal
asIntegerNoAssert() const
template <typename T>
T
asNoAssert() const
{
if (!isScalar())
return 0;
return std::any_cast<RegVal>(result);
}
TheISA::VecRegContainer
asVector() const
{
panic_if(!isVector(), "Converting scalar (or invalid) to vector!!");
return std::any_cast<TheISA::VecRegContainer>(result);
}
TheISA::VecPredRegContainer
asPred() const
{
panic_if(!isPred(), "Converting scalar (or invalid) to predicate!!");
return std::any_cast<TheISA::VecPredRegContainer>(result);
if (!is<T>())
return T{};
return as<T>();
}
/** @} */