arch: Eliminate the "Lane" view of vector registers.

Nothing uses it.

Change-Id: I1b8a629cfff5c9a58584045ac25424fa8b6dfb24
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/41900
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
Gabe Black
2021-02-25 00:55:15 -08:00
parent 05e580f146
commit fa8a528db5

View File

@@ -47,8 +47,8 @@
* As the (maximum) length of the physical vector register is a compile-time
* constant, it is defined as a template parameter.
*
* This file also describes two views of the container that have semantic
* information about the bytes. The first of this views is VecRegT.
* This file also describe one view of the container that has semantic
* information about the bytes, the VecRegT.
* A VecRegT is a view of a VecRegContainer (by reference). The VecRegT has
* a type (VecElem) to which bytes are casted, and the amount of such
* elements that the vector contains (NumElems). The size of a view,
@@ -56,18 +56,9 @@
* underlying container. As VecRegT has some degree of type information it
* has vector semantics, and defines the index operator ([]) to get
* references to particular bytes understood as a VecElem.
* The second view of a container implemented in this file is VecLaneT, which
* is a view of a subset of the container.
* A VecLaneT is a view of a lane of a vector register, where a lane is
* identified by a type (VecElem) and an index (although the view is
* unaware of its index). Operations on the lane are directly applied to
* the corresponding bytes of the underlying VecRegContainer through a
* reference.
*
* The intended usage is requesting views to the VecRegContainer via the
* member 'as' for VecRegT and the member 'laneView' for VecLaneT. Kindly
* find an example of usage in the following.
*
* member 'as' for VecRegT.
*
* // We declare 512 bits vectors
* using Vec512 = VecRegContainer<64>;
@@ -100,41 +91,6 @@
* xc->setWriteRegOperand(this, 0, vdstraw);
* }
*
* // Usage example, for a micro op that operates over lane number _lidx:
* VecFloatLaneAdd(ExecContext* xd) {
* // Request source vector register to the execution context (const as it
* // is read only).
* const Vec512& vsrc1raw = xc->readVecRegOperand(this, 0);
* // View it as a lane of a vector of floats (we could just specify the
* // first template parametre, the second is derived by the constness of
* // vsrc1raw).
* VecLaneT<float, true>& src1 = vsrc1raw->laneView<float>(this->_lidx);
*
* // Second source and view
* const Vec512& vsrc2raw = xc->readVecRegOperand(this, 1);
* VecLaneT<float, true>& src2 = vsrc2raw->laneView<float>(this->_lidx);
*
* // (Writable) destination and view
* // As this is a partial write, we need the exec context to support that
* // through, e.g., 'readVecRegOperandToWrite' returning a writable
* // reference to the register
* Vec512 vdstraw = xc->readVecRegOperandToWrite(this, 3);
* VecLaneT<float, false>& dst = vdstraw->laneView<float>(this->_lidx);
*
* dst = src1 + src2;
* // There is no need to copy the value back into the exec context, as
* // the assignment to dst modifies the appropriate bytes in vdstraw which
* // is in turn, a reference to the register in the cpu model.
* // For operations that do conditional writeback, we can decouple the
* // write by doing:
* // auto tmp = src1 + src2;
* // if (test) {
* // dst = tmp; // do writeback
* // } else {
* // // do not do writeback
* // }
* }
*
*/
#ifndef __ARCH_GENERIC_VEC_REG_HH__
@@ -257,10 +213,6 @@ class VecRegT
operator Container&() { return container; }
};
/* Forward declaration. */
template <typename VecElem, bool Const>
class VecLaneT;
/**
* Vector Register Abstraction
* This generic class is the model in a particularization of MVC, to vector
@@ -402,14 +354,6 @@ class VecRegContainer
return VecRegT<VecElem, NumElems, false>(*this);
}
template <typename VecElem, int LaneIdx>
VecLaneT<VecElem, false> laneView();
template <typename VecElem, int LaneIdx>
VecLaneT<VecElem, true> laneView() const;
template <typename VecElem>
VecLaneT<VecElem, false> laneView(int laneIdx);
template <typename VecElem>
VecLaneT<VecElem, true> laneView(int laneIdx) const;
/** @} */
/**
* Output operator.
@@ -424,217 +368,6 @@ class VecRegContainer
}
};
/** We define an auxiliary abstraction for LaneData. The ISA should care
* about the semantics of a, e.g., 32bit element, treating it as a signed or
* unsigned int, or a float depending on the semantics of a particular
* instruction. On the other hand, the cpu model should only care about it
* being a 32-bit value. */
enum class LaneSize
{
Empty = 0,
Byte,
TwoByte,
FourByte,
EightByte,
};
/** LaneSize is an abstraction of a LS byte value for the execution and thread
* contexts to handle values just depending on its width. That way, the ISA
* can request, for example, the second 4 byte lane of register 5 to the model.
* The model serves that value, agnostic of the semantics of those bits. Then,
* it is up to the ISA to interpret those bits as a float, or as an uint.
* To maximize the utility, this class implements the assignment operator and
* the casting to equal-size types.
* As opposed to a RegLaneT, LaneData is not 'backed' by a VecRegContainer.
* The idea is:
* When data is passed and is susceptible to being copied, use LaneData, as
* copying the primitive type is build on is cheap.
* When data is passed as references (const or not), use RegLaneT, as all
* operations happen 'in place', avoiding any copies (no copies is always
* cheaper than cheap copies), especially when things are inlined, and
* references are not explicitly passed.
*/
template <LaneSize LS>
class LaneData
{
public:
/** Alias to the native type of the appropriate size. */
using UnderlyingType =
typename std::conditional<LS == LaneSize::EightByte, uint64_t,
typename std::conditional<LS == LaneSize::FourByte, uint32_t,
typename std::conditional<LS == LaneSize::TwoByte, uint16_t,
typename std::conditional<LS == LaneSize::Byte, uint8_t,
void>::type
>::type
>::type
>::type;
private:
static constexpr auto ByteSz = sizeof(UnderlyingType);
UnderlyingType _val;
using MyClass = LaneData<LS>;
public:
template <typename T> explicit
LaneData(typename std::enable_if_t<sizeof(T) == ByteSz, const T&> t)
: _val(t) {}
template <typename T>
typename std::enable_if_t<sizeof(T) == ByteSz, MyClass&>
operator=(const T& that)
{
_val = that;
return *this;
}
template<typename T,
typename std::enable_if_t<sizeof(T) == ByteSz, int> I = 0>
operator T() const {
return *static_cast<const T*>(&_val);
}
};
/** Output operator overload for LaneData<Size>. */
template <LaneSize LS>
inline std::ostream&
operator<<(std::ostream& os, const LaneData<LS>& d)
{
return os << static_cast<typename LaneData<LS>::UnderlyingType>(d);
}
/** Vector Lane abstraction
* Another view of a container. This time only a partial part of it is exposed.
* @tparam VecElem Type of each element of the vector.
* @tparam Const Indicate if the underlying container can be modified through
* the view.
*/
/** @{ */
/* General */
template <typename VecElem, bool Const>
class VecLaneT
{
public:
/** VecRegContainer friendship to access private VecLaneT constructors.
* Only VecRegContainers can build VecLanes.
*/
/** @{ */
friend VecLaneT<VecElem, !Const>;
/*template <size_t Sz>
friend class VecRegContainer;*/
friend class VecRegContainer<8>;
friend class VecRegContainer<16>;
friend class VecRegContainer<32>;
friend class VecRegContainer<64>;
friend class VecRegContainer<128>;
friend class VecRegContainer<256>;
friend class VecRegContainer<MaxVecRegLenInBytes>;
/** My type alias. */
using MyClass = VecLaneT<VecElem, Const>;
private:
using Cont = typename std::conditional<Const,
const VecElem,
VecElem>::type;
static_assert(!std::is_const<VecElem>::value || Const,
"Asked for non-const lane of const type!");
static_assert(std::is_integral<VecElem>::value,
"VecElem type is not integral!");
/** Reference to data. */
Cont& container;
/** Constructor */
VecLaneT(Cont& cont) : container(cont) { }
public:
/** Assignment operators.
* Assignment operators are only enabled if the underlying container is
* non-constant.
*/
/** @{ */
template <bool Assignable = !Const>
typename std::enable_if_t<Assignable, MyClass&>
operator=(const VecElem& that) {
container = that;
return *this;
}
/**
* Generic.
* Generic bitwise assignment. Narrowing and widening assignemnts are
* not allowed, pre-treatment of the rhs is required to conform.
*/
template <bool Assignable = !Const, typename T>
typename std::enable_if_t<Assignable, MyClass&>
operator=(const T& that) {
static_assert(sizeof(T) >= sizeof(VecElem),
"Attempt to perform widening bitwise copy.");
static_assert(sizeof(T) <= sizeof(VecElem),
"Attempt to perform narrowing bitwise copy.");
container = static_cast<VecElem>(that);
return *this;
}
/** @} */
/** Cast to vecElem. */
operator VecElem() const { return container; }
/** Constification. */
template <bool Cond = !Const, typename std::enable_if_t<Cond, int> = 0>
operator VecLaneT<typename std::enable_if_t<Cond, VecElem>, true>()
{
return VecLaneT<VecElem, true>(container);
}
};
namespace std {
template<typename T, bool Const>
struct add_const<VecLaneT<T, Const>> { typedef VecLaneT<T, true> type; };
}
/** View as the Nth lane of type VecElem. */
template <size_t Sz>
template <typename VecElem, int LaneIdx>
VecLaneT<VecElem, false>
VecRegContainer<Sz>::laneView()
{
return VecLaneT<VecElem, false>(as<VecElem>()[LaneIdx]);
}
/** View as the const Nth lane of type VecElem. */
template <size_t Sz>
template <typename VecElem, int LaneIdx>
VecLaneT<VecElem, true>
VecRegContainer<Sz>::laneView() const
{
return VecLaneT<VecElem, true>(as<VecElem>()[LaneIdx]);
}
/** View as the Nth lane of type VecElem. */
template <size_t Sz>
template <typename VecElem>
VecLaneT<VecElem, false>
VecRegContainer<Sz>::laneView(int laneIdx)
{
return VecLaneT<VecElem, false>(as<VecElem>()[laneIdx]);
}
/** View as the const Nth lane of type VecElem. */
template <size_t Sz>
template <typename VecElem>
VecLaneT<VecElem, true>
VecRegContainer<Sz>::laneView(int laneIdx) const
{
return VecLaneT<VecElem, true>(as<VecElem>()[laneIdx]);
}
using VecLane8 = VecLaneT<uint8_t, false>;
using VecLane16 = VecLaneT<uint16_t, false>;
using VecLane32 = VecLaneT<uint32_t, false>;
using VecLane64 = VecLaneT<uint64_t, false>;
using ConstVecLane8 = VecLaneT<uint8_t, true>;
using ConstVecLane16 = VecLaneT<uint16_t, true>;
using ConstVecLane32 = VecLaneT<uint32_t, true>;
using ConstVecLane64 = VecLaneT<uint64_t, true>;
/**
* Calls required for serialization/deserialization
*/