From 91dccfe6bd5cf757df9178209214f7bab995f107 Mon Sep 17 00:00:00 2001 From: Brian Silver Date: Thu, 30 Apr 2015 07:19:01 -0500 Subject: Extend fapi2::buffer parametric interfaces Add fapi2::buffer::clearBit(bit_to_clear) Add extract/insert() Change-Id: I8dc00b6da68b22cd7b346cc1da56d33b94aec5b7 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/17542 Tested-by: Jenkins Server Reviewed-by: Matt K. Light Reviewed-by: Thi N. Tran Reviewed-by: Brian Silver Tested-by: Brian Silver --- import/hwpf/fapi2/include/buffer.H | 225 +++++++++++++++++++++++++++++++------ 1 file changed, 191 insertions(+), 34 deletions(-) diff --git a/import/hwpf/fapi2/include/buffer.H b/import/hwpf/fapi2/include/buffer.H index 9249d0ef..2fc2438e 100644 --- a/import/hwpf/fapi2/include/buffer.H +++ b/import/hwpf/fapi2/include/buffer.H @@ -169,6 +169,24 @@ namespace fapi2 return *this; } + /// + /// @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) + { + if (i_bit >= TT::bits_per_unit()) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + iv_data |= + (static_cast(1)) << (TT::bits_per_unit() - i_bit - 1); + return FAPI2_RC_SUCCESS; + } + /// /// @brief Clear a bit in buffer /// @tparam B Bit in buffer to clear. @@ -187,6 +205,31 @@ namespace fapi2 return *this; } + /// + /// @brief Clear a bit in the buffer + /// @param[in] i_bit the bit number to clear. + /// @note 0 is left-most + /// @return FAPI2_RC_SUCCESS if OK + /// + inline fapi2::ReturnCode clearBit(const bits_type& i_bit) + { + if (i_bit >= TT::bits_per_unit()) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + fapi2::buffer l_scratch; + + if (l_scratch.setBit(i_bit) != FAPI2_RC_SUCCESS) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + iv_data &= l_scratch.invert(); + + return FAPI2_RC_SUCCESS; + } + /// /// @brief Write a bit in buffer to a given value /// @tparam B Bit in buffer to write @@ -224,26 +267,6 @@ namespace fapi2 return *this; } - /// - /// @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) - { - if (i_bit >= TT::bits_per_unit()) - { - return FAPI2_RC_INVALID_PARAMETER; - } - - // Force iv_data to be dependent on the template type to force - // its look up in the second phase - iv_data |= - (static_cast(1)) << (TT::bits_per_unit() - i_bit - 1); - return FAPI2_RC_SUCCESS; - } - /// /// @brief Get the value of a bit in the buffer /// @tparam B Bit in buffer to get. @@ -392,9 +415,6 @@ namespace fapi2 /// @param[in] i_datain OT value to copy into DataBuffer /// - data is taken left aligned /// @return buffer& Useful for method chaining - /// @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 inline buffer& insert(const OT i_datain) @@ -439,6 +459,76 @@ namespace fapi2 return *this; } + /// + /// @brief Copy part of a OT into the DataBuffer + /// @tparam OT the type of the incoming (origin) data + /// @param[in] i_datain OT value to copy into DataBuffer + /// - data is taken left aligned + /// @param[in] Start bit to insert into (target start) + /// @param[in] Length of bits to insert + /// @param[in] Start bit in source - defaults to bit 0 + + /// @return FAPI2_RC_SUCCESS if successful + /// + template + fapi2::ReturnCode insert(const OT i_datain, const bits_type i_targetStart, + const bits_type i_len, const bits_type i_sourceStart = 0) + { + const bits_type target_length = parameterTraits::bit_length(); + const bits_type source_length = parameterTraits::bit_length(); + + // Error if input data don't make sense + if ((i_targetStart + i_len) > target_length) + { + FAPI_ERR("insert(): (Target Start + Len) is out of bounds"); + return FAPI2_RC_INVALID_PARAMETER; + } + + if ((i_sourceStart + i_len) > source_length) + { + FAPI_ERR("insert(): (Source Start + Len) is out of bounds"); + return FAPI2_RC_INVALID_PARAMETER; + } + + if (i_targetStart >= target_length) + { + FAPI_ERR("insert(): Target Start is out of bounds"); + return FAPI2_RC_INVALID_PARAMETER; + } + + if (i_sourceStart >= source_length) + { + FAPI_ERR("insert(): Source Start is out of bounds"); + return FAPI2_RC_INVALID_PARAMETER; + } + + // Normalize the input to 2 64 bit integers and adjust the starts accordingly + uint64_t source = static_cast(i_datain); + const uint64_t target = static_cast(iv_data); + + const bits_type source_start = parameterTraits::bit_length() - (source_length - i_sourceStart); + const bits_type target_start = parameterTraits::bit_length() - (target_length - i_targetStart); + + // Get mask value for Target buffer + // Note: Need "& 0UL" because bit shift left for Target buffer doesn't roll off + uint64_t mask = ((~0UL << (parameterTraits::bit_length() - i_len)) & ~0UL) >> target_start; + + // Align the source to the target. Make things signed so we know which way to shift. + int32_t shift = source_start - target_start; + if (shift > 0) + { + source <<= shift; + } + else + { + shift = target_start - source_start; + source >>= shift; + } + + iv_data = ((target & ~mask) | (source & mask)); + return FAPI2_RC_SUCCESS; + } + /// /// @brief Copy in a right aligned value /// @tparam SB Start bit to insert into @@ -448,16 +538,13 @@ namespace fapi2 /// - data is taken right aligned /// @return buffer& Useful for method chaining /// @note Data is assumed to be aligned on the word boundary of L - /// @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 inline buffer& insertFromRight(const OT i_datain) { // Error if input data don't make sense - static_assert(L < parameterTraits::bit_length(), - "insertFromRight(): Len >= input buffer"); + static_assert(L <= parameterTraits::bit_length(), + "insertFromRight(): Len > input buffer"); static_assert(TS < parameterTraits::bit_length(), "insertFromRight(): Target Start is out of bounds"); static_assert((TS + L) <= parameterTraits::bit_length(), @@ -467,6 +554,42 @@ namespace fapi2 return *this; } + /// + /// @brief Copy in a right aligned value + /// @tparam OT the type of the incoming (origin) data + /// @param[in] i_datain OT value to copy into DataBuffer + /// - data is taken right aligned + /// @param[in] Start bit to insert into + /// @param[in] Length of bits to insert + /// @return FAPi2_RC_SUCCESS if no error + /// @note Data is assumed to be aligned on the word boundary of L + /// + template + fapi2::ReturnCode insertFromRight(const OT i_datain, const bits_type i_targetStart, + const bits_type i_len) + { + // Error if input data don't make sense + if ((i_targetStart + i_len) > parameterTraits::bit_length()) + { + FAPI_ERR("insertFromRight(): (Target Start + Len) is out of bounds"); + return FAPI2_RC_INVALID_PARAMETER; + } + + if (i_targetStart >= parameterTraits::bit_length()) + { + FAPI_ERR("insertFromRight(): Target Start is out of bounds"); + return FAPI2_RC_INVALID_PARAMETER; + } + + if (i_len > parameterTraits::bit_length()) + { + FAPI_ERR("insertFromRight(): Len > input buffer"); + return FAPI2_RC_INVALID_PARAMETER; + } + + return this->insert(i_datain, i_targetStart, i_len, parameterTraits::bit_length() - i_len); + } + /// /// @brief Copy data from this buffer into an OT /// @tparam TS Start bit to insert into (target start) @@ -475,9 +598,6 @@ namespace fapi2 /// @tparam OT the type of the outgoing (target) /// @param[out] o_out OT to copy into - data is placed left aligned /// @return buffer& Useful for method chaining - /// @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 inline buffer& extract(OT& o_out) @@ -490,6 +610,31 @@ namespace fapi2 return *this; } + /// + /// @brief Copy data from this buffer into an OT + /// @tparam OT the type of the outgoing (target) + /// @param[out] o_out OT to copy into - data is placed left aligned + /// @param[in] Start bit to insert into (target start) + /// @param[in] Length of bits to insert + /// @param[in] Start bit in source + /// @return FAPI2_RC_SUCCESS if ok + /// + template + fapi2::ReturnCode extract(OT& o_out, const bits_type i_targetStart, + const bits_type i_len, const bits_type i_sourceStart) + { + // Extraction is just an insert into o_out + + buffer out(o_out); + if (out.insert(iv_data, i_targetStart, i_len, i_sourceStart) != FAPI2_RC_SUCCESS) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + o_out = out; + return FAPI2_RC_SUCCESS; + } + /// /// @brief Copy data from this buffer into an OT and right justify /// @tparam SS Start bit to insert into (source start) @@ -497,9 +642,6 @@ namespace fapi2 /// @tparam OT the type of the outgoing (target) /// @param[out] o_out OT to copy into - data is placed right aligned /// @return buffer& Useful for method chaining - /// @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 inline buffer& extractToRight(OT& o_out) @@ -508,6 +650,21 @@ namespace fapi2 return *this; } + /// + /// @brief Copy data from this buffer into an OT and right justify + /// @tparam OT the type of the outgoing (target) + /// @param[out] o_out OT to copy into - data is placed right aligned + /// @param[in] Start bit to insert into (source start) + /// @param[in] Length of bits to insert + /// @return FAPI2_RC_SUCCESS if ok + /// + template + fapi2::ReturnCode extractToRight(OT& o_out, const bits_type i_sourceStart, + const bits_type i_len) + { + return extract(o_out, parameterTraits::bit_length() - i_len, i_len, i_sourceStart); + } + ///@} private: -- cgit v1.2.3