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