#ifndef CK_STATIC_BUFFER_HPP #define CK_STATIC_BUFFER_HPP #include "statically_indexed_array.hpp" namespace ck { // static buffer for scalar template // TODO remove this bool, no longer needed struct StaticBuffer : public StaticallyIndexedArray { using type = T; using base = StaticallyIndexedArray; __host__ __device__ constexpr StaticBuffer() : base{} {} __host__ __device__ static constexpr AddressSpaceEnum GetAddressSpace() { return AddressSpace; } __host__ __device__ static constexpr bool IsStaticBuffer() { return true; } __host__ __device__ static constexpr bool IsDynamicBuffer() { return false; } // read access template __host__ __device__ constexpr const T& operator[](Number i) const { return base::operator[](i); } // write access template __host__ __device__ constexpr T& operator()(Number i) { return base::operator()(i); } }; #ifndef CK_NOGPU // static buffer for vector template ::value, bool>::type = false> struct StaticBufferTupleOfVector : public StaticallyIndexedArray, NumOfVector> { using V = typename vector_type::type; using base = StaticallyIndexedArray, NumOfVector>; static constexpr auto s_per_v = Number{}; static constexpr auto num_of_v_ = Number{}; __host__ __device__ constexpr StaticBufferTupleOfVector() : base{} {} __host__ __device__ static constexpr AddressSpaceEnum GetAddressSpace() { return AddressSpace; } __host__ __device__ static constexpr bool IsStaticBuffer() { return true; } __host__ __device__ static constexpr bool IsDynamicBuffer() { return false; } // Get S // i is offset of S template __host__ __device__ constexpr const S& operator[](Number i) const { constexpr auto i_v = i / s_per_v; constexpr auto i_s = i % s_per_v; return base::operator[](i_v).template AsType()[i_s]; } // Set S // i is offset of S template __host__ __device__ constexpr S& operator()(Number i) { constexpr auto i_v = i / s_per_v; constexpr auto i_s = i % s_per_v; return base::operator()(i_v).template AsType()(i_s); } // Get X // i is offset of S, not X. i should be aligned to X template ::value, bool>::type = false> __host__ __device__ constexpr auto GetAsType(Number i) const { constexpr auto s_per_x = Number>::vector_size>{}; static_assert(s_per_v % s_per_x == 0, "wrong! V must one or multiple X"); static_assert(i % s_per_x == 0, "wrong!"); constexpr auto i_v = i / s_per_v; constexpr auto i_x = (i % s_per_v) / s_per_x; return base::operator[](i_v).template AsType()[i_x]; } // Set X // i is offset of S, not X. i should be aligned to X template ::value, bool>::type = false> __host__ __device__ constexpr void SetAsType(Number i, X x) { constexpr auto s_per_x = Number>::vector_size>{}; static_assert(s_per_v % s_per_x == 0, "wrong! V must contain one or multiple X"); static_assert(i % s_per_x == 0, "wrong!"); constexpr auto i_v = i / s_per_v; constexpr auto i_x = (i % s_per_v) / s_per_x; base::operator()(i_v).template AsType()(i_x) = x; } // Get read access to vector_type V // i is offset of S, not V. i should be aligned to V template __host__ __device__ constexpr const auto& GetVectorTypeReference(Number i) const { static_assert(i % s_per_v == 0, "wrong!"); constexpr auto i_v = i / s_per_v; return base::operator[](i_v); } // Get write access to vector_type V // i is offset of S, not V. i should be aligned to V template __host__ __device__ constexpr auto& GetVectorTypeReference(Number i) { static_assert(i % s_per_v == 0, "wrong!"); constexpr auto i_v = i / s_per_v; return base::operator()(i_v); } __host__ __device__ void Clear() { const index_t numScalars = NumOfVector * ScalarPerVector; static_for<0, Number{}, 1>{}([&](auto i) { SetAsType(i, S{0}); }); } }; #endif template __host__ __device__ constexpr auto make_static_buffer(Number) { return StaticBuffer{}; } template __host__ __device__ constexpr auto make_static_buffer(LongNumber) { return StaticBuffer{}; } } // namespace ck #endif