diff options
author | Brian Silver <bsilver@us.ibm.com> | 2015-03-13 10:50:16 -0500 |
---|---|---|
committer | Derk Rembold <rembold@de.ibm.com> | 2015-09-03 07:21:42 -0500 |
commit | 91cc641a78c379d9b6b0d5c270866429d36e6c16 (patch) | |
tree | c80adfa2988186857924da0585b2106725db7b1b | |
parent | 54281ef813168b16b41a084e4f70dbab462da2ce (diff) | |
download | talos-sbe-91cc641a78c379d9b6b0d5c270866429d36e6c16.tar.gz talos-sbe-91cc641a78c379d9b6b0d5c270866429d36e6c16.zip |
Buffer, targeting updates
Update target types for ex, l2/l3
Add variable_buffer resize
Update, fix, variable_buffer insert/extract
variable_buffer array constructor
-Wall clean up
Refactor buffer::insert, bit_lengths
Change-Id: I2bbec294f275a80c33917dc2df2f8b8220f6d8d6
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/16359
Reviewed-by: Matt K. Light <mklight@us.ibm.com>
Reviewed-by: MATTHEW A. PLOETZ <maploetz@us.ibm.com>
Reviewed-by: Brian Silver <bsilver@us.ibm.com>
Tested-by: Brian Silver <bsilver@us.ibm.com>
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/20126
Tested-by: Jenkins Server
Reviewed-by: Derk Rembold <rembold@de.ibm.com>
-rw-r--r-- | import/hwpf/fapi2/include/buffer.H | 82 | ||||
-rw-r--r-- | import/hwpf/fapi2/include/buffer_base.H | 48 | ||||
-rw-r--r-- | import/hwpf/fapi2/include/buffer_parameters.H | 19 | ||||
-rw-r--r-- | import/hwpf/fapi2/include/buffer_traits.H | 13 | ||||
-rw-r--r-- | import/hwpf/fapi2/include/error_info.H | 3 | ||||
-rw-r--r-- | import/hwpf/fapi2/include/ffdc.H | 2 | ||||
-rw-r--r-- | import/hwpf/fapi2/include/return_code.H | 2 | ||||
-rw-r--r-- | import/hwpf/fapi2/include/target.H | 2 | ||||
-rw-r--r-- | import/hwpf/fapi2/include/target_types.H | 9 | ||||
-rw-r--r-- | import/hwpf/fapi2/include/variable_buffer.H | 316 |
10 files changed, 373 insertions, 123 deletions
diff --git a/import/hwpf/fapi2/include/buffer.H b/import/hwpf/fapi2/include/buffer.H index 9f072039..e0b6ec8c 100644 --- a/import/hwpf/fapi2/include/buffer.H +++ b/import/hwpf/fapi2/include/buffer.H @@ -108,11 +108,11 @@ namespace fapi2 inline buffer& setBit(void) { static_assert((B >= 0) && - (B < bufferTraits<T>::bits_per_unit), "failed range check"); + (B < bufferTraits<T>::bits_per_unit()), "failed range check"); // Force iv_data to be dependent on the template type to force // its look up in the second phase - this->iv_data |= (static_cast<T>(1)) << (bufferTraits<T>::bits_per_unit - B - 1); + this->iv_data |= (static_cast<T>(1)) << (bufferTraits<T>::bits_per_unit() - B - 1); return *this; } @@ -128,7 +128,7 @@ namespace fapi2 inline buffer& clearBit(void) { static_assert((B >= 0) && - (B < bufferTraits<T>::bits_per_unit), "failed range check"); + (B < bufferTraits<T>::bits_per_unit()), "failed range check"); this->iv_data &= buffer<T>().setBit<B>().invert(); return *this; @@ -146,7 +146,7 @@ namespace fapi2 inline buffer& flipBit(void) { static_assert((B >= 0) && - (B < bufferTraits<T>::bits_per_unit), "failed range check"); + (B < bufferTraits<T>::bits_per_unit()), "failed range check"); this->iv_data ^= buffer<T>().setBit<B>(); return *this; @@ -160,7 +160,7 @@ namespace fapi2 /// inline fapi2::ReturnCode setBit(const bits_type& i_bit) { - if (i_bit >= bufferTraits<T>::bits_per_unit) + if (i_bit >= bufferTraits<T>::bits_per_unit()) { return FAPI2_RC_INVALID_PARAMETER; } @@ -168,7 +168,7 @@ namespace fapi2 // Force iv_data to be dependent on the template type to force // its look up in the second phase this->iv_data |= - (static_cast<T>(1)) << (bufferTraits<T>::bits_per_unit - i_bit - 1); + (static_cast<T>(1)) << (bufferTraits<T>::bits_per_unit() - i_bit - 1); return FAPI2_RC_SUCCESS; } @@ -280,7 +280,7 @@ namespace fapi2 /// @brief Copy part of a OT into the DataBuffer /// @tparam TS Start bit to insert into (target start) /// @tparam L Length of bits to insert - /// @tparam SS Start bit in source + /// @tparam SS Start bit in source - defaults to bit 0 /// @tparam OT the type of the incoming (origin) data /// @param[in] i_datain OT value to copy into DataBuffer /// - data is taken left aligned @@ -288,11 +288,11 @@ namespace fapi2 /// compile time so this can be templated only. If that is not /// the case we can add a function parameter version. /// - template<bits_type TS, bits_type L, bits_type SS, typename OT> + template<bits_type TS, bits_type L, bits_type SS = 0, typename OT> inline void insert(const OT i_datain) { - const bits_type target_length = parameterTraits<T>::bit_length; - const bits_type source_length = parameterTraits<OT>::bit_length; + const bits_type target_length = parameterTraits<T>::bit_length(); + const bits_type source_length = parameterTraits<OT>::bit_length(); // Error if input data don't make sense static_assert((TS + L) <= target_length, @@ -304,48 +304,30 @@ namespace fapi2 static_assert(SS < source_length, "insert(): Source Start is out of bounds"); - // Get mask value for Target buffer - // Note: Need "& ((T)-1) because bit shift left for Target buffer doesn't roll off - T mask =((T(~0) << (target_length - L)) & T(~0)) >> TS; + // Normalize the input to 2 64 bit integers and adjust the starts accordingly + uint64_t source = static_cast<uint64_t>(i_datain); + const uint64_t target = static_cast<uint64_t>(this->iv_data); - // Calculate the equivalent position of the input Source start for the size of the Target buffer. + const bits_type source_start = parameterTraits<uint64_t>::bit_length() - (source_length - SS); + const bits_type target_start = parameterTraits<uint64_t>::bit_length() - (target_length - TS); - // Assume OT is smaller (sizeof(T) > sizeof(OT)) - uint64_t sourceShift = abs(TS - ((target_length - source_length) + SS)); - uint64_t sourceAlign = T(i_datain) << sourceShift; + // 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<uint64_t>::bit_length() - L)) & ~0UL) >> target_start; - if (sizeof(T) == sizeof(OT)) + // 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) { - sourceShift = abs(SS - TS); - sourceAlign = (SS > TS) ? ((T)i_datain) << sourceShift : ((T)i_datain) >> sourceShift; + source <<= shift; } - - if (sizeof(T) < sizeof(OT)) + else { - sourceShift = source_length - target_length; - if (SS <= sourceShift) - { - sourceShift = sourceShift + TS - SS; - sourceAlign = ((OT)i_datain) >> sourceShift; - } - - // (SS > sourceShift) - else - { - if (sourceShift > TS) - { - sourceShift = SS - sourceShift - TS; - sourceAlign = OT(i_datain) << sourceShift; - } - else - { - sourceShift = SS - sourceShift; - sourceAlign = (sourceShift < TS) ? OT(i_datain) >> sourceShift : OT(i_datain); - } - } + shift = target_start - source_start; + source >>= shift; } - this->iv_data = (this->iv_data & ~mask) | (sourceAlign & mask); + this->iv_data = ((target & ~mask) | (source & mask)); return; } @@ -365,14 +347,14 @@ namespace fapi2 inline void insertFromRight(const OT i_datain) { // Error if input data don't make sense - static_assert(L < parameterTraits<OT>::bit_length, + static_assert(L < parameterTraits<OT>::bit_length(), "insertFromRight(): Len >= input buffer"); - static_assert(TS < parameterTraits<T>::bit_length, + static_assert(TS < parameterTraits<T>::bit_length(), "insertFromRight(): Target Start is out of bounds"); - static_assert((TS + L) <= parameterTraits<T>::bit_length, + static_assert((TS + L) <= parameterTraits<T>::bit_length(), "InsertFromRight(): (Target Start + Len) is out of bounds"); - this->insert<TS, L, parameterTraits<OT>::bit_length - L>(i_datain); + this->insert<TS, L, parameterTraits<OT>::bit_length() - L>(i_datain); return; } @@ -411,12 +393,12 @@ namespace fapi2 template<bits_type SS, bits_type L, typename OT> inline void extractToRight(OT& o_out) { - extract<parameterTraits<OT>::bit_length - L, L, SS>(o_out); + extract<parameterTraits<OT>::bit_length() - L, L, SS>(o_out); return; } ///@} }; -}; +} #endif diff --git a/import/hwpf/fapi2/include/buffer_base.H b/import/hwpf/fapi2/include/buffer_base.H index a6e8c4ad..849e9e79 100644 --- a/import/hwpf/fapi2/include/buffer_base.H +++ b/import/hwpf/fapi2/include/buffer_base.H @@ -289,6 +289,17 @@ namespace fapi2 protected: /// + /// @brief Get the actual bit length of the buffer + /// @return The bit length of the buffer. + /// @note This is needed by variable_buffer, which is why it's here + /// + uint32_t bit_length(void) + { return TT::bit_length(iv_data); } + + uint32_t bit_length(void) const + { return TT::bit_length(iv_data); } + + /// /// @brief Variable buffer constructor /// @param[in] i_value number of *bits* (sizeof(container_units) * 8) /// needed. Meaningless for integral types and thus protected. @@ -300,7 +311,7 @@ namespace fapi2 /// @param[in] i_value an initializer list to initialize the container. /// Meaningless for integral types and thus protected /// - buffer_base(std::initializer_list<unit_type> i_value); + buffer_base(const std::initializer_list<unit_type>& i_value); /// /// @brief Clear the buffer @@ -308,23 +319,46 @@ namespace fapi2 inline void clear(void) { TT::clear(iv_data); } + ///@cond + /// + /// @brief Return the size of the internal vector given a desired bit size + /// @param[in] The size in bits + /// @return The size in units. + /// + inline bits_type _vector_size(const bits_type& bits_size) + { + // If we fit in one unit, we allocate one unit. + if (bits_size < parameterTraits<unit_type>::bit_length()) + { + return 1; + } + + // Otherwise, the number of units is calculates - add one if + // we cross the unit boundary. + else + { + bits_type my_size = bits_type(bits_size / 8 / sizeof(unit_type)); + my_size += (bits_size % parameterTraits<unit_type>::bit_length() == 0) ? 0 : 1; + return my_size; + } + } + ///@endcond + /// The contents of the buffer T iv_data; }; template <typename T, typename TT> inline buffer_base<T, TT>::buffer_base(bits_type i_value): - iv_data( std::max(bits_type(1), - bits_type(i_value / 8 / sizeof(bits_type)))) - { - } + iv_data(_vector_size(i_value)) + {} template <typename T, typename TT> - inline buffer_base<T, TT>::buffer_base(std::initializer_list<unit_type> i_value): + inline buffer_base<T, TT>::buffer_base(const std::initializer_list<unit_type>& i_value): iv_data(i_value) { } -}; +} diff --git a/import/hwpf/fapi2/include/buffer_parameters.H b/import/hwpf/fapi2/include/buffer_parameters.H index 3dc41b26..1ad9ba43 100644 --- a/import/hwpf/fapi2/include/buffer_parameters.H +++ b/import/hwpf/fapi2/include/buffer_parameters.H @@ -41,12 +41,17 @@ namespace fapi2 class parameterTraits { public: - enum - { - mask = T(~0), - bit_length = sizeof(T) * 8, - byte_length = sizeof(T), - }; + // Why constexpr functions? Enums are hard to do math on, and + // static const doesn't work without -O1 (or greater.) That might + // be a bug in g++ but this works just the same. + constexpr static uint32_t mask(void) + { return T(~0); } + + constexpr static uint32_t byte_length(void) + { return sizeof(T); } + + constexpr static uint32_t bit_length(void) + { return sizeof(T) * 8; } template<typename U> inline static void write_element(void* i_data, T i_value, uint32_t i_offset) @@ -60,6 +65,6 @@ namespace fapi2 } }; /// @endcond -}; +} #endif diff --git a/import/hwpf/fapi2/include/buffer_traits.H b/import/hwpf/fapi2/include/buffer_traits.H index 5fa9f0b7..cf4df1be 100644 --- a/import/hwpf/fapi2/include/buffer_traits.H +++ b/import/hwpf/fapi2/include/buffer_traits.H @@ -43,7 +43,10 @@ namespace fapi2 { /// @cond /// Types representing a container of bits. Used to create - /// variable_buffer. + /// variable_buffer. container_unit must remain 32-bits + /// for now - there will be a lot of code to change if it + /// changes. There are assertions helping to enforce this + /// in places in the code. typedef uint32_t container_unit; typedef std::vector<container_unit> bits_container; @@ -137,7 +140,8 @@ namespace fapi2 typedef B bits_type; typedef T unit_type; - enum { bits_per_unit = sizeof(unit_type) * 8 }; + constexpr static uint32_t bits_per_unit(void) + { return sizeof(unit_type) * 8; } }; // @@ -222,10 +226,11 @@ namespace fapi2 typedef uint32_t bits_type; typedef container_unit unit_type; - enum { bits_per_unit = sizeof(unit_type) * 8 }; + constexpr static uint32_t bits_per_unit(void) + { return sizeof(unit_type) * 8; } }; /// @endcond -}; +} diff --git a/import/hwpf/fapi2/include/error_info.H b/import/hwpf/fapi2/include/error_info.H index b28ab011..30f82998 100644 --- a/import/hwpf/fapi2/include/error_info.H +++ b/import/hwpf/fapi2/include/error_info.H @@ -53,7 +53,7 @@ namespace fapi2 {} operator const void*() const { return iv_value.first; } - operator const uint8_t() const + operator uint8_t() const { return *(reinterpret_cast<const uint8_t*>(iv_value.first)); } int16_t size(void) const { return iv_value.second; } @@ -219,6 +219,7 @@ namespace fapi2 { static_assert(std::is_pointer<T>::value, "pointer passed to getErrorInfoFfdcSize"); + return 0; } /// diff --git a/import/hwpf/fapi2/include/ffdc.H b/import/hwpf/fapi2/include/ffdc.H index fd79d92e..a0cdd6f2 100644 --- a/import/hwpf/fapi2/include/ffdc.H +++ b/import/hwpf/fapi2/include/ffdc.H @@ -187,5 +187,5 @@ namespace fapi2 std::shared_ptr<ErrorInfo> iv_info; }; -}; +} #endif // FAPI2_FFDC_H_ diff --git a/import/hwpf/fapi2/include/return_code.H b/import/hwpf/fapi2/include/return_code.H index 0442ca89..348180cb 100644 --- a/import/hwpf/fapi2/include/return_code.H +++ b/import/hwpf/fapi2/include/return_code.H @@ -175,6 +175,6 @@ namespace fapi2 extern thread_local uint64_t pib_error_mask; /// the pib mask extern thread_local uint64_t operational_state; /// the operational mode -}; +} #endif diff --git a/import/hwpf/fapi2/include/target.H b/import/hwpf/fapi2/include/target.H index 1add61d6..5946e3cf 100644 --- a/import/hwpf/fapi2/include/target.H +++ b/import/hwpf/fapi2/include/target.H @@ -332,6 +332,6 @@ namespace fapi2 { return (K & T) != 0; } -}; +} #endif diff --git a/import/hwpf/fapi2/include/target_types.H b/import/hwpf/fapi2/include/target_types.H index f4cfd931..5cee0141 100644 --- a/import/hwpf/fapi2/include/target_types.H +++ b/import/hwpf/fapi2/include/target_types.H @@ -48,14 +48,14 @@ namespace fapi2 TARGET_TYPE_DIMM = 0x00000002, ///< DIMM type TARGET_TYPE_PROC_CHIP = 0x00000004, ///< Processor type TARGET_TYPE_MEMBUF_CHIP = 0x00000008, ///< Membuf type - TARGET_TYPE_EX = 0x00000010, ///< Ex type + TARGET_TYPE_EX = 0x00000010, ///< EX - 2x Core, L2, L3 - can be deconfigured TARGET_TYPE_MBA = 0x00000020, ///< MBA type TARGET_TYPE_MCS = 0x00000040, ///< MCS type TARGET_TYPE_XBUS = 0x00000080, ///< XBUS type TARGET_TYPE_ABUS = 0x00000100, ///< ABUS type TARGET_TYPE_L4 = 0x00000200, ///< L4 type - TARGET_TYPE_CORE = 0x00000400, ///< Core type - TARGET_TYPE_EQ = 0x00000800, ///< EQ type + TARGET_TYPE_CORE = 0x00000400, ///< Core - 4x threads(?) - can be deconfigured + TARGET_TYPE_EQ = 0x00000800, ///< EQ - 4x core, 2x L2, 2x L3 - can be deconfigured TARGET_TYPE_MCA = 0x00001000, ///< MCA type TARGET_TYPE_MCBIST = 0x00002000, ///< MCBIST type TARGET_TYPE_MIA = 0x00004000, ///< MIA type @@ -68,7 +68,6 @@ namespace fapi2 TARGET_TYPE_PERV = 0x00200000, ///< Pervasive type TARGET_TYPE_PEC = 0x00400000, ///< PEC type TARGET_TYPE_PHB = 0x00800000, ///< PHB type - TARGET_TYPE_EL = 0x01000000, ///< L3/L2 Caches TARGET_TYPE_ALL = 0xFFFFFFFF, ///< Any/All types @@ -100,6 +99,6 @@ namespace fapi2 static const uint8_t count = 0; }; /// @endcond -}; +} #endif diff --git a/import/hwpf/fapi2/include/variable_buffer.H b/import/hwpf/fapi2/include/variable_buffer.H index a1280830..95183b32 100644 --- a/import/hwpf/fapi2/include/variable_buffer.H +++ b/import/hwpf/fapi2/include/variable_buffer.H @@ -73,26 +73,27 @@ namespace fapi2 /// @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> + template<typename unit_type, typename bits_type, typename output_type> inline fapi2::ReturnCode _insert(const unit_type* i_source, bits_type i_source_length, - unit_type* i_target, + output_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; + const bits_type bits_per_input_unit = parameterTraits<unit_type>::bit_length(); + const bits_type bits_per_output_unit =parameterTraits<output_type>::bit_length(); - // tartgetStart is defaulted to the sizeof(target) - (sizeof(source) - i_source_start_bit) + // targetStart 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) + if (i_target_start_bit == static_cast<bits_type>(~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) + if (i_length == static_cast<bits_type>(~0)) { i_length = i_source_length - i_source_start_bit; } @@ -106,17 +107,17 @@ namespace fapi2 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; + const bits_type src_idx = i_source_start_bit / bits_per_input_unit; + const bits_type trg_idx = i_target_start_bit / bits_per_output_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; + const bits_type src_slop = i_source_start_bit % bits_per_input_unit; + const bits_type trg_slop = i_target_start_bit % bits_per_output_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); + bits_type cnt = std::min(i_length, bits_per_input_unit); + cnt = std::min(cnt, bits_per_input_unit - src_slop); + cnt = std::min(cnt, bits_per_output_unit - trg_slop); // generate the source mask only once bits_type mask = fast_mask32(src_slop, cnt); @@ -127,9 +128,6 @@ namespace fapi2 // "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; @@ -143,6 +141,7 @@ namespace fapi2 // 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; @@ -150,6 +149,7 @@ namespace fapi2 i_target_start_bit += cnt; i_length -= cnt; + } while (0 < i_length); return fapi2::FAPI2_RC_SUCCESS; @@ -182,9 +182,47 @@ namespace fapi2 /// /// @brief Variable buffer list constructor /// @param[in] i_value an initializer list to initialize the container. + /// @warning Input data is assumed to be right-aligned and must be 32 bits /// variable_buffer(const std::initializer_list<unit_type>& i_value); + /// + /// @brief Variable buffer copy constructor + /// @param[in] i_buffer the buffer to copy from + /// + variable_buffer(const variable_buffer& i_buffer): + buffer_base() + { + iv_perceived_bit_length = i_buffer.iv_perceived_bit_length; + iv_data = i_buffer.iv_data; + } + + /// + /// @brief Variable buffer move constructor + /// @param[in] i_buffer the buffer to move + /// + variable_buffer(variable_buffer&& i_buffer): + buffer_base() + { + iv_perceived_bit_length = i_buffer.iv_perceived_bit_length; + i_buffer.iv_perceived_bit_length = 0; + iv_data = std::move(i_buffer.iv_data); + } + + /// + /// @brief Variable buffer array constructor + /// @param[in] i_value a uint32_t array to initialize the container. + /// @param[in] i_length the length of the array in 32-bit words + /// @param[in] i_bit_length the length of the resulting buffer in bits. + /// @warning This assumes the underlying container of a variable_buffer + /// is a uint32_t - which it is. + /// @note To use this constructor given an ecmdDataBuffer, you would + /// ecmd.memCopyOut( buffer, ... ); + /// variable_buffer( buffer, ecmd.getCapacity(), ecmd.getBitLength()); + /// + variable_buffer(const uint32_t* i_value, const uint32_t i_length, + const uint32_t i_bit_length); + /// @name Bit/Word Manipulation Functions ///@{ @@ -226,8 +264,8 @@ namespace fapi2 } iv_data[index] |= - unit_type(1) << (bits_per_unit - 1) - - (i_bit - (index * bits_per_unit)); + unit_type(1) << ((bits_per_unit - 1) - + (i_bit - (index * bits_per_unit))); return FAPI2_RC_SUCCESS; } @@ -319,9 +357,28 @@ namespace fapi2 /// @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 move operator=() + /// @note To use: new_buffer = std::move(old_buffer). old_buffer will be + /// destroyed and no copy will be made (moved) + /// + variable_buffer& operator=(variable_buffer&& other) + { + iv_perceived_bit_length = other.iv_perceived_bit_length; + other.iv_perceived_bit_length = 0; + iv_data = std::move(other.iv_data); + return *this; + } + + /// + /// @brief operator=() + /// + variable_buffer& operator=(const variable_buffer& other) + { + iv_perceived_bit_length = other.iv_perceived_bit_length; + iv_data = other.iv_data; + return *this; + } /// /// @brief operator>>() @@ -339,10 +396,37 @@ namespace fapi2 /// /// @brief operator+() + /// @param[in] A variable_buffer to append to this /// -#ifdef DOXYGEN - variable_buffer<T>& operator+(const T& rhs); -#endif + variable_buffer& operator+(const variable_buffer& rhs) + { + iv_perceived_bit_length += rhs.iv_perceived_bit_length; + iv_data.insert(iv_data.end(), rhs.iv_data.begin(), rhs.iv_data.end()); + return *this; + } + + /// + /// @brief operator+() + /// @param[in] A number of bits to add to this buffer + /// + variable_buffer& operator+(const bits_type& rhs) + { + if (rhs != 0) + { + iv_perceived_bit_length += rhs; + iv_data.resize(_vector_size(iv_perceived_bit_length)); + } + return *this; + } + + /// + /// @brief resize() + /// @param[in] Desired resulting size of the buffer, in bits + /// + variable_buffer& resize(const bits_type& rhs) + { + return operator+(rhs - iv_perceived_bit_length); + } /// /// @brief operator+=() @@ -389,22 +473,22 @@ namespace fapi2 /// /// @brief operator!=() /// -#ifdef DOXYGEN - bool operator!=(const T& rhs) const; -#endif + bool operator!=(const variable_buffer& rhs) const + { return ! operator==(rhs); } /// /// @brief operator==() /// @return true if and only if lhs == rhs /// - inline bool operator==(const fapi2::bits_container& rhs) const + inline bool operator==(const fapi2::variable_buffer& rhs) const { - if (&iv_data == &rhs) + if (&iv_data == &rhs.iv_data) { return true; } - return iv_data == rhs; + return (iv_data == rhs.iv_data) && + (iv_perceived_bit_length == rhs.iv_perceived_bit_length); } /// @@ -466,7 +550,7 @@ namespace fapi2 private: // Just shorthand ... static const bits_type bits_per_unit = - bufferTraits<bits_container>::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. @@ -517,7 +601,17 @@ namespace fapi2 "code currently needs unit_type to be a unit32_t"); } + inline variable_buffer:: + variable_buffer(const uint32_t* i_value, const uint32_t i_length, + const uint32_t i_bit_length): + iv_perceived_bit_length(i_bit_length) + { + static_assert(std::is_same<unit_type, uint32_t>::value, + "code currently needs unit_type to be a unit32_t"); + // Copy the array in to our vector. + iv_data.insert(iv_data.end(), i_value, &i_value[i_length]); + } /// @cond // @@ -529,7 +623,30 @@ namespace fapi2 bits_type i_len, bits_type i_sourceStart) { - return _insert((unit_type*)(&i_source), parameterTraits<OT>::bit_length, + // _insert likes 32-bit sources. So lets make our source 32 bits. + uint32_t l_source = static_cast<uint32_t>(i_source); + bits_type l_sourceStart = i_sourceStart + + parameterTraits<uint32_t>::bit_length() - parameterTraits<OT>::bit_length(); + + return _insert(&l_source, parameterTraits<uint32_t>::bit_length(), + &(iv_data[0]), getBitLength(), + l_sourceStart, i_targetStart, i_len); + } + + // + // If the source is 64-bits, treat that as 2x32 + template<> + inline fapi2::ReturnCode variable_buffer::insert(const uint64_t& i_source, + bits_type i_targetStart, + bits_type i_len, + bits_type i_sourceStart) + { + // _insert wants 32 bit chunks, so lets turn our uint64_t into a + // uint32_t array (of 64 bits in length). Looks like a 64 bit variable_buffer. + uint32_t l_source[2] = {static_cast<uint32_t>((i_source & 0xFFFFFFFF00000000) >> 32), + static_cast<uint32_t>((i_source & 0x00000000FFFFFFFF))}; + + return _insert(l_source, parameterTraits<uint64_t>::bit_length(), &(iv_data[0]), getBitLength(), i_sourceStart, i_targetStart, i_len); } @@ -544,7 +661,8 @@ namespace fapi2 bits_type i_len, bits_type i_sourceStart) { - return _insert((unit_type*)&(i_data()[0]), i_data.getBitLength(), + return _insert(reinterpret_cast<const unit_type*>(&(i_data()[0])), + i_data.getBitLength(), &(iv_data[0]), getBitLength(), i_sourceStart, i_targetStart, i_len); } @@ -558,7 +676,7 @@ namespace fapi2 bits_type i_targetStart, bits_type i_len) { - _insertFromRight(i_data, parameterTraits<OT>::bit_length, i_targetStart, i_len); + return _insertFromRight(i_data, parameterTraits<OT>::bit_length(), i_targetStart, i_len); } // @@ -571,7 +689,7 @@ namespace fapi2 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); + return _insertFromRight(i_data, bit_length_of_source, i_targetStart, i_len); } @@ -586,19 +704,125 @@ namespace fapi2 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 == static_cast<bits_type>(~0)) + { + i_len = std::min(getBitLength(), parameterTraits<OT>::bit_length()); + } + + // _insert likes 32-bit targets. So lets make our target 32 bits. + uint32_t l_data = static_cast<uint32_t>(i_data); + + ReturnCode rc; + if ((rc = _insert((container_unit*)&iv_data[0], getBitLength(), + &l_data, parameterTraits<uint32_t>::bit_length(), + i_start, 0U, i_len)) != FAPI2_RC_SUCCESS) + { + return rc; + } + + // Shift back to the original bit width. + i_data = l_data >> (parameterTraits<uint32_t>::bit_length() - parameterTraits<OT>::bit_length()); + return FAPI2_RC_SUCCESS; + } + template<> + inline fapi2::ReturnCode variable_buffer::extract( + uint64_t& 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) + if ((i_len == static_cast<bits_type>(~0)) || + (i_len > parameterTraits<uint64_t>::bit_length())) { - i_len = max_length; + i_len = std::min(getBitLength(), parameterTraits<uint64_t>::bit_length()); } - return _insert((container_unit*)&iv_data[0], getBitLength(), - &i_data, max_length, - i_start, 0U, i_len); + // _insert wants 32 bit chunks, so lets turn our uint64_t into a + // uint32_t array (of 64 bits in length). Looks like a 64 bit variable_buffer. + uint32_t l_data[2] = {static_cast<uint32_t>((i_data & 0xFFFFFFFF00000000) >> 32), + static_cast<uint32_t>((i_data & 0x00000000FFFFFFFF))}; + + ReturnCode rc; + if ((rc = _insert((container_unit*)&iv_data[0], getBitLength(), + l_data, parameterTraits<uint64_t>::bit_length(), + i_start, 0U, i_len)) != FAPI2_RC_SUCCESS) + { + return rc; + } + + i_data = static_cast<uint64_t>(l_data[0]) << 32; + i_data |= l_data[1]; + + return FAPI2_RC_SUCCESS; + } + + // + // Generic extractToRight. Extract is an insert with the arguments reversed. + // + template<typename OT> + inline fapi2::ReturnCode variable_buffer::extractToRight( + OT& 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 == static_cast<bits_type>(~0)) || + (i_len > parameterTraits<OT>::bit_length())) + { + i_len = std::min(getBitLength(), parameterTraits<OT>::bit_length()); + } + + // _insert likes 32-bit targets. So lets make our target 32 bits. + uint32_t l_data = static_cast<uint32_t>(i_data); + + ReturnCode rc; + if ((rc = _insert(reinterpret_cast<const container_unit*>(&iv_data[0]), getBitLength(), + &l_data, parameterTraits<uint32_t>::bit_length(), + i_start, parameterTraits<uint32_t>::bit_length() - i_len, i_len)) != FAPI2_RC_SUCCESS) + { + return rc; + } + + i_data = l_data; + return FAPI2_RC_SUCCESS; + } + + template<> + inline fapi2::ReturnCode variable_buffer::extractToRight( + uint64_t& 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 == static_cast<bits_type>(~0)) || + (i_len > parameterTraits<uint64_t>::bit_length())) + { + i_len = std::min(getBitLength(), parameterTraits<uint64_t>::bit_length()); + } + + // _insert wants 32 bit chunks, so lets turn our uint64_t into a + // uint32_t array (of 64 bits in length). + uint32_t l_data[2] = {static_cast<uint32_t>((i_data & 0xFFFFFFFF00000000) >> 32), + static_cast<uint32_t>((i_data & 0x00000000FFFFFFFF))}; + + ReturnCode rc; + if ((rc = _insert(reinterpret_cast<const container_unit*>(&iv_data[0]), getBitLength(), + l_data, parameterTraits<uint64_t>::bit_length(), + i_start, parameterTraits<uint64_t>::bit_length() - i_len, i_len)) != FAPI2_RC_SUCCESS) + { + return rc; + } + + i_data = static_cast<uint64_t>(l_data[0]) << 32; + i_data |= l_data[1]; + + return FAPI2_RC_SUCCESS; } // @@ -612,11 +836,11 @@ namespace fapi2 { // If thy didn't pass an i_len, assume they want all the data // which will fit. - if (i_len == ~0) + if (i_len == static_cast<bits_type>(~0)) { i_len = i_data.getBitLength(); } - return _insert((container_unit*)&iv_data[0], getBitLength(), + return _insert(reinterpret_cast<const container_unit*>(&iv_data[0]), getBitLength(), &(i_data()[0]), i_data.getBitLength(), i_start, 0U, i_len); } @@ -632,7 +856,7 @@ namespace fapi2 { // If they didn't pass in a length, assume they want all the i_data // which will fit. - if( i_len == ~0 ) + if( i_len == static_cast<bits_type>(~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 @@ -657,7 +881,7 @@ namespace fapi2 bits_type i_offset); #endif /// @endcond -}; +} #endif |