summaryrefslogtreecommitdiffstats
path: root/hwpf/fapi/include/variable_buffer.H
diff options
context:
space:
mode:
Diffstat (limited to 'hwpf/fapi/include/variable_buffer.H')
-rwxr-xr-xhwpf/fapi/include/variable_buffer.H663
1 files changed, 663 insertions, 0 deletions
diff --git a/hwpf/fapi/include/variable_buffer.H b/hwpf/fapi/include/variable_buffer.H
new file mode 100755
index 00000000..a1280830
--- /dev/null
+++ b/hwpf/fapi/include/variable_buffer.H
@@ -0,0 +1,663 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2012,2014 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file variable_buffer.H
+ * @brief definitions for fapi2 variable length buffers
+ */
+
+#ifndef __FAPI2_VARIABLE_BUFFER__
+#define __FAPI2_VARIABLE_BUFFER__
+
+#include <buffer_base.H>
+
+namespace fapi2
+{
+ /// @brief Get a 32 bit mask quickly
+ // This is one of the main reasons we static_assert in the ctor's
+ // to ensure the unit_type is 32 bits.
+ inline uint32_t fast_mask32(int32_t i_pos, int32_t i_len)
+ {
+ // generates an arbitrary 32-bit mask using two operations, not too shabby
+
+ static const uint32_t l_mask32[] = {
+ 0x00000000,
+ 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,
+ 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000,
+ 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000,
+ 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
+ 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000,
+ 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00,
+ 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0,
+ 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF,
+ };
+ return l_mask32[i_len] >> i_pos;
+ }
+
+ //
+ // General set a series of bits in the buffer.
+ //
+
+ ///
+ /// @cond
+ /// @brief Internal bit inserting method.
+ /// @tparam unit_type The type of a unit of the arrays
+ /// @tparam bits_type The type of the bit counting values
+ /// @param[in] i_source The incoming data
+ /// @param[in] i_source_length The length in bits of the incoming data
+ /// @param[in] i_target The outgoing data
+ /// @param[in] i_target_length The length in bits of the outgoing data
+ /// @param[in] i_source_start_bit The starting bit location in the
+ /// incoming data
+ /// @param[in] i_target_start_bit The starting bit position in this
+ /// @param[in] i_length The length, in bits, the user wants copied.
+ ///
+ template<typename unit_type, typename bits_type>
+ inline fapi2::ReturnCode _insert(const unit_type* i_source,
+ bits_type i_source_length,
+ unit_type* i_target,
+ bits_type i_target_length,
+ bits_type i_source_start_bit,
+ bits_type i_target_start_bit,
+ bits_type i_length)
+ {
+ const bits_type bits_per_unit = fapi2::parameterTraits<unit_type>::bit_length;
+
+ // tartgetStart is defaulted to the sizeof(target) - (sizeof(source) - i_source_start_bit)
+ // which makes this act like insert from right
+ if (i_target_start_bit == ~0)
+ {
+ i_target_start_bit = (i_target_length - (i_source_length - i_source_start_bit));
+ }
+
+ // len defaults to (sizeof(OT) * 8) - i_source_start_bit
+ if (i_length == ~0)
+ {
+ i_length = i_source_length - i_source_start_bit;
+ }
+
+ // Check for overflow
+ if ((i_length + i_target_start_bit > i_target_length) ||
+ (i_length + i_source_start_bit > i_source_length))
+ {
+ return fapi2::FAPI2_RC_OVERFLOW;
+ }
+
+ do
+ {
+ const bits_type src_idx = i_source_start_bit / bits_per_unit;
+ const bits_type trg_idx = i_target_start_bit / bits_per_unit;
+
+ // "slop" = unaligned bits
+ const bits_type src_slop = i_source_start_bit % bits_per_unit;
+ const bits_type trg_slop = i_target_start_bit % bits_per_unit;
+
+ // "cnt" = largest number of bits to be moved each pass
+ bits_type cnt = std::min(i_length, bits_per_unit);
+ cnt = std::min(cnt, bits_per_unit - src_slop);
+ cnt = std::min(cnt, bits_per_unit - trg_slop);
+
+ // generate the source mask only once
+ bits_type mask = fast_mask32(src_slop, cnt);
+
+ // read the source bits only once
+ bits_type src_bits = i_source[src_idx] & mask;
+
+ // "shift" = amount of shifting needed for target alignment
+ int32_t shift = trg_slop - src_slop;
+
+ // ideally (i << -1) would yield (i >> 1), but it
+ // doesn't, so we need an extra branch here
+
+ if (shift < 0)
+ {
+ src_bits <<= -shift;
+ mask <<= -shift;
+ }
+ else
+ {
+ src_bits >>= shift;
+ mask >>= shift;
+ }
+
+ // clear source '0' bits in the target
+ i_target[trg_idx] &= ~mask;
+ // set source '1' bits in the target
+ i_target[trg_idx] |= src_bits;
+
+ i_source_start_bit += cnt;
+ i_target_start_bit += cnt;
+
+ i_length -= cnt;
+ } while (0 < i_length);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+ /// @endcond
+
+ /// @brief Class representing a FAPI variable_buffer.
+ /// @remark Variable buffers are buffers which can be variable in length
+ /// (and "odd sized.") These best represent the FAPI 1.X ecmdDataBuffer,
+ /// however they are implemented using the same template techniques
+ /// as the new fapi::buffer.
+ /// @note Variable buffers are not (presently) declared as std::bitset
+ /// as bitsets' size is fixed at runtime. It is not clear if this is
+ /// acceptable for variable_buffers at this time.
+ /// @note Variable buffers are not (presently) declared as std::vector<bool>
+ /// as it would need to be implemented separate from std::vector, and
+ /// it's not clear it would give us any real advantage. Howevever, its is
+ /// more likely this will become a std::vector<bool> than a std::bitset.
+ class variable_buffer : public buffer_base<bits_container>
+ {
+
+ public:
+
+ ///
+ /// @brief Variable buffer constructor
+ /// @param[in] i_value number of *bits* (sizeof(uint_type) * 8)
+ /// needed.
+ variable_buffer(bits_type i_value = 0);
+
+ ///
+ /// @brief Variable buffer list constructor
+ /// @param[in] i_value an initializer list to initialize the container.
+ ///
+ variable_buffer(const std::initializer_list<unit_type>& i_value);
+
+ /// @name Bit/Word Manipulation Functions
+ ///@{
+
+ ///
+ /// @brief Return the length of the buffer in bits
+ /// @return Length in bits
+ ///
+ inline uint32_t getBitLength(void) const
+ { return iv_perceived_bit_length; }
+
+ ///
+ /// @brief Return the length of the buffer in OT units
+ /// @return Length in OT units rounded up
+ /// @tparam OT the type to get the length of. For example, if one
+ /// wanted the length in double words, OT would be uint64_t
+ /// (getLength<uint64_t>().) Similarly, to get the length in words,
+ /// getLength<uin32_t>().
+ ///
+ template< typename OT >
+ inline uint32_t getLength(void) const
+ {
+ static const uint32_t bits_in_ot = sizeof(OT) * 8;
+ return (getBitLength() + (bits_in_ot - 1)) / bits_in_ot;
+ }
+
+ ///
+ /// @brief Set a bit in the buffer
+ /// @param[in] i_bit the bit number to set.
+ /// @note 0 is left-most
+ /// @return FAPI2_RC_SUCCESS if OK
+ ///
+ inline fapi2::ReturnCode setBit(const bits_type& i_bit)
+ {
+ const bits_type index = i_bit / bits_per_unit;
+
+ if (index > iv_data.size())
+ {
+ return FAPI2_RC_INVALID_PARAMETER;
+ }
+
+ iv_data[index] |=
+ unit_type(1) << (bits_per_unit - 1) -
+ (i_bit - (index * bits_per_unit));
+
+ return FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Clear a bit in buffer
+ /// @tparam SB Start bit in buffer to clear.
+ /// @tparam L Number of consecutive bits from start bit to
+ /// clear
+ /// @return FAPI2_RC_SUCCESS on success
+ /// @note Asserting that all the parameters are known at
+ /// compile time so this can be templated only. If that is not
+ /// the case we can add a function parameter version.
+ ///
+ template< bits_type SB, bits_type L >
+ fapi2::ReturnCode clearBit(void);
+
+ ///
+ /// @brief Invert bit
+ /// @tparam SB Start bit in buffer to invert.
+ /// @tparam L Number of consecutive bits from start bit to
+ /// invert, defaults to 1
+ /// @return FAPI2_RC_SUCCESS on success
+ /// @note Asserting that all the parameters are known at
+ /// compile time so this can be templated only. If that is not
+ /// the case we can add a function parameter version.
+ ///
+ template< bits_type SB, bits_type L = 1 >
+ fapi2::ReturnCode flipBit(void);
+
+ ///
+ /// @brief Get the value of a bit in the buffer
+ /// @tparam B Bit in buffer to get.
+ /// @return true/1 if bit is on, false/0 if bit is off
+ /// @note Asserting that all the parameters are known at
+ /// compile time so this can be templated only. If that is not
+ /// the case we can add a function parameter version.
+ ///
+ template< bits_type B >
+ inline bool getBit(void) const
+ {
+ const bits_type index = B / bits_per_unit;
+ const unit_type mask = unit_type(1) << (bits_per_unit - 1) - (B - (index * bits_per_unit));
+ return iv_data[index] & mask;
+ }
+
+ ///
+ /// @brief Test if multiple bits are set
+ /// @tparam SB Start bit in buffer to test.
+ /// @tparam L Number of consecutive bits from start bit to
+ /// test, defaults to 1
+ /// @note Asserting that all the parameters are known at
+ /// compile time so this can be templated only. If that is not
+ /// the case we can add a function parameter version.
+ /// @return true if all bits in range are set - false if any
+ /// bit is clear
+ ///
+ template< bits_type SB, bits_type L = 1 >
+ bool isBitSet(void) const;
+
+ ///
+ /// @brief Test if multiple bits are clear
+ /// @tparam SB Start bit in buffer to test.
+ /// @tparam L Number of consecutive bits from start bit to
+ /// test, defaults to 1
+ /// @note Asserting that all the parameters are known at
+ /// compile time so this can be templated only. If that is not
+ /// the case we can add a function parameter version.
+ /// @return true if bit is clear - false if bit is set
+ ///
+ template< bits_type SB, bits_type L = 1 >
+ bool isBitClear(void) const;
+
+ ///
+ /// @brief Count number of bits set in a range
+ /// @tparam SB Start bit in buffer to test.
+ /// @tparam L Number of consecutive bits from start bit to
+ /// test, defaults to 1
+ /// @note Asserting that all the parameters are known at
+ /// compile time so this can be templated only. If that is not
+ /// the case we can add a function parameter version.
+ /// @return Number of bits set in range
+ ///
+ template< bits_type SB, bits_type L = 1 >
+ bits_type getNumBitsSet(void) const;
+
+ ///@}
+
+ /// @name Buffer Manipulation Functions
+ ///@{
+
+ // Note: Many (all?) of these are not needed and the compiler complains
+ // as the cast to T yields a better operator. There are here mainly for
+ // documenation purposes.
+
+ ///
+ /// @brief operator>>()
+ ///
+#ifdef DOXYGEN
+ variable_buffer<T>& operator>>(bits_type i_shiftnum);
+#endif
+
+ ///
+ /// @brief operator<<()
+ ///
+#ifdef DOXYGEN
+ variable_buffer<T>& operator<<(bits_type i_shiftnum);
+#endif
+
+ ///
+ /// @brief operator+()
+ ///
+#ifdef DOXYGEN
+ variable_buffer<T>& operator+(const T& rhs);
+#endif
+
+ ///
+ /// @brief operator+=()
+ ///
+#ifdef DOXYGEN
+ variable_buffer<T>& operator+=(const T& rhs);
+#endif
+
+ ///
+ /// @brief operator|=()
+ ///
+#ifdef DOXYGEN
+ variable_buffer<T>& operator|=(const T& rhs);
+#endif
+
+ ///
+ /// @brief operator&=()
+ ///
+#ifdef DOXYGEN
+ variable_buffer<T>& operator&=(const T& rhs);
+#endif
+
+ ///
+ /// @brief operator|()
+ ///
+#ifdef DOXYGEN
+ variable_buffer<T>& operator|(const T& rhs);
+#endif
+
+ ///
+ /// @brief operator&()
+ ///
+#ifdef DOXYGEN
+ variable_buffer<T>& operator&(const T& rhs);
+#endif
+
+ ///
+ /// @brief operator^=()
+ ///
+#ifdef DOXYGEN
+ variable_buffer<T>& operator^=(const T& rhs);
+#endif
+
+ ///
+ /// @brief operator!=()
+ ///
+#ifdef DOXYGEN
+ bool operator!=(const T& rhs) const;
+#endif
+
+ ///
+ /// @brief operator==()
+ /// @return true if and only if lhs == rhs
+ ///
+ inline bool operator==(const fapi2::bits_container& rhs) const
+ {
+ if (&iv_data == &rhs)
+ {
+ return true;
+ }
+
+ return iv_data == rhs;
+ }
+
+ ///
+ /// @brief Copy part of an element into the DataBuffer
+ /// @param[in] i_data OT value to copy into DataBuffer
+ /// @param[in] i_targetStart The position in this where the copy starts
+ /// @param[in] i_len How many bits to copy
+ /// @param[in] i_sourceStart The start positon in i_data, defaults to 0
+ /// @return FAPI2_RC_SUCCESS on success, FAPi2_RC_OVERFLOW otherwise
+ ///
+ template<typename OT>
+ fapi2::ReturnCode insert(const OT& i_data,
+ bits_type i_targetStart = 0,
+ bits_type i_len = ~0,
+ bits_type i_sourceStart = 0);
+
+ ///
+ /// @brief Copy in a right aligned (decimal) element
+ /// @param[in] i_data the incoming data
+ /// - data is taken right aligned
+ /// @param[in] i_targetStart The starting bit position in this
+ /// - Defaultst to 0
+ /// @param[in] i_len The length, in bits, the user wants copied.
+ /// - Defaults to all of the bits in the source which fit
+ /// @return FAPI2_RC_SUCCESS on success, FAPI2_RC_OVERFLOW otherwise
+ ///
+ template<typename OT>
+ fapi2::ReturnCode insertFromRight(const OT& i_data,
+ bits_type i_targetStart = 0,
+ bits_type i_len = ~0);
+
+ ///
+ /// @brief Copy data from this buffer into an OT
+ /// @tparam OT the type of the outgoing data
+ /// @param[out] o_out OT to copy into - data is placed left aligned
+ /// @param[in] i_start Start bit to copy from - defaults to 0
+ /// @param[in] i_len Length of bits to copy - defaults to filling o_out
+ /// @return FAPI2_RC_SUCCESS on success
+ ///
+ template< typename OT >
+ fapi2::ReturnCode extract(OT& o_out,
+ bits_type i_start = 0,
+ bits_type i_len = ~0) const;
+
+ ///
+ /// @brief Copy data from this buffer into an OT and right justify
+ /// @tparam OT the type of the outgoing data
+ /// @param[out] o_out OT to copy into - data is placed right aligned
+ /// @param[in] i_start Start bit to copy from - defaults to 0
+ /// @param[in] i_len Length of bits to copy - defaults to filling o_out
+ /// @return FAPI2_RC_SUCCESS on success
+ ///
+ template< typename OT >
+ fapi2::ReturnCode extractToRight(OT& o_out,
+ bits_type i_start = 0,
+ bits_type i_len = ~0) const;
+ ///@}
+
+ private:
+ // Just shorthand ...
+ static const bits_type bits_per_unit =
+ bufferTraits<bits_container>::bits_per_unit;
+
+ // The number of bits the user asked for. The actual size of the
+ // container might be larger.
+ bits_type iv_perceived_bit_length;
+
+ ///
+ /// @brief Internal bit extraction method.
+ /// @tparam OT The type of the destination
+ /// @param[in] i_start The starting bit position in this
+ /// @param[in] i_count The length, in bits, the user wants copied.
+ /// @param[out] o_dest Where to put the data
+ ///
+ template< typename OT >
+ fapi2::ReturnCode _extract(bits_type i_start,
+ bits_type i_count,
+ OT* o_dest) const;
+
+ ///
+ /// @brief Internal insertFromRight
+ /// @param[in] i_data, the incoming data
+ /// @param[in] i_data_length The length in bits of the incoming data
+ /// @param[in] i_target_start_bit The starting bit position in this
+ /// @param[in] i_length The length, in bits, the user wants copied.
+ ///
+ template<typename OT>
+ fapi2::ReturnCode _insertFromRight(const OT& i_data,
+ bits_type i_data_length,
+ bits_type i_targetStart,
+ bits_type i_len);
+
+ };
+
+ inline variable_buffer::
+ variable_buffer(bits_type i_value):
+ buffer_base(i_value),
+ iv_perceived_bit_length(i_value)
+ {
+ static_assert(std::is_same<unit_type, uint32_t>::value,
+ "code currently needs unit_type to be a unit32_t");
+ }
+
+ inline variable_buffer::
+ variable_buffer(const std::initializer_list<unit_type>& i_value):
+ buffer_base(i_value),
+ iv_perceived_bit_length(i_value.size() * sizeof(unit_type) * 8)
+ {
+ static_assert(std::is_same<unit_type, uint32_t>::value,
+ "code currently needs unit_type to be a unit32_t");
+ }
+
+
+
+ /// @cond
+ //
+ // Generic insert
+ //
+ template<typename OT>
+ inline fapi2::ReturnCode variable_buffer::insert(const OT& i_source,
+ bits_type i_targetStart,
+ bits_type i_len,
+ bits_type i_sourceStart)
+ {
+ return _insert((unit_type*)(&i_source), parameterTraits<OT>::bit_length,
+ &(iv_data[0]), getBitLength(),
+ i_sourceStart, i_targetStart, i_len);
+ }
+
+ //
+ // Insert another variable_bufer
+ //
+ template<>
+ inline fapi2::ReturnCode variable_buffer::insert(
+ const variable_buffer& i_data,
+ bits_type i_targetStart,
+ bits_type i_len,
+ bits_type i_sourceStart)
+ {
+ return _insert((unit_type*)&(i_data()[0]), i_data.getBitLength(),
+ &(iv_data[0]), getBitLength(),
+ i_sourceStart, i_targetStart, i_len);
+ }
+
+ //
+ // Generic insert from right
+ //
+ template<typename OT>
+ inline fapi2::ReturnCode variable_buffer::insertFromRight(
+ const OT& i_data,
+ bits_type i_targetStart,
+ bits_type i_len)
+ {
+ _insertFromRight(i_data, parameterTraits<OT>::bit_length, i_targetStart, i_len);
+ }
+
+ //
+ // variable_buffer insert from right
+ //
+ template<>
+ inline fapi2::ReturnCode variable_buffer::insertFromRight(
+ const variable_buffer& i_data,
+ bits_type i_targetStart,
+ bits_type i_len)
+ {
+ const bits_type bit_length_of_source = i_data.getBitLength();
+ _insertFromRight(i_data, bit_length_of_source, i_targetStart, i_len);
+ }
+
+
+
+
+ //
+ // Generic extract. Extract is an insert with the arguments reversed.
+ //
+ template<typename OT>
+ inline fapi2::ReturnCode variable_buffer::extract(
+ OT& i_data,
+ bits_type i_start,
+ bits_type i_len) const
+ {
+ // Needed to trick the compiler into matching the template below
+ const bits_type max_length = parameterTraits<OT>::bit_length;
+
+ // If thy didn't pass an i_len, assume they want all the data
+ // which will fit.
+ if (i_len == ~0)
+ {
+ i_len = max_length;
+ }
+
+ return _insert((container_unit*)&iv_data[0], getBitLength(),
+ &i_data, max_length,
+ i_start, 0U, i_len);
+ }
+
+ //
+ // Extract in to another variable_bufer
+ //
+ template<>
+ inline fapi2::ReturnCode variable_buffer::extract(
+ variable_buffer& i_data,
+ bits_type i_start,
+ bits_type i_len) const
+ {
+ // If thy didn't pass an i_len, assume they want all the data
+ // which will fit.
+ if (i_len == ~0)
+ {
+ i_len = i_data.getBitLength();
+ }
+ return _insert((container_unit*)&iv_data[0], getBitLength(),
+ &(i_data()[0]), i_data.getBitLength(),
+ i_start, 0U, i_len);
+ }
+
+
+
+ template<typename OT>
+ inline fapi2::ReturnCode variable_buffer::_insertFromRight(
+ const OT& i_data,
+ bits_type i_data_length,
+ bits_type i_targetStart,
+ bits_type i_len)
+ {
+ // If they didn't pass in a length, assume they want all the i_data
+ // which will fit.
+ if( i_len == ~0 )
+ {
+ // The longest the length can be is the length of the data
+ // This is the miniumum of the length of the data or the
+ // number of available bits
+ i_len = std::min(i_data_length, getBitLength() - i_targetStart);
+ }
+
+ // Source start is the length, counted from the right
+ return insert(i_data, i_targetStart, i_len, i_data_length - i_len);
+ }
+
+ //
+ // Invalid specializations of set
+ //
+ /// @cond
+ // Sepcialize the variable_buffer version to to "undefined" so the
+ // linker complains loudly if anyone calls it.
+#if 0
+ template<>
+ inline fapi2::ReturnCode buffer_base::set(
+ const variable_buffer& i_value,
+ bits_type i_offset);
+#endif
+ /// @endcond
+};
+
+
+#endif
OpenPOWER on IntegriCloud