113610Sgiacomo.gabrielli@arm.com// Copyright (c) 2017 ARM Limited 213610Sgiacomo.gabrielli@arm.com// All rights reserved 313610Sgiacomo.gabrielli@arm.com// 413610Sgiacomo.gabrielli@arm.com// The license below extends only to copyright in the software and shall 513610Sgiacomo.gabrielli@arm.com// not be construed as granting a license to any other intellectual 613610Sgiacomo.gabrielli@arm.com// property including but not limited to intellectual property relating 713610Sgiacomo.gabrielli@arm.com// to a hardware implementation of the functionality of the software 813610Sgiacomo.gabrielli@arm.com// licensed hereunder. You may use the software subject to the license 913610Sgiacomo.gabrielli@arm.com// terms below provided that you ensure that this notice is replicated 1013610Sgiacomo.gabrielli@arm.com// unmodified and in its entirety in all distributions of the software, 1113610Sgiacomo.gabrielli@arm.com// modified or unmodified, in source code or in binary form. 1213610Sgiacomo.gabrielli@arm.com// 1313610Sgiacomo.gabrielli@arm.com// Redistribution and use in source and binary forms, with or without 1413610Sgiacomo.gabrielli@arm.com// modification, are permitted provided that the following conditions are 1513610Sgiacomo.gabrielli@arm.com// met: redistributions of source code must retain the above copyright 1613610Sgiacomo.gabrielli@arm.com// notice, this list of conditions and the following disclaimer; 1713610Sgiacomo.gabrielli@arm.com// redistributions in binary form must reproduce the above copyright 1813610Sgiacomo.gabrielli@arm.com// notice, this list of conditions and the following disclaimer in the 1913610Sgiacomo.gabrielli@arm.com// documentation and/or other materials provided with the distribution; 2013610Sgiacomo.gabrielli@arm.com// neither the name of the copyright holders nor the names of its 2113610Sgiacomo.gabrielli@arm.com// contributors may be used to endorse or promote products derived from 2213610Sgiacomo.gabrielli@arm.com// this software without specific prior written permission. 2313610Sgiacomo.gabrielli@arm.com// 2413610Sgiacomo.gabrielli@arm.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2513610Sgiacomo.gabrielli@arm.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2613610Sgiacomo.gabrielli@arm.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2713610Sgiacomo.gabrielli@arm.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2813610Sgiacomo.gabrielli@arm.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2913610Sgiacomo.gabrielli@arm.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3013610Sgiacomo.gabrielli@arm.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3113610Sgiacomo.gabrielli@arm.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3213610Sgiacomo.gabrielli@arm.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3313610Sgiacomo.gabrielli@arm.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3413610Sgiacomo.gabrielli@arm.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3513610Sgiacomo.gabrielli@arm.com// 3613610Sgiacomo.gabrielli@arm.com// Authors: Giacomo Gabrielli 3713610Sgiacomo.gabrielli@arm.com// Rekai Gonzalez 3813610Sgiacomo.gabrielli@arm.com// Javier Setoain 3913610Sgiacomo.gabrielli@arm.com 4013610Sgiacomo.gabrielli@arm.com#ifndef __ARCH_GENERIC_VEC_PRED_REG_HH__ 4113610Sgiacomo.gabrielli@arm.com#define __ARCH_GENERIC_VEC_PRED_REG_HH__ 4213610Sgiacomo.gabrielli@arm.com 4313610Sgiacomo.gabrielli@arm.com#include <array> 4413610Sgiacomo.gabrielli@arm.com#include <cassert> 4513610Sgiacomo.gabrielli@arm.com#include <vector> 4613610Sgiacomo.gabrielli@arm.com 4713610Sgiacomo.gabrielli@arm.com#include "arch/generic/vec_reg.hh" 4813610Sgiacomo.gabrielli@arm.com#include "base/cprintf.hh" 4913610Sgiacomo.gabrielli@arm.com 5013610Sgiacomo.gabrielli@arm.comtemplate <size_t NumBits, bool Packed> 5113610Sgiacomo.gabrielli@arm.comclass VecPredRegContainer; 5213610Sgiacomo.gabrielli@arm.com 5313610Sgiacomo.gabrielli@arm.com/// Predicate register view. 5413610Sgiacomo.gabrielli@arm.com/// 5513610Sgiacomo.gabrielli@arm.com/// This generic class implements the View in an MVC pattern, similarly to 5613610Sgiacomo.gabrielli@arm.com/// @see VecRegT. Since predicates are mainly used in conjunction with vectors 5713610Sgiacomo.gabrielli@arm.com/// to specify which lanes are active in a vector operation, the class is 5813610Sgiacomo.gabrielli@arm.com/// templated on the vector element type to simplify ISA definitions. 5913610Sgiacomo.gabrielli@arm.com/// @tparam VecElem Type of the vector elements. 6013610Sgiacomo.gabrielli@arm.com/// @tparam NumElems Number of vector elements making up the view. 6113610Sgiacomo.gabrielli@arm.com/// @tparam Packed True if the predicate register relies on a packed 6213610Sgiacomo.gabrielli@arm.com/// representation, i.e. adjacent bits refer to different vector elements 6313610Sgiacomo.gabrielli@arm.com/// irrespective of the vector element size (e.g. this is the case for 6413610Sgiacomo.gabrielli@arm.com/// AVX-512). If false, the predicate register relies on an unpacked 6513610Sgiacomo.gabrielli@arm.com/// representation, where each bit refers to the corresponding byte in a vector 6613610Sgiacomo.gabrielli@arm.com/// register (e.g. this is the case for ARM SVE). 6713610Sgiacomo.gabrielli@arm.com/// @tparam Const True if the underlying container can be modified through 6813610Sgiacomo.gabrielli@arm.com/// the view. 6913610Sgiacomo.gabrielli@arm.comtemplate <typename VecElem, size_t NumElems, bool Packed, bool Const> 7013610Sgiacomo.gabrielli@arm.comclass VecPredRegT 7113610Sgiacomo.gabrielli@arm.com{ 7213610Sgiacomo.gabrielli@arm.com protected: 7313610Sgiacomo.gabrielli@arm.com /// Size of the register in bits. 7413610Sgiacomo.gabrielli@arm.com static constexpr size_t NUM_BITS = Packed ? NumElems : 7513610Sgiacomo.gabrielli@arm.com sizeof(VecElem) * NumElems; 7613610Sgiacomo.gabrielli@arm.com 7713610Sgiacomo.gabrielli@arm.com public: 7813610Sgiacomo.gabrielli@arm.com /// Container type alias. 7913610Sgiacomo.gabrielli@arm.com using Container = typename std::conditional< 8013610Sgiacomo.gabrielli@arm.com Const, 8113610Sgiacomo.gabrielli@arm.com const VecPredRegContainer<NUM_BITS, Packed>, 8213610Sgiacomo.gabrielli@arm.com VecPredRegContainer<NUM_BITS, Packed>>::type; 8313610Sgiacomo.gabrielli@arm.com 8413610Sgiacomo.gabrielli@arm.com protected: 8513610Sgiacomo.gabrielli@arm.com // Alias for this type 8613610Sgiacomo.gabrielli@arm.com using MyClass = VecPredRegT<VecElem, NumElems, Packed, Const>; 8713610Sgiacomo.gabrielli@arm.com /// Container corresponding to this view. 8813610Sgiacomo.gabrielli@arm.com Container& container; 8913610Sgiacomo.gabrielli@arm.com 9013610Sgiacomo.gabrielli@arm.com public: 9113610Sgiacomo.gabrielli@arm.com VecPredRegT(Container& c) : container(c) {} 9213610Sgiacomo.gabrielli@arm.com 9313610Sgiacomo.gabrielli@arm.com /// Reset the register to an all-false value. 9413610Sgiacomo.gabrielli@arm.com template<bool Condition = !Const> 9513610Sgiacomo.gabrielli@arm.com typename std::enable_if<Condition, void>::type 9613610Sgiacomo.gabrielli@arm.com reset() { container.reset(); } 9713610Sgiacomo.gabrielli@arm.com 9813610Sgiacomo.gabrielli@arm.com /// Reset the register to an all-true value. 9913610Sgiacomo.gabrielli@arm.com template<bool Condition = !Const> 10013610Sgiacomo.gabrielli@arm.com typename std::enable_if<Condition, void>::type 10113610Sgiacomo.gabrielli@arm.com set() { container.set(); } 10213610Sgiacomo.gabrielli@arm.com 10313610Sgiacomo.gabrielli@arm.com template<bool Condition = !Const> 10413610Sgiacomo.gabrielli@arm.com typename std::enable_if<Condition, MyClass&>::type 10513610Sgiacomo.gabrielli@arm.com operator=(const MyClass& that) 10613610Sgiacomo.gabrielli@arm.com { 10713610Sgiacomo.gabrielli@arm.com container = that.container; 10813610Sgiacomo.gabrielli@arm.com return *this; 10913610Sgiacomo.gabrielli@arm.com } 11013610Sgiacomo.gabrielli@arm.com 11113610Sgiacomo.gabrielli@arm.com const bool& 11213610Sgiacomo.gabrielli@arm.com operator[](size_t idx) const 11313610Sgiacomo.gabrielli@arm.com { 11413610Sgiacomo.gabrielli@arm.com return container[idx * (Packed ? 1 : sizeof(VecElem))]; 11513610Sgiacomo.gabrielli@arm.com } 11613610Sgiacomo.gabrielli@arm.com 11713610Sgiacomo.gabrielli@arm.com template<bool Condition = !Const> 11813610Sgiacomo.gabrielli@arm.com typename std::enable_if<Condition, bool&>::type 11913610Sgiacomo.gabrielli@arm.com operator[](size_t idx) 12013610Sgiacomo.gabrielli@arm.com { 12113610Sgiacomo.gabrielli@arm.com return container[idx * (Packed ? 1 : sizeof(VecElem))]; 12213610Sgiacomo.gabrielli@arm.com } 12313610Sgiacomo.gabrielli@arm.com 12413610Sgiacomo.gabrielli@arm.com /// Return an element of the predicate register as it appears 12513610Sgiacomo.gabrielli@arm.com /// in the raw (untyped) internal representation 12613610Sgiacomo.gabrielli@arm.com uint8_t 12713610Sgiacomo.gabrielli@arm.com get_raw(size_t idx) const 12813610Sgiacomo.gabrielli@arm.com { 12913610Sgiacomo.gabrielli@arm.com return container.get_bits(idx * (Packed ? 1 : sizeof(VecElem)), 13013610Sgiacomo.gabrielli@arm.com (Packed ? 1 : sizeof(VecElem))); 13113610Sgiacomo.gabrielli@arm.com } 13213610Sgiacomo.gabrielli@arm.com 13313610Sgiacomo.gabrielli@arm.com /// Write a raw value in an element of the predicate register 13413610Sgiacomo.gabrielli@arm.com template<bool Condition = !Const> 13513610Sgiacomo.gabrielli@arm.com typename std::enable_if<Condition, void>::type 13613610Sgiacomo.gabrielli@arm.com set_raw(size_t idx, uint8_t val) 13713610Sgiacomo.gabrielli@arm.com { 13813610Sgiacomo.gabrielli@arm.com container.set_bits(idx * (Packed ? 1 : sizeof(VecElem)), 13913610Sgiacomo.gabrielli@arm.com (Packed ? 1 : sizeof(VecElem)), val); 14013610Sgiacomo.gabrielli@arm.com } 14113610Sgiacomo.gabrielli@arm.com 14213610Sgiacomo.gabrielli@arm.com /// Equality operator, required to compare thread contexts. 14313610Sgiacomo.gabrielli@arm.com template<typename VE2, size_t NE2, bool P2, bool C2> 14413610Sgiacomo.gabrielli@arm.com bool 14513610Sgiacomo.gabrielli@arm.com operator==(const VecPredRegT<VE2, NE2, P2, C2>& that) const 14613610Sgiacomo.gabrielli@arm.com { 14713610Sgiacomo.gabrielli@arm.com return container == that.container; 14813610Sgiacomo.gabrielli@arm.com } 14913610Sgiacomo.gabrielli@arm.com 15013610Sgiacomo.gabrielli@arm.com /// Inequality operator, required to compare thread contexts. 15113610Sgiacomo.gabrielli@arm.com template<typename VE2, size_t NE2, bool P2, bool C2> 15213610Sgiacomo.gabrielli@arm.com bool 15313610Sgiacomo.gabrielli@arm.com operator!=(const VecPredRegT<VE2, NE2, P2, C2>& that) const 15413610Sgiacomo.gabrielli@arm.com { 15513610Sgiacomo.gabrielli@arm.com return !operator==(that); 15613610Sgiacomo.gabrielli@arm.com } 15713610Sgiacomo.gabrielli@arm.com 15813610Sgiacomo.gabrielli@arm.com friend std::ostream& 15913610Sgiacomo.gabrielli@arm.com operator<<(std::ostream& os, const MyClass& p) 16013610Sgiacomo.gabrielli@arm.com { 16113610Sgiacomo.gabrielli@arm.com // 0-sized is not allowed 16213610Sgiacomo.gabrielli@arm.com os << '[' << p.container[0]; 16313610Sgiacomo.gabrielli@arm.com for (int i = 0; i < p.NUM_BITS; ++i) { 16413610Sgiacomo.gabrielli@arm.com os << " " << (p.container[i] ? 1 : 0); 16513610Sgiacomo.gabrielli@arm.com } 16613610Sgiacomo.gabrielli@arm.com os << ']'; 16713610Sgiacomo.gabrielli@arm.com return os; 16813610Sgiacomo.gabrielli@arm.com } 16913610Sgiacomo.gabrielli@arm.com 17013610Sgiacomo.gabrielli@arm.com /// Returns a string representation of the register content. 17113610Sgiacomo.gabrielli@arm.com const std::string print() const { return csprintf("%s", *this); } 17213610Sgiacomo.gabrielli@arm.com 17313610Sgiacomo.gabrielli@arm.com /// Returns true if the first active element of the register is true. 17413610Sgiacomo.gabrielli@arm.com /// @param mask Input mask used to filter the predicates to be tested. 17513610Sgiacomo.gabrielli@arm.com /// @param actual_num_elems Actual number of vector elements considered for 17613610Sgiacomo.gabrielli@arm.com /// the test (corresponding to the current vector length). 17713610Sgiacomo.gabrielli@arm.com template <bool MC> 17813610Sgiacomo.gabrielli@arm.com bool 17913610Sgiacomo.gabrielli@arm.com firstActive(const VecPredRegT<VecElem, NumElems, Packed, MC>& mask, 18013610Sgiacomo.gabrielli@arm.com size_t actual_num_elems) const 18113610Sgiacomo.gabrielli@arm.com { 18213610Sgiacomo.gabrielli@arm.com assert(actual_num_elems <= NumElems); 18313610Sgiacomo.gabrielli@arm.com for (int i = 0; i < actual_num_elems; ++i) { 18413610Sgiacomo.gabrielli@arm.com if (mask[i]) { 18513610Sgiacomo.gabrielli@arm.com return (*this)[i]; 18613610Sgiacomo.gabrielli@arm.com } 18713610Sgiacomo.gabrielli@arm.com } 18813610Sgiacomo.gabrielli@arm.com return false; 18913610Sgiacomo.gabrielli@arm.com } 19013610Sgiacomo.gabrielli@arm.com 19113610Sgiacomo.gabrielli@arm.com /// Returns true if there are no active elements in the register. 19213610Sgiacomo.gabrielli@arm.com /// @param mask Input mask used to filter the predicates to be tested. 19313610Sgiacomo.gabrielli@arm.com /// @param actual_num_elems Actual number of vector elements considered for 19413610Sgiacomo.gabrielli@arm.com /// the test (corresponding to the current vector length). 19513610Sgiacomo.gabrielli@arm.com template <bool MC> 19613610Sgiacomo.gabrielli@arm.com bool 19713610Sgiacomo.gabrielli@arm.com noneActive(const VecPredRegT<VecElem, NumElems, Packed, MC>& mask, 19813610Sgiacomo.gabrielli@arm.com size_t actual_num_elems) const 19913610Sgiacomo.gabrielli@arm.com { 20013610Sgiacomo.gabrielli@arm.com assert(actual_num_elems <= NumElems); 20113610Sgiacomo.gabrielli@arm.com for (int i = 0; i < actual_num_elems; ++i) { 20213610Sgiacomo.gabrielli@arm.com if (mask[i] && operator[](i)) { 20313610Sgiacomo.gabrielli@arm.com return false; 20413610Sgiacomo.gabrielli@arm.com } 20513610Sgiacomo.gabrielli@arm.com } 20613610Sgiacomo.gabrielli@arm.com return true; 20713610Sgiacomo.gabrielli@arm.com } 20813610Sgiacomo.gabrielli@arm.com 20913610Sgiacomo.gabrielli@arm.com /// Returns true if the last active element of the register is true. 21013610Sgiacomo.gabrielli@arm.com /// @param mask Input mask used to filter the predicates to be tested. 21113610Sgiacomo.gabrielli@arm.com /// @param actual_num_elems Actual number of vector elements considered for 21213610Sgiacomo.gabrielli@arm.com /// the test (corresponding to the current vector length). 21313610Sgiacomo.gabrielli@arm.com template <bool MC> 21413610Sgiacomo.gabrielli@arm.com bool 21513610Sgiacomo.gabrielli@arm.com lastActive(const VecPredRegT<VecElem, NumElems, Packed, MC>& mask, 21613610Sgiacomo.gabrielli@arm.com size_t actual_num_elems) const 21713610Sgiacomo.gabrielli@arm.com { 21813610Sgiacomo.gabrielli@arm.com assert(actual_num_elems <= NumElems); 21913610Sgiacomo.gabrielli@arm.com for (int i = actual_num_elems - 1; i >= 0; --i) { 22013610Sgiacomo.gabrielli@arm.com if (mask[i]) { 22113610Sgiacomo.gabrielli@arm.com return operator[](i); 22213610Sgiacomo.gabrielli@arm.com } 22313610Sgiacomo.gabrielli@arm.com } 22413610Sgiacomo.gabrielli@arm.com return false; 22513610Sgiacomo.gabrielli@arm.com } 22613610Sgiacomo.gabrielli@arm.com}; 22713610Sgiacomo.gabrielli@arm.com 22813610Sgiacomo.gabrielli@arm.com/// Generic predicate register container. 22913610Sgiacomo.gabrielli@arm.com/// 23013610Sgiacomo.gabrielli@arm.com/// This generic class implements the Model in an MVC pattern, similarly to 23113610Sgiacomo.gabrielli@arm.com/// @see VecRegContainer. 23213610Sgiacomo.gabrielli@arm.com/// @tparam NumBits Size of the container in bits. 23313610Sgiacomo.gabrielli@arm.com/// @tparam Packed See @VecRegT. 23413610Sgiacomo.gabrielli@arm.comtemplate <size_t NumBits, bool Packed> 23513610Sgiacomo.gabrielli@arm.comclass VecPredRegContainer 23613610Sgiacomo.gabrielli@arm.com{ 23713610Sgiacomo.gabrielli@arm.com static_assert(NumBits > 0, 23813610Sgiacomo.gabrielli@arm.com "Size of a predicate register must be > 0"); 23913610Sgiacomo.gabrielli@arm.com 24013610Sgiacomo.gabrielli@arm.com public: 24113610Sgiacomo.gabrielli@arm.com static constexpr size_t NUM_BITS = NumBits; 24213610Sgiacomo.gabrielli@arm.com using Container = std::array<bool, NumBits>; 24313610Sgiacomo.gabrielli@arm.com 24413610Sgiacomo.gabrielli@arm.com private: 24513610Sgiacomo.gabrielli@arm.com Container container; 24613610Sgiacomo.gabrielli@arm.com // Alias for this type 24713610Sgiacomo.gabrielli@arm.com using MyClass = VecPredRegContainer<NumBits, Packed>; 24813610Sgiacomo.gabrielli@arm.com 24913610Sgiacomo.gabrielli@arm.com public: 25013610Sgiacomo.gabrielli@arm.com VecPredRegContainer() {} 25113610Sgiacomo.gabrielli@arm.com 25213610Sgiacomo.gabrielli@arm.com MyClass& 25313610Sgiacomo.gabrielli@arm.com operator=(const MyClass& that) 25413610Sgiacomo.gabrielli@arm.com { 25513610Sgiacomo.gabrielli@arm.com if (&that == this) 25613610Sgiacomo.gabrielli@arm.com return *this; 25713610Sgiacomo.gabrielli@arm.com container = that.container; 25813610Sgiacomo.gabrielli@arm.com return *this; 25913610Sgiacomo.gabrielli@arm.com } 26013610Sgiacomo.gabrielli@arm.com 26113610Sgiacomo.gabrielli@arm.com /// Required for de-serialization. 26213610Sgiacomo.gabrielli@arm.com MyClass& 26313610Sgiacomo.gabrielli@arm.com operator=(const std::vector<uint8_t>& that) 26413610Sgiacomo.gabrielli@arm.com { 26513610Sgiacomo.gabrielli@arm.com assert(that.size() == NUM_BITS); 26613610Sgiacomo.gabrielli@arm.com std::copy(that.begin(), that.end(), container.begin()); 26713610Sgiacomo.gabrielli@arm.com return *this; 26813610Sgiacomo.gabrielli@arm.com } 26913610Sgiacomo.gabrielli@arm.com 27013610Sgiacomo.gabrielli@arm.com /// Resets the predicate register to an all-false register. 27113610Sgiacomo.gabrielli@arm.com void 27213610Sgiacomo.gabrielli@arm.com reset() 27313610Sgiacomo.gabrielli@arm.com { 27413610Sgiacomo.gabrielli@arm.com container.fill(false); 27513610Sgiacomo.gabrielli@arm.com } 27613610Sgiacomo.gabrielli@arm.com 27713610Sgiacomo.gabrielli@arm.com /// Sets the predicate register to an all-true value. 27813610Sgiacomo.gabrielli@arm.com void 27913610Sgiacomo.gabrielli@arm.com set() 28013610Sgiacomo.gabrielli@arm.com { 28113610Sgiacomo.gabrielli@arm.com container.fill(true); 28213610Sgiacomo.gabrielli@arm.com } 28313610Sgiacomo.gabrielli@arm.com 28413610Sgiacomo.gabrielli@arm.com /// Equality operator, required to compare thread contexts. 28513610Sgiacomo.gabrielli@arm.com template<size_t N2, bool P2> 28613610Sgiacomo.gabrielli@arm.com inline bool 28713610Sgiacomo.gabrielli@arm.com operator==(const VecPredRegContainer<N2, P2>& that) const 28813610Sgiacomo.gabrielli@arm.com { 28913610Sgiacomo.gabrielli@arm.com return NumBits == N2 && Packed == P2 && container == that.container; 29013610Sgiacomo.gabrielli@arm.com } 29113610Sgiacomo.gabrielli@arm.com 29213610Sgiacomo.gabrielli@arm.com /// Inequality operator, required to compare thread contexts. 29313610Sgiacomo.gabrielli@arm.com template<size_t N2, bool P2> 29413610Sgiacomo.gabrielli@arm.com bool 29513610Sgiacomo.gabrielli@arm.com operator!=(const VecPredRegContainer<N2, P2>& that) const 29613610Sgiacomo.gabrielli@arm.com { 29713610Sgiacomo.gabrielli@arm.com return !operator==(that); 29813610Sgiacomo.gabrielli@arm.com } 29913610Sgiacomo.gabrielli@arm.com 30013610Sgiacomo.gabrielli@arm.com /// Returns a reference to a specific element of the internal container. 30113610Sgiacomo.gabrielli@arm.com bool& operator[](size_t idx) { return container[idx]; } 30213610Sgiacomo.gabrielli@arm.com 30313610Sgiacomo.gabrielli@arm.com /// Returns a const reference to a specific element of the internal 30413610Sgiacomo.gabrielli@arm.com /// container. 30513610Sgiacomo.gabrielli@arm.com const bool& operator[](size_t idx) const { return container[idx]; } 30613610Sgiacomo.gabrielli@arm.com 30713610Sgiacomo.gabrielli@arm.com /// Returns a subset of bits starting from a specific element in the 30813610Sgiacomo.gabrielli@arm.com /// container. 30913610Sgiacomo.gabrielli@arm.com uint8_t 31013610Sgiacomo.gabrielli@arm.com get_bits(size_t idx, uint8_t nbits) const 31113610Sgiacomo.gabrielli@arm.com { 31213610Sgiacomo.gabrielli@arm.com assert(nbits > 0 && nbits <= 8 && (idx + nbits - 1) < NumBits); 31313610Sgiacomo.gabrielli@arm.com uint8_t v = 0; 31413610Sgiacomo.gabrielli@arm.com idx = idx + nbits - 1; 31513610Sgiacomo.gabrielli@arm.com for (int i = 0; i < nbits; ++i, --idx) { 31613610Sgiacomo.gabrielli@arm.com v <<= 1; 31713610Sgiacomo.gabrielli@arm.com v |= container[idx]; 31813610Sgiacomo.gabrielli@arm.com } 31913610Sgiacomo.gabrielli@arm.com return v; 32013610Sgiacomo.gabrielli@arm.com } 32113610Sgiacomo.gabrielli@arm.com 32213610Sgiacomo.gabrielli@arm.com /// Set a subset of bits starting from a specific element in the 32313610Sgiacomo.gabrielli@arm.com /// container. 32413610Sgiacomo.gabrielli@arm.com void 32513610Sgiacomo.gabrielli@arm.com set_bits(size_t idx, uint8_t nbits, uint8_t bval) 32613610Sgiacomo.gabrielli@arm.com { 32713610Sgiacomo.gabrielli@arm.com assert(nbits > 0 && nbits <= 8 && (idx + nbits - 1) < NumBits); 32813610Sgiacomo.gabrielli@arm.com for (int i = 0; i < nbits; ++i, ++idx) { 32913610Sgiacomo.gabrielli@arm.com container[idx] = bval & 1; 33013610Sgiacomo.gabrielli@arm.com bval >>= 1; 33113610Sgiacomo.gabrielli@arm.com } 33213610Sgiacomo.gabrielli@arm.com } 33313610Sgiacomo.gabrielli@arm.com 33413610Sgiacomo.gabrielli@arm.com /// Returns a string representation of the register content. 33513610Sgiacomo.gabrielli@arm.com const std::string print() const { return csprintf("%s", *this); } 33613610Sgiacomo.gabrielli@arm.com 33713610Sgiacomo.gabrielli@arm.com friend std::ostream& 33813610Sgiacomo.gabrielli@arm.com operator<<(std::ostream& os, const MyClass& v) 33913610Sgiacomo.gabrielli@arm.com { 34013610Sgiacomo.gabrielli@arm.com for (auto b: v.container) { 34113610Sgiacomo.gabrielli@arm.com os << csprintf("%d", b); 34213610Sgiacomo.gabrielli@arm.com } 34313610Sgiacomo.gabrielli@arm.com return os; 34413610Sgiacomo.gabrielli@arm.com } 34513610Sgiacomo.gabrielli@arm.com 34613610Sgiacomo.gabrielli@arm.com /// Create a view of this container. 34713610Sgiacomo.gabrielli@arm.com /// 34813610Sgiacomo.gabrielli@arm.com /// If NumElems is provided, the size of the container is bounds-checked, 34913610Sgiacomo.gabrielli@arm.com /// otherwise the size is inferred from the container size. 35013610Sgiacomo.gabrielli@arm.com /// @tparam VecElem Type of the vector elements. 35113610Sgiacomo.gabrielli@arm.com /// @tparam NumElems Number of vector elements making up the view. 35213610Sgiacomo.gabrielli@arm.com /// @{ 35313610Sgiacomo.gabrielli@arm.com template <typename VecElem, 35413610Sgiacomo.gabrielli@arm.com size_t NumElems = (Packed ? NumBits : NumBits / sizeof(VecElem))> 35513610Sgiacomo.gabrielli@arm.com VecPredRegT<VecElem, NumElems, Packed, true> as() const 35613610Sgiacomo.gabrielli@arm.com { 35713610Sgiacomo.gabrielli@arm.com static_assert((Packed && NumElems <= NumBits) || 35813610Sgiacomo.gabrielli@arm.com (!Packed && 35913610Sgiacomo.gabrielli@arm.com NumBits % sizeof(VecElem) == 0 && 36013610Sgiacomo.gabrielli@arm.com sizeof(VecElem) * NumElems <= NumBits), 36113610Sgiacomo.gabrielli@arm.com "Container size incompatible with view size"); 36213610Sgiacomo.gabrielli@arm.com return VecPredRegT<VecElem, NumElems, Packed, true>(*this); 36313610Sgiacomo.gabrielli@arm.com } 36413610Sgiacomo.gabrielli@arm.com 36513610Sgiacomo.gabrielli@arm.com template <typename VecElem, 36613610Sgiacomo.gabrielli@arm.com size_t NumElems = (Packed ? NumBits : NumBits / sizeof(VecElem))> 36713610Sgiacomo.gabrielli@arm.com VecPredRegT<VecElem, NumElems, Packed, false> as() 36813610Sgiacomo.gabrielli@arm.com { 36913610Sgiacomo.gabrielli@arm.com static_assert((Packed && NumElems <= NumBits) || 37013610Sgiacomo.gabrielli@arm.com (!Packed && 37113610Sgiacomo.gabrielli@arm.com NumBits % sizeof(VecElem) == 0 && 37213610Sgiacomo.gabrielli@arm.com sizeof(VecElem) * NumElems <= NumBits), 37313610Sgiacomo.gabrielli@arm.com "Container size incompatible with view size"); 37413610Sgiacomo.gabrielli@arm.com return VecPredRegT<VecElem, NumElems, Packed, false>(*this); 37513610Sgiacomo.gabrielli@arm.com } 37613610Sgiacomo.gabrielli@arm.com /// @} 37713610Sgiacomo.gabrielli@arm.com}; 37813610Sgiacomo.gabrielli@arm.com 37913610Sgiacomo.gabrielli@arm.com/// Helper functions used for serialization/de-serialization 38013610Sgiacomo.gabrielli@arm.comtemplate <size_t NumBits, bool Packed> 38113610Sgiacomo.gabrielli@arm.cominline bool 38213610Sgiacomo.gabrielli@arm.comto_number(const std::string& value, VecPredRegContainer<NumBits, Packed>& p) 38313610Sgiacomo.gabrielli@arm.com{ 38413610Sgiacomo.gabrielli@arm.com int i = 0; 38513610Sgiacomo.gabrielli@arm.com for (const auto& c: value) { 38613610Sgiacomo.gabrielli@arm.com p[i] = (c == '1'); 38713610Sgiacomo.gabrielli@arm.com } 38813610Sgiacomo.gabrielli@arm.com return true; 38913610Sgiacomo.gabrielli@arm.com} 39013610Sgiacomo.gabrielli@arm.com 39113610Sgiacomo.gabrielli@arm.com/// Dummy type aliases and constants for architectures that do not implement 39213610Sgiacomo.gabrielli@arm.com/// vector predicate registers. 39313610Sgiacomo.gabrielli@arm.com/// @{ 39413610Sgiacomo.gabrielli@arm.comconstexpr bool DummyVecPredRegHasPackedRepr = false; 39513610Sgiacomo.gabrielli@arm.comusing DummyVecPredReg = VecPredRegT<DummyVecElem, DummyNumVecElemPerVecReg, 39613610Sgiacomo.gabrielli@arm.com DummyVecPredRegHasPackedRepr, false>; 39713610Sgiacomo.gabrielli@arm.comusing DummyConstVecPredReg = VecPredRegT<DummyVecElem, 39813610Sgiacomo.gabrielli@arm.com DummyNumVecElemPerVecReg, 39913610Sgiacomo.gabrielli@arm.com DummyVecPredRegHasPackedRepr, true>; 40013610Sgiacomo.gabrielli@arm.comusing DummyVecPredRegContainer = DummyVecPredReg::Container; 40113610Sgiacomo.gabrielli@arm.comconstexpr size_t DummyVecPredRegSizeBits = 8; 40213610Sgiacomo.gabrielli@arm.com/// @} 40313610Sgiacomo.gabrielli@arm.com 40413610Sgiacomo.gabrielli@arm.com#endif // __ARCH_GENERIC_VEC_PRED_REG_HH__ 405