diff options
| author | Brian Silver <bsilver@us.ibm.com> | 2015-02-10 07:40:19 -0600 |
|---|---|---|
| committer | Joshua Hunsberger <jahunsbe@us.ibm.com> | 2017-10-23 15:50:50 -0500 |
| commit | 360ef22ccf2715d9581e78a088449e0b164d6486 (patch) | |
| tree | 06b9287008f8301e4f616ae3bcb2211047fdead7 /import/hwpf/fapi2 | |
| parent | ac19be2005906145169cabf08d18b88c0376abae (diff) | |
| download | talos-hcode-360ef22ccf2715d9581e78a088449e0b164d6486.tar.gz talos-hcode-360ef22ccf2715d9581e78a088449e0b164d6486.zip | |
Error/xml parsing and FFDC classes
Change-Id: Iddc92bb876dd07efe398255d7321ac6394eb4ae9
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15966
Reviewed-by: Thi N. Tran <thi@us.ibm.com>
Reviewed-by: Matt K. Light <mklight@us.ibm.com>
Reviewed-by: Brian Silver <bsilver@us.ibm.com>
Tested-by: Brian Silver <bsilver@us.ibm.com>
Diffstat (limited to 'import/hwpf/fapi2')
| -rw-r--r-- | import/hwpf/fapi2/include/buffer.H | 421 | ||||
| -rw-r--r-- | import/hwpf/fapi2/include/buffer_parameters.H | 65 | ||||
| -rw-r--r-- | import/hwpf/fapi2/include/buffer_traits.H | 232 | ||||
| -rw-r--r-- | import/hwpf/fapi2/include/error_scope.H | 104 |
4 files changed, 822 insertions, 0 deletions
diff --git a/import/hwpf/fapi2/include/buffer.H b/import/hwpf/fapi2/include/buffer.H new file mode 100644 index 00000000..363d69ac --- /dev/null +++ b/import/hwpf/fapi2/include/buffer.H @@ -0,0 +1,421 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/hwpf/fapi2/include/buffer.H $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2012,2017 */ +/* [+] 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 buffer.H + * @brief definitions for fapi2 variable integral buffers + */ + +#ifndef __FAPI2_INTEGRAL_BUFFER__ +#define __FAPI2_INTEGRAL_BUFFER__ + +#include <buffer_base.H> +#include <return_code.H> + +namespace fapi2 +{ + /// @brief Class representing a FAPI buffer<T> + /// @note Buffers support method chaining. So, rather than + /// this + /// @code + /// buffer<T> mask; + /// mask.setBit<B>(); + /// mask.invert(); + /// my_buffer &= mask; + /// @endcode + /// You can do + /// @code + /// my_buffer &= buffer<T>().setBit<B>.invert(); + /// @endcode + template <typename T> + class buffer : public buffer_base<T> + { + public: + typedef typename buffer_base<T, buffer>::bits_type bits_type; + + /// + /// @brief Integral buffer assignment constructor + /// @param[in] i_value initial value of the buffer + /// Meaningless for variable types and thus protected. + /// + inline buffer(T i_value = 0) + { + // Why not an initializer list? That would force buffer_base<T> + // to have a ctor which took a T, and I want to avoid that in + // the generic case: this makes it more clear that the two + // ctor's (integral and container) behave very differently. + // variable_buffers also have a ctor which takes a single + // numerical value, and that represents a bit count, not an + // initial value. + this->iv_data = i_value; + } + + + /// @name Bit/Word Manipulation Functions + ///@{ + + /// + /// @brief Return the length of the buffer in bits + /// @return Length in bits + /// + inline constexpr uint32_t getBitLength(void) const + { return bufferTraits<T>::bit_length(this->iv_data); } + + /// + /// @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 constexpr uint32_t getLength(void) const + { + return bufferTraits<T>::template size<OT>(this->iv_data); + } + + /// + /// @brief Templated setBit for integral types + /// @tparam B the bit number to set. + /// @return buffer& Useful for method chaining + /// @note 0 is left-most + /// @note Example: fapi2::buffer<uint64_t>().setBit<3>(); + /// + template <bits_type B> + inline buffer& setBit(void) + { + static_assert((B >= 0) && + (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); + return *this; + } + + /// + /// @brief Clear a bit in buffer + /// @tparam B Bit in buffer to clear. + /// @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< bits_type B > + inline buffer& clearBit(void) + { + static_assert((B >= 0) && + (B < bufferTraits<T>::bits_per_unit), "failed range check"); + + this->iv_data &= buffer<T>().setBit<B>().invert(); + return *this; + } + + /// + /// @brief Invert bit + /// @tparam B Bit in buffer to invert. + /// @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< bits_type B > + inline buffer& flipBit(void) + { + static_assert((B >= 0) && + (B < bufferTraits<T>::bits_per_unit), "failed range check"); + + this->iv_data ^= buffer<T>().setBit<B>(); + 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 >= bufferTraits<T>::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 + this->iv_data |= + (static_cast<T>(1)) << (bufferTraits<T>::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. + /// @return true if bit is on, false if bit is off + /// + template< bits_type B > + inline bool getBit(void) const + { + return buffer<T>().setBit<B>() & this->iv_data; + } + + ///@} + + /// @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 + buffer<T>& operator>>(bits_type i_shiftnum); +#endif + + /// + /// @brief operator<<() + /// +#ifdef DOXYGEN + buffer<T>& operator<<(bits_type i_shiftnum); +#endif + + /// + /// @brief operator+() + /// +#ifdef DOXYGEN + buffer<T>& operator+(const T& rhs); +#endif + + /// + /// @brief operator+=() + /// +#ifdef DOXYGEN + buffer<T>& operator+=(const T& rhs); +#endif + + /// + /// @brief operator|=() + /// +#ifdef DOXYGEN + buffer<T>& operator|=(const T& rhs); +#endif + + /// + /// @brief operator&=() + /// +#ifdef DOXYGEN + buffer<T>& operator&=(const T& rhs); +#endif + + /// + /// @brief operator|() + /// +#ifdef DOXYGEN + buffer<T>& operator|(const T& rhs); +#endif + + /// + /// @brief operator&() + /// +#ifdef DOXYGEN + buffer<T>& operator&(const T& rhs); +#endif + + /// + /// @brief operator^=() + /// +#ifdef DOXYGEN + buffer<T>& operator^=(const T& rhs); +#endif + + /// + /// @brief operator==() + /// +#ifdef DOXYGEN + buffer<T>& operator==(const T& rhs) const; +#endif + + /// + /// @brief operator!=() + /// +#ifdef DOXYGEN + bool operator!=(const T& rhs) const; +#endif + + /// + /// @brief operator~() + /// +#ifdef DOXYGEN + bool operator~(const T& rhs) const; +#endif + /// + /// @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 OT the type of the incoming (origin) data + /// @param[in] i_data OT value to copy into DataBuffer + /// - data is taken left aligned + /// @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 TS, bits_type L, bits_type SS, 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; + + // Error if input data don't make sense + static_assert((TS + L) <= target_length, + "insert(): (Target Start + Len) is out of bounds"); + static_assert((SS + L) <= source_length, + "insert(): (Source Start + Len) is out of bounds"); + static_assert(TS < target_length, + "insert(): Target Start is out of bounds"); + 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; + + // Calculate the equivalent position of the input Source start for the size of the Target buffer. + + // 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; + + if (sizeof(T) == sizeof(OT)) + { + sourceShift = abs(SS - TS); + sourceAlign = (SS > TS) ? ((T)i_datain) << sourceShift : ((T)i_datain) >> sourceShift; + } + + if (sizeof(T) < sizeof(OT)) + { + 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); + } + } + } + + this->iv_data = (this->iv_data & ~mask) | (sourceAlign & mask); + return; + } + + /// + /// @brief Copy in a right aligned value + /// @tparam SB Start bit to insert into + /// @tparam L Length of bits to insert + /// @tparam OT the type of the incoming (origin) data + /// @param[in] i_data OT value to copy into DataBuffer + /// - data is taken right aligned + /// @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<bits_type TS, bits_type L, typename OT> + inline void insertFromRight(const OT i_datain) + { + // Error if input data don't make sense + static_assert(L < parameterTraits<OT>::bit_length, + "insertFromRight(): Len >= input buffer"); + static_assert(TS < parameterTraits<T>::bit_length, + "insertFromRight(): Target Start is out of bounds"); + 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); + return; + } + + /// + /// @brief Copy data from this buffer into an OT + /// @tparam TS Start bit to insert into (target start) + /// @tparam L Length of bits to insert + /// @tparam SS Start bit in source + /// @tparam OT the type of the outgoing (target) + /// @param[out] o_out OT to copy into - data is placed left aligned + /// @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 TS, bits_type L, bits_type SS, typename OT> + inline void extract(OT& o_out) + { + // Extraction is just an insert into o_out + + buffer<OT> out(o_out); + out.insert<TS, L, SS>(this->iv_data); + o_out = out; + return; + } + +#if 0 + /// + /// @brief Copy data from this buffer into an OT and right justify + /// @tparam OT the type of the outgoing data - defaults to T + /// @tparam SB Start bit to insert into - defaults to 0 + /// @tparam SS Start bit in o_out - default value is zero + /// @tparam L Length of bits to copy - defaults to sizeof(OT) * 8 + /// @param[out] o_out OT to copy into - data is placed right aligned + /// @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. + /// @post Data is copied from specified location to o_out, right + /// aligned. Data is only right aligned if L < sizeof(bits_type) + /// + template< typename OT = T, bits_type L = parameterTraits<OT>::bit_length, + bits_type SB = 0, bits_type SS = 0 > + void extractFromRight(OT& o_out); +#endif + ///@} + }; +}; + +#endif diff --git a/import/hwpf/fapi2/include/buffer_parameters.H b/import/hwpf/fapi2/include/buffer_parameters.H new file mode 100644 index 00000000..90b3db45 --- /dev/null +++ b/import/hwpf/fapi2/include/buffer_parameters.H @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/hwpf/fapi2/include/buffer_parameters.H $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2012,2017 */ +/* [+] 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 buffer_parameters.H + * @brief definitions for fapi2 buffer parameter types + */ + +#ifndef __FAPI2_BUFFER_PARAM__ +#define __FAPI2_BUFFER_PARAM__ + +#include <stdint.h> + +namespace fapi2 +{ + /// @cond + /// @brief Traits of buffer parameters - things passed in + /// @tparam T is the type of i_value (typically an integral type) + template<typename T> + class parameterTraits + { + public: + enum + { + mask = T(~0), + bit_length = sizeof(T) * 8, + byte_length = sizeof(T), + }; + + template<typename U> + inline static void write_element(void* i_data, T i_value, uint32_t i_offset) + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + T* ptr = (T*)i_data + (i_offset ^ ((sizeof(U) / sizeof(T)) - 1)); +#else + T* ptr = (T*)i_data + i_offset; +#endif + *ptr = i_value; + } + }; + /// @endcond +}; + +#endif diff --git a/import/hwpf/fapi2/include/buffer_traits.H b/import/hwpf/fapi2/include/buffer_traits.H new file mode 100644 index 00000000..b9362386 --- /dev/null +++ b/import/hwpf/fapi2/include/buffer_traits.H @@ -0,0 +1,232 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/hwpf/fapi2/include/buffer_traits.H $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2012,2017 */ +/* [+] 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 buffer_traits.H + * @brief trait definitions for fapi2 buffer base class + */ + +#ifndef __FAPI2_BUFFER_TRAITS__ +#define __FAPI2_BUFFER_TRAITS__ + +#include <stdint.h> +#include <vector> +#include <algorithm> +#include <buffer_parameters.H> + +// for debug printing ... can be removed for flight +#include <iostream> +#include <iterator> + +namespace fapi2 +{ + /// @cond + /// Types representing a container of bits. Used to create + /// variable_buffer. + typedef uint32_t container_unit; + typedef std::vector<container_unit> bits_container; + + /// @brief Traits of buffers + // In general, we try to give buffers traits reflecting integral types. If + // this fails, the compiler will let someone know. + /// + /// @tparam T is the type of iv_data (std::vector, etc) + /// @tparam B is the type of the bit-specifier, typically uint32_t + template<typename T, typename B = uint32_t> + class bufferTraits + { + public: +#ifndef DOXYGEN + /// + /// @brief Print a container of bits + /// @param[in] i_data the container of bits + /// + static inline void print(const T& i_data) + { + // convert to uint64_t to prevent uint8_t from being + // printed as a char. + std::cout << "\tdata is " + << std::hex + << static_cast<uint64_t>(i_data) + << std::dec << std::endl; + } +#endif + + /// + /// @brief Return the size of the buffer in E units + /// @tparam E, the element size. + /// @param[in] io_buffer the buffer which to size + /// @return The size of the buffer in E's rounded up + /// + template<typename E> + constexpr static B size(const T& i_buffer) + { + return (bit_length(i_buffer) + + (parameterTraits<E>::bit_length - 1)) / + parameterTraits<E>::bit_length; + } + + /// + /// @brief Return the size of the buffer itself + /// @param[in] io_buffer the buffer which to size + /// @return The size of the buffer in bits (not units) + /// + constexpr static B bit_length(const T&) + { return sizeof(T) * 8; } + + /// + /// @brief Clear the buffer + /// @param[in,out] io_buffer the buffer which to clear + /// + static inline void clear(T& io_buffer) + { io_buffer = static_cast<T>(0); } + + /// + /// @brief Set the buffer + /// @param[in,out] io_buffer the buffer which to set + /// + static inline void set(T& io_buffer) + { io_buffer = static_cast<T>(~0); } + + /// + /// @brief Invert the buffer + /// @param[in,out] io_buffer the buffer which to invert + /// + static inline void invert(T& io_buffer) + { io_buffer = ~io_buffer; } + + /// + /// @brief Reverse the buffer + /// @param[in,out] io_buffer the buffer which to reverse + /// + static inline void reverse(T& io_buffer) + { + io_buffer = + ((io_buffer & 0xAAAAAAAAAAAAAAAA) >> 1) | + ((io_buffer & 0x5555555555555555) << 1); + } + + /// + /// @brief Get the address of the buffer as an array + /// @param[in] i_buffer the buffer which to invert + /// @return The address of the first element of the buffer + /// + static inline void* get_address(T& i_buffer) + { return (void*)&i_buffer; } + + typedef B bits_type; + typedef T unit_type; + enum { bits_per_unit = sizeof(unit_type) * 8 }; + }; + + // + // + /// @brief Traits for buffers which are a container of bits + // + // + template<> + class bufferTraits<bits_container, uint32_t> + { + public: +#ifndef DOXYGEN + /// + /// @brief Print a container of bits + /// @param[in] i_data the container of bits + /// + static inline void print(const bits_container& i_data) + { + std::cout << "\tdata is " << std::hex; + std::copy(i_data.begin(), i_data.end(), + std::ostream_iterator<container_unit>(std::cout, " ")); + std::cout << std::dec << std::endl; + } +#endif + + /// + /// @brief Return the size of the buffer in E units + /// @tparam E, the element size. + /// @param[in] io_buffer the buffer which to size + /// @return The size of the buffer in E's rounded up + /// + template<typename E> + constexpr static uint32_t size(const bits_container& i_buffer) + { + return (bit_length(i_buffer) + + (parameterTraits<E>::bit_length - 1)) / + parameterTraits<E>::bit_length; + } + + /// + /// @brief Return the size of the buffer itself + /// @param[in,out] io_buffer the buffer which to size + /// @return The size of the buffer in bits (not units) + /// + static inline uint32_t bit_length(const bits_container& i_buffer) + { return i_buffer.size() * sizeof(container_unit) * 8; } + + /// + /// @brief Clear the buffer + /// @param[in,out] io_buffer the buffer which to clear + /// + static inline void clear(bits_container& io_buffer) + { io_buffer.assign(io_buffer.size(), 0); } + + /// + /// @brief Set the buffer + /// @param[in,out] io_buffer the buffer which to set + /// + static inline void set(bits_container& io_buffer) + { io_buffer.assign(io_buffer.size(), ~0); } + + /// + /// @brief Invert the buffer + /// @param[in,out] io_buffer the buffer which to invert + /// + static inline void invert(bits_container& io_buffer) + { + std::transform(io_buffer.begin(), io_buffer.end(), + io_buffer.begin(), + [](container_unit u) { return ~u; }); + } + + /// + /// @brief Get the address of the buffer as an array + /// @param[in] i_buffer the buffer which to invert + /// @return The address of the first element of the buffer + /// + static inline void* get_address(bits_container& i_buffer) + { + return (void*)&(i_buffer[0]); + } + + typedef uint32_t bits_type; + typedef container_unit unit_type; + enum { bits_per_unit = sizeof(unit_type) * 8 }; + }; + /// @endcond +}; + + + +#endif diff --git a/import/hwpf/fapi2/include/error_scope.H b/import/hwpf/fapi2/include/error_scope.H new file mode 100644 index 00000000..6b265343 --- /dev/null +++ b/import/hwpf/fapi2/include/error_scope.H @@ -0,0 +1,104 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/hwpf/fapi2/include/error_scope.H $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2012,2017 */ +/* [+] 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 error_scope.H + * @brief definitions which create a scope for automatic error handling + */ + +#ifndef __FAPI2_ERROR_SCOPE__ +#define __FAPI2_ERROR_SCOPE__ + +#include <stdint.h> +#include <thread> +#include <stdio.h> +#include <return_code.H> + +/// @cond +#define FAPI_VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N +#define FAPI_VA_NARGS(...) FAPI_VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1) + +#define FAPI_TRY_IMPL2(count, ...) FAPI_TRY ## count (__VA_ARGS__) +#define FAPI_TRY_IMPL(count, ...) FAPI_TRY_IMPL2(count, __VA_ARGS__) + +#define FAPI_TRY_NO_TRACE( __operation__ ) \ + if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \ + { \ + goto clean_up; \ + } + +// Why debug? Because this isn't a mechanism to gather FFDC +// one should be using FAPI_ASSERT. However, it is nice to +// have a conditional trace in the event of a failure in the +// operation, so that's why this is here. +#define FAPI_TRY_TRACE( __operation__, ... ) \ + if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \ + { \ + FAPI_DBG(__VA_ARGS__); \ + goto clean_up; \ + } + +#define FAPI_TRY1 FAPI_TRY_NO_TRACE +#define FAPI_TRY2 FAPI_TRY_TRACE +#define FAPI_TRY3 FAPI_TRY_TRACE +#define FAPI_TRY4 FAPI_TRY_TRACE +#define FAPI_TRY5 FAPI_TRY_TRACE +/// @endcond + +/// +/// @brief Wrapper to check an operation for an error state +/// and jump to the label cleam_up if there is an error. +/// @param[in] __operation__ an operation which returns a fapi::ReturnCode +/// @param[in] Optional vararg format/agruments for trace output. +/// @note This implementation does not support PIB error masks or +/// FSP operational states. +/// @warning The trace information is only going to be seen during +/// debug, it's not an error or informational trace. This is because +/// traces might not be seen in the field. If you want information +/// you will see on a field error, use FAPI_ASSERT. +/// +#ifdef DOXYGEN +#define FAPI_TRY(__operation__, ...) FAPI_TRY_IMPL +#else +#define FAPI_TRY(...) FAPI_TRY_IMPL(FAPI_VA_NARGS(__VA_ARGS__), __VA_ARGS__) +#endif + +/// +/// @brief Assert a conditional is true. +/// If it is not, the FFDC gathering function is called and the +/// trace is output as a FAPI error trace. +/// @param[in] __conditional__ the condition to assert +/// @param[in] __ffdc__ the FFDC gathering function +/// @param[in] ... varargs, as input to FAPI_ERR +/// +#define FAPI_ASSERT( __conditional__, __ffdc__, ... ) \ + if (! (__conditional__)) \ + { \ + (__ffdc__).execute(); \ + FAPI_ERR(__VA_ARGS__); \ + goto clean_up; \ + } + + +#endif |

