diff options
author | Greg Still <stillgs@us.ibm.com> | 2015-06-03 07:12:31 -0500 |
---|---|---|
committer | Derk Rembold <rembold@de.ibm.com> | 2015-06-16 13:20:49 -0500 |
commit | 5e9cb6846e5860c4f82d234760c32ca561ac3854 (patch) | |
tree | 95c4e1fbde8170fb6b7c8234c107bacf718e1030 /hwpf/plat | |
parent | 2315a070ebd8edeaac44df5d7a2d17ad7b44f1bb (diff) | |
download | talos-sbe-5e9cb6846e5860c4f82d234760c32ca561ac3854.tar.gz talos-sbe-5e9cb6846e5860c4f82d234760c32ca561ac3854.zip |
PPE FAPI2 resync changes
- Tested SCOMs (absolute and FAPI_TRY) on GPE SIMICS without RCs
to chip target OCB registers. GPE SIMICS model does not have
registers in non-chip level targets.
- Testing on GPE SIMICS with RCs fails with illegal addresses in
thread local storage initialization
- Added ./ppe/sbe/plat platform specifics
- Added missing ./ppe/hwpf/plat/include files
- Added missing fapi2AttributeService.H
- Add PPE specific (though likely temporary) versions of buffer.H
(to deal with compile errors for "units_per_bit()" to "units_per_bit"
and "bit_length()" to "bit_length") and return_code.H (to include
return_code_defs.H)
- Add ppe/plat/include/plat_error_scope.H to deal with SBE return code
tracing
- Deleted old file version
- Added local version of buffer.H
- Move current_err to global variable (vs thread local storage);
This removes #include <thread>.
- Enable PK_TRACE under FAPI_* Trace macros
- Added plat_attributes.H to include generated platform specific files
- Added -DUSE_PK_APP_CFG to img_defs.mk
Change-Id: Ice6c24a5091d3cf8eb4e4d93a0d139086126df95
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/18239
Reviewed-by: Derk Rembold <rembold@de.ibm.com>
Tested-by: Derk Rembold <rembold@de.ibm.com>
Diffstat (limited to 'hwpf/plat')
-rw-r--r-- | hwpf/plat/include/buffer.H | 684 | ||||
-rw-r--r-- | hwpf/plat/include/buffer_traits.H | 28 | ||||
-rw-r--r-- | hwpf/plat/include/fapi2.H | 4 | ||||
-rw-r--r-- | hwpf/plat/include/fapi2AttributeService.H | 127 | ||||
-rw-r--r-- | hwpf/plat/include/fapi2_hw_access.H | 464 | ||||
-rw-r--r-- | hwpf/plat/include/fapi2_target.H | 496 | ||||
-rw-r--r-- | hwpf/plat/include/hw_access.H | 33 | ||||
-rw-r--r-- | hwpf/plat/include/plat_attributes.H | 36 | ||||
-rw-r--r-- | hwpf/plat/include/plat_error_scope.H | 65 | ||||
-rw-r--r-- | hwpf/plat/include/plat_hw_access.H | 4 | ||||
-rw-r--r-- | hwpf/plat/include/plat_trace.H | 22 | ||||
-rw-r--r-- | hwpf/plat/include/return_code.H | 108 | ||||
-rw-r--r-- | hwpf/plat/include/target.H | 689 | ||||
-rw-r--r-- | hwpf/plat/include/target_types.H | 2 | ||||
-rw-r--r-- | hwpf/plat/include/utils.H | 15 | ||||
-rw-r--r-- | hwpf/plat/src/fapi2ppefiles.mk | 2 | ||||
-rw-r--r-- | hwpf/plat/src/plat_utils.C | 79 |
17 files changed, 2351 insertions, 507 deletions
diff --git a/hwpf/plat/include/buffer.H b/hwpf/plat/include/buffer.H new file mode 100644 index 00000000..9e863c3b --- /dev/null +++ b/hwpf/plat/include/buffer.H @@ -0,0 +1,684 @@ +/* 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 buffer.H + * @brief definitions for fapi2 variable integral buffers + */ + +#ifndef __FAPI2_INTEGRAL_BUFFER__ +#define __FAPI2_INTEGRAL_BUFFER__ + +#include <buffer_parameters.H> +#include <buffer_traits.H> +#include <return_code.H> + +namespace fapi2 +{ + /// @brief Class representing a FAPI buffer<T> + /// @tparam T, the integral type of the buffer (uint16_t, uint64_t, etc.) + template <typename T, typename TT = bufferTraits<T> > + class buffer + { + public: + /// Shortcut typedef to get to our traits class + typedef typename TT::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): + iv_data(i_value) + { + } + + ~buffer(void) = default; + +#if !defined(DOXYGEN) && defined(FAPI2_DEBUG) + /// @brief Print the contents of the buffer to stdout + inline void print(void) const + { TT::print(iv_data); } +#endif + + /// + /// @brief Get the contents of the buffer + /// @return The contents of the buffer + /// + inline operator T() const { return iv_data; } + + /// + /// @brief Get the contents of the buffer + /// @return The contents of the buffer + /// + inline operator T&() { return iv_data; } + + /// + /// @brief Get the contents of the buffer + /// @return The contents of the buffer + /// + inline T& operator()(void) { return iv_data; } + + /// + /// @brief Get the contents of the buffer + /// @return Reference to the contents of the buffer + /// + inline const T& operator()(void) const { return iv_data; } + + /// @name Buffer Manipulation Functions + ///@{ + + /// + /// @brief Set an OT of data in buffer + /// @param[in] i_value sizeof(OT) bits of data + /// @param[in] i_offset Start OT (start word, for example) in buffer + /// - defaults to 0 (will by default write the left most element) + /// @return FAPI2_RC_SUCCESS on success, FAPI2_RC_OVERFLOW otherwise + /// @note This is is only available for integral types. To set a + /// variable_buffer into a variable_buffer, use insert() + /// + template< typename OT> + inline fapi2::ReturnCode set(OT i_value, const bits_type i_offset = 0) + { + // Compile time check to make sure OT is integral + static_assert( std::is_integral<OT>::value, + "Input must be an integral type" ); + + const uint32_t length = TT:: template size<OT>(iv_data); + static const bits_type bits_in_value = parameterTraits<OT>::bit_length(); + const bits_type bit_length = TT::bit_length(iv_data); + + if (i_offset + bits_in_value >= bit_length) + { + return FAPI2_RC_OVERFLOW; + } + + // Create mask if part of this byte is not in the valid part of the buffer, + // Shift it left by the amount of unused bits, + // Clear the unused bits + if (((i_offset + 1) == length) && (bit_length % bits_in_value)) { + i_value &= parameterTraits<OT>::mask() << ((bits_in_value * length) - bit_length); + } + + parameterTraits<OT>::template write_element<typename TT::unit_type>(TT::get_address(iv_data), i_value, i_offset); + return FAPI2_RC_SUCCESS; + } + + /// @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 TT::bit_length(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 TT::template size<OT>(iv_data); + } + + /// + /// @brief Templated setBit for integral types + /// @tparam B the bit number to set. + /// @tparam C the count of bits to set, defaults to 1 + /// @return buffer& Useful for method chaining + /// @note 0 is left-most + /// @note Example: fapi2::buffer<uint64_t>().setBit<3>(); + /// + template< bits_type B, bits_type C = 1 > + inline buffer& setBit(void) + { + static_assert((B >= 0) && + ((B + C - 1) < TT::bits_per_unit()), "failed range check"); + + // This would be a candidate for a fast_mask (see variable_buffer) but + // we'd need tables for all the integral types which maybe we need to + // do ... + iv_data |= (T(~0) >> (TT::bits_per_unit() - C)) << (TT::bits_per_unit() - B - C); + return *this; + } + + /// + /// @brief Set a bit in the buffer + /// @param[in] i_bit the bit number to set. + /// @param[in] i_count the count of bits to set, defaults to 1 + /// @note 0 is left-most + /// @return FAPI2_RC_SUCCESS if OK + /// + inline fapi2::ReturnCode setBit(const bits_type& i_bit, const bits_type& i_count = 1) + { + if ((i_count + i_bit - 1) >= TT::bits_per_unit()) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + iv_data |= (T(~0) >> (TT::bits_per_unit() - i_count)) << (TT::bits_per_unit() - i_bit - i_count); + + return FAPI2_RC_SUCCESS; + } + + /// + /// @brief Clear a bit in buffer + /// @tparam B Bit in buffer to clear. + /// @tparam C the count of bits to clear, defaults to 1 + /// @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, bits_type C = 1> + inline buffer& clearBit(void) + { + static_assert((B >= 0) && + ((B + C - 1)< TT::bits_per_unit()), "failed range check"); + + iv_data &= buffer<T>().setBit<B, C>().invert(); + return *this; + } + + /// + /// @brief Clear a bit in the buffer + /// @param[in] i_bit the bit number to clear. + /// @param[in] i_count the count of bits to clear, defaults to 1 + /// @note 0 is left-most + /// @return FAPI2_RC_SUCCESS if OK + /// + inline fapi2::ReturnCode clearBit(const bits_type& i_bit, const bits_type& i_count = 1) + { + if ((i_count + i_bit - 1) >= TT::bits_per_unit()) + { + return FAPI2_RC_INVALID_PARAMETER; + } + + fapi2::buffer<T> l_scratch; + + if (l_scratch.setBit(i_bit, i_count) != 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 + /// @tparam C the count of bits to write, defaults to 1 + /// @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, bits_type C = 1 > + inline buffer& writeBit(const bool i_value) + { + static_assert((B >= 0) && + ((B + C - 1)< TT::bits_per_unit()), "failed range check"); + + (i_value == 0) ? clearBit<B, C>() : setBit<B, C>(); + return *this; + } + + + /// + /// @brief Invert bit + /// @tparam B Bit in buffer to invert. + /// @tparam C the count of bits to flip, defaults to 1 + /// @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, bits_type C = 1 > + inline buffer& flipBit(void) + { + static_assert((B >= 0) && + ((B + C - 1) < TT::bits_per_unit()), "failed range check"); + + iv_data ^= buffer<T>().setBit<B, C>(); + return *this; + } + + /// + /// @brief Get the value of a bit in the buffer + /// @tparam B Bit in buffer to get. + /// @tparam C the count of bits to get, defaults to 1 + /// @return true if *any* bit is on, false if *every* bit is off + /// + template< bits_type B, bits_type C = 1> + inline bool getBit(void) const + { + return buffer<T>().setBit<B, C>() & iv_data; + } + + /// + /// @brief Set and entire buffer to X's + /// @tparam X {0,1} depending if you want to clear (0) + /// or fill (1) a buffer + /// @return buffer_base&, Useful for method chaining + /// + template< uint8_t X > + inline buffer& flush(void) + { + static_assert( (X == 1) || (X == 0), "bad argument to flush" ); + (0 == X) ? TT::clear(iv_data) : TT::set(iv_data); + return *this; + } + + /// + /// @brief Invert entire buffer + /// @return buffer_base&, Useful for method chaining + /// + inline buffer& invert(void) + { TT::invert(iv_data); return *this; } + + /// + /// @brief Bit reverse entire buffer + /// @return buffer_base&, Useful for method chaining + /// + inline buffer& reverse(void) + { TT::reverse(iv_data); return *this; } + + + ///@} + + /// @name Buffer Manipulation Functions + ///@{ + + /// + /// @brief Get a pointer to the buffer bits + /// @return Pointer to the buffer itself + /// + inline T* pointer(void) { return &iv_data; } + + // 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 + inline buffer<T>& operator>>(bits_type i_shiftnum); +#endif + + /// + /// @brief operator<<() + /// +#ifdef DOXYGEN + inline buffer<T>& operator<<(bits_type i_shiftnum); +#endif + + /// + /// @brief operator+() + /// +#ifdef DOXYGEN + inline buffer<T>& operator+(const T& rhs); +#endif + + /// + /// @brief operator+=() + /// +#ifdef DOXYGEN + inline buffer<T>& operator+=(const T& rhs); +#endif + + /// + /// @brief operator|=() + /// +#ifdef DOXYGEN + inline buffer<T>& operator|=(const T& rhs); +#endif + + /// + /// @brief operator&=() + /// +#ifdef DOXYGEN + inline buffer<T>& operator&=(const T& rhs); +#endif + + /// + /// @brief operator|() + /// +#ifdef DOXYGEN + inline buffer<T>& operator|(const T& rhs); +#endif + + /// + /// @brief operator&() + /// +#ifdef DOXYGEN + inline buffer<T>& operator&(const T& rhs); +#endif + + /// + /// @brief operator^=() + /// +#ifdef DOXYGEN + inline buffer<T>& operator^=(const T& rhs); +#endif + + /// + /// @brief operator~() + /// +#ifdef DOXYGEN + inline buffer<T>& operator~(const T& rhs) const; +#endif + + /// + /// @brief operator==() + /// +#ifdef DOXYGEN + inline bool operator==(const T& rhs) const; +#endif + + /// + /// @brief operator!=() + /// +#ifdef DOXYGEN + inline 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 - 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 + /// @return buffer& Useful for method chaining + /// + template<bits_type TS, bits_type L, bits_type SS = 0, typename OT> + inline buffer& 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"); + + // 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>(iv_data); + + 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); + + // 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; + + // 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 *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<typename OT> + 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<T>::bit_length(); + const bits_type source_length = parameterTraits<OT>::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<uint64_t>(i_datain); + const uint64_t target = static_cast<uint64_t>(iv_data); + + const bits_type source_start = parameterTraits<uint64_t>::bit_length - (source_length - i_sourceStart); + const bits_type target_start = parameterTraits<uint64_t>::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<uint64_t>::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 + /// @tparam L Length of bits to insert + /// @tparam OT the type of the incoming (origin) data + /// @param[in] i_datain OT value to copy into DataBuffer + /// - data is taken right aligned + /// @return buffer& Useful for method chaining + /// @note Data is assumed to be aligned on the word boundary of L + /// + template<bits_type TS, bits_type L, typename OT> + inline buffer& 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 *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<typename OT> + 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<T>::bit_length()) + { + FAPI_ERR("insertFromRight(): (Target Start + Len) is out of bounds"); + return FAPI2_RC_INVALID_PARAMETER; + } + + if (i_targetStart >= parameterTraits<T>::bit_length()) + { + FAPI_ERR("insertFromRight(): Target Start is out of bounds"); + return FAPI2_RC_INVALID_PARAMETER; + } + + if (i_len > parameterTraits<OT>::bit_length()) + { + FAPI_ERR("insertFromRight(): Len > input buffer"); + return FAPI2_RC_INVALID_PARAMETER; + } + + return this->insert(i_datain, i_targetStart, i_len, parameterTraits<OT>::bit_length() - i_len); + } + + /// + /// @brief Copy data from this buffer into an OT + /// @tparam SS Start bit in source + /// @tparam L Length of bits to insert + /// @tparam TS Start bit to insert into (target start) + /// @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 + /// + template<bits_type SS, bits_type L, bits_type TS = 0, typename OT> + inline buffer& extract(OT& o_out) + { + // Extraction is just an insert into o_out + + buffer<OT> out(o_out); + out.insert<TS, L, SS>(iv_data); + o_out = out; + 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 in source + /// @param[in] Length of bits to extract + /// @param[in] Start bit to insert into (target start) + /// @return FAPI2_RC_SUCCESS if ok + /// + template<typename OT> + fapi2::ReturnCode extract(OT& o_out, const bits_type i_sourceStart, + const bits_type i_len, const bits_type i_targetStart = 0) + { + // Extraction is just an insert into o_out + + buffer<OT> 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) + /// @tparam L Length of bits to extract + /// @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 + /// + template<bits_type SS, bits_type L, typename OT> + inline buffer& extractToRight(OT& o_out) + { + extract<SS, L, parameterTraits<OT>::bit_length() - L>(o_out); + 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<typename OT> + fapi2::ReturnCode extractToRight(OT& o_out, const bits_type i_sourceStart, + const bits_type i_len) + { + return extract(o_out, i_sourceStart, i_len, parameterTraits<OT>::bit_length() - i_len); + } + + ///@} + + private: + /// The contents of the buffer + T iv_data; + }; +} + +#endif diff --git a/hwpf/plat/include/buffer_traits.H b/hwpf/plat/include/buffer_traits.H index 08073fb6..8f42ce9e 100644 --- a/hwpf/plat/include/buffer_traits.H +++ b/hwpf/plat/include/buffer_traits.H @@ -35,17 +35,22 @@ #include <algorithm> #include <buffer_parameters.H> -#ifdef __FAPI2_DEBUG__ -// for debug printing ... can be removed for flight +#ifdef FAPI2_DEBUG #include <iostream> #endif + +#if !defined(DOXYGEN) && defined(FAPI2_DEBUG) #include <iterator> +#endif 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; @@ -59,8 +64,8 @@ namespace fapi2 class bufferTraits { public: -#ifndef DOXYGEN -#ifdef __FAPI2_DEBUG__ + +#if !defined(DOXYGEN) && defined(FAPI2_DEBUG) /// /// @brief Print a container of bits /// @param[in] i_data the container of bits @@ -75,7 +80,6 @@ namespace fapi2 << std::dec << std::endl; } #endif -#endif /// /// @brief Return the size of the buffer in E units @@ -141,7 +145,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; } }; // @@ -153,8 +158,7 @@ namespace fapi2 class bufferTraits<bits_container, uint32_t> { public: -#ifndef DOXYGEN -#ifdef __FAPI2_DEBUG__ +#if !defined(DOXYGEN) && defined(FAPI2_DEBUG) /// /// @brief Print a container of bits /// @param[in] i_data the container of bits @@ -167,7 +171,6 @@ namespace fapi2 std::cout << std::dec << std::endl; } #endif -#endif /// /// @brief Return the size of the buffer in E units @@ -228,10 +231,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/hwpf/plat/include/fapi2.H b/hwpf/plat/include/fapi2.H index c6197284..a3dd4fbe 100644 --- a/hwpf/plat/include/fapi2.H +++ b/hwpf/plat/include/fapi2.H @@ -27,11 +27,11 @@ #include <utils.H> + // In turn includes the needed generated headers (hwp_ffd_classes, etc.) #include <error_scope.H> #include <set_sbe_error.H> // Generated file -#include <fapi2PlatAttributeService.H> -#include <fapi2AttributeIds.H> // Generated file +#include <plat_attributes.H> #include <hwp_executor.H> diff --git a/hwpf/plat/include/fapi2AttributeService.H b/hwpf/plat/include/fapi2AttributeService.H new file mode 100644 index 00000000..ab49c9ab --- /dev/null +++ b/hwpf/plat/include/fapi2AttributeService.H @@ -0,0 +1,127 @@ +/// +/// @file fapi2AttributeService.H +/// +/// @brief Defines the FAPI_ATTR_GET and FAPI_ATTR_SET macros that a user +/// calls to get/set attributes and a check function that the macros use to +/// verify correct usage +/// + +#ifndef FAPI2ATTRIBUTESERVICE_H_ +#define FAPI2ATTRIBUTESERVICE_H_ +#include <stdint.h> +//#include <attribute_ids.H> +#include <fapi2AttributeIds.H> +#include <target.H> +#include <target_types.H> +//#include <plat_attribute_service.H> +#include <fapi2PlatAttributeService.H> + +/// @brief Macros called by user to get/set attributes for FAPI2 targets +/// +/// Code must have a reference to a FAPI2 Target and an attribute ID (from +/// XML file): +/// fapi2::ReturnCode l_rc; +/// fapi2::Target<target type>& l_target = ????; +/// Ex: Target<TARGET_TYPE_PROC_CHIP>& l_target = ????; +/// +/// To get a copy of an integer attribute and set the attribute +/// uint64_t l_val = 0; +/// l_rc = FAPI_ATTR_GET(<ID>, l_target, l_val); +/// l_rc = FAPI_ATTR_SET(<ID>, l_target, l_val); +/// +/// To get a copy of an integer array attribute and set the attribute +/// uint32_t l_pVal[4] = {0}; +/// l_rc = FAPI_ATTR_GET(<ID>, l_target, l_pVal); +/// l_rc = FAPI_ATTR_SET(<ID>, l_target, l_pVal); +/// +/// A priveleged attribute is one that a HWP should not generally access, +/// examples include ATTR_NAME and ATTR_EC, where usage can lead to a non +/// data-driven design. A privileged attribute can be accessed with +/// FAPI_ATTR_GET_PRIVILEGED and FAPI_ATTR_SET_PRIVILEGED +/// +/// The non-PRIVILEGED macros first call a template function (compiler will +/// optimize out) that will cause a compile failure if the attribute is +/// privileged, they then call a PRIVILEGED macro to get/set the attribute +/// +/// The PRIVILEGED macros call a template function (compiler will optimize out) +/// that will cause a compile failure if the ID is not valid or VAL is not the +/// correct type. +// + +#define FAPI_ATTR_GET(ID, TARGET, VAL) \ + (fapi2::failIfPrivileged<ID##_Privileged>(), \ + fapi2::checkIdType<ID##_Type>(ID, VAL), \ + ID##_GETMACRO(ID, TARGET, VAL)) + +#define FAPI_ATTR_SET(ID, TARGET, VAL) \ + (fapi2::failIfPrivileged<ID##_Privileged>(), \ + fapi2::checkIdType<ID##_Type>(ID, VAL), \ + ID##_SETMACRO(ID, TARGET, VAL)) + +#define FAPI_ATTR_GET_PRIVILEGED(ID, TARGET, VAL) \ + (fapi2::checkIdType<ID##_Type>(ID, VAL), \ + ID##_GETMACRO(ID, TARGET, VAL)) + +#define FAPI_ATTR_SET_PRIVILEGED(ID, TARGET, VAL) \ + (fapi2::checkIdType<ID##_Type>(ID, VAL), \ + ID##_SETMACRO(ID, TARGET, VAL)) + +namespace fapi2 +{ + +/// +/// @brief Get an InitFile attribute for FAPI2 +/// +/// This function gets a copy of an attribute. In the case of an array attribute, +/// The value in the specified index is retrieved. This should be used by the +/// InitFile HWP only, that HWP processes a binary InitFile and therefore needs +/// to read a variable ID of a variable data type. Standard HWPs should use the +/// FAPI2_ATTR_GET macro which automatically checks the type for correct usage. +/// +/// If there are ever attributes with more than 4 dimensions then this function +/// will need to be updated. +/// +/// @Tparam K template parameter, passed in target. +/// @param[in] i_id AttributeID +/// @param[in] i_target Reference to fapi2::Target (can be NULL for system) +/// @param[out] o_val Reference to uint64_t where attribute value is set +/// @param[in] i_arrayIndex1 If array attribute then index1 +/// @param[in] i_arrayIndex2 If at least 2D array attribute then index2 +/// @param[in] i_arrayIndex3 If at least 3D array attribute then index3 +/// @param[in] i_arrayIndex4 If at least 4D array attribute then index4 +/// +/// @return ReturnCode. Zero if success +/// +template< TargetType K > +ReturnCode getInitFileAttr(const AttributeId i_id, + const Target<K>& i_target, + uint64_t & o_val, + const uint32_t i_arrayIndex1 = 0, + const uint32_t i_arrayIndex2 = 0, + const uint32_t i_arrayIndex3 = 0, + const uint32_t i_arrayIndex4 = 0); + +/** + * @brief Check the ID and TYPE + * + * This is called by FAPI code to check at compile time that a FAPI attribute + * access is using the correct data type and a valid AttributeId + */ +template<typename T> inline void checkIdType(AttributeId, T &) {} + +/** + * @brief Fail if attribute privileged + * + * This is called by FAPI code to check at compile time that a standard FAPI + * attribute access (FAPI_ATTR_GET) is not accessing a privileged attribute + */ +class ErrorAccessingPrivilegedAttribute; +template<const bool PRIVILEGED> void failIfPrivileged() +{ + ErrorAccessingPrivilegedAttribute(); +} +template <> inline void failIfPrivileged<false>() {} + +} + +#endif // FAPI2ATTRIBUTESERVICE_H_ diff --git a/hwpf/plat/include/fapi2_hw_access.H b/hwpf/plat/include/fapi2_hw_access.H new file mode 100644 index 00000000..44a592f8 --- /dev/null +++ b/hwpf/plat/include/fapi2_hw_access.H @@ -0,0 +1,464 @@ +/* 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 fapi2_hw_access.H +/// @brief Common file that defines the hardware access functions that +/// platform code must implement. +/// + +#ifndef _FAPI2_COMMON_HWACCESS_H_ +#define _FAPI2_COMMON_HWACCESS_H_ + +#ifdef FAPI_SUPPORT_SPY_AS_ENUM +#include <spy_ids.H> +typedef uint64_t spyId_t; +#endif + +#include <stdint.h> +//#include <thread> +#include <buffer.H> + +// variable_buffer isn't supported on PPE +#ifndef __PPE__ +#include <variable_buffer.H> +#endif + +#include <return_code.H> +#include <target.H> +#include <hw_access_def.H> +#include <plat_hw_access.H> + +#ifdef FAPI_SUPPORT_MULTI_SCOM +#include <multi_scom.H> +#endif + +namespace fapi2 +{ + //-------------------------------------------------------------------------- + // PIB Error Functions + //-------------------------------------------------------------------------- + + /// @brief Sets the PIB error mask - platform dependant + /// @param[in] i_mask The new error mask + inline void setPIBErrorMask(uint8_t i_mask); + + /// @brief Gets the PIB error mask - platform dependant + /// @return uint8_t The current PIB error mask + inline uint8_t getPIBErrorMask(void); + + //-------------------------------------------------------------------------- + // Operational Mode Error Functions + //-------------------------------------------------------------------------- + + /// @brief Sets the operational mode + /// @param[in] i_mode The new mode + inline void setOpMode(const OpModes i_mode); + + /// @brief Gets the operational mode + /// @return the operational mode + inline OpModes getOpMode(void); + + //-------------------------------------------------------------------------- + // HW Communication Functions + //-------------------------------------------------------------------------- + + /// @brief Reads a SCOM register from a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to read from. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline void getScom(const Target<K>& i_target, const uint64_t i_address, + buffer<uint64_t>& o_data); + + /// @brief Writes a SCOM register on a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to write to. + /// @param[in] i_data Buffer that holds data to write into address. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline void putScom(const Target<K>& i_target, const uint64_t i_address, + const buffer<uint64_t> i_data); + + /// @brief Writes a SCOM register under mask on a chip + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address SCOM register address to write to. + /// @param[in] i_data Buffer that holds data to write into address. + /// @param[in] i_mask Buffer that holds the mask value. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline void putScomUnderMask(const Target<K>& i_target, + const uint64_t i_address, + const buffer<uint64_t> i_data, + const buffer<uint64_t> i_mask); + + /// @brief Reads a CFAM register from a chip. + /// CFAM register is 32-bit wide. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address CFAM register address to read from. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode getCfamRegister(const Target<K>& i_target, + const uint32_t i_address, + buffer<uint32_t>& o_data); + + /// @brief Writes a CFAM register on a chip. + /// CFAM register is 32-bit wide. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address CFAM register address to write to. + /// @param[in] i_data Buffer that holds data to write into address. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putCfamRegister(const Target<K>& i_target, + const uint32_t i_address, + const buffer<uint32_t> i_data); + + /// @brief Read-modify-write a CFAM register on a chip. + /// CFAM register is 32-bit wide. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target HW target to operate on. + /// @param[in] i_address CFAM register address to modify. + /// @param[in] i_data Buffer that holds data to be modified. + /// @param[in] i_modifyMode The modify mode (or/and/xor). + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode modifyCfamRegister(const Target<K>& i_target, + const uint32_t i_address, + const buffer<uint32_t> i_data, + const ChipOpModifyMode i_modifyMode); + + // variable_buffer isn't supported on PPE +#ifndef __PPE__ + /// @brief Reads a ring from a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to read from. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode getRing(const Target<K>& i_target, + const scanRingId_t i_address, + variable_buffer& o_data, + const RingMode i_ringMode = 0); + + /// @brief Writes a ring to a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to write to. + /// @param[in] i_data Buffer that contains RS4 compressed ring data + /// to write into address + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode putRing(const Target<K>& i_target, + const scanRingId_t i_address, + const variable_buffer& i_data, + const RingMode i_ringMode = 0); + + + /// @brief Read-modify-write a ring on a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_address Ring address to modify. + /// @param[in] i_data Buffer that contains RS4 compressed ring data + /// to be modified. + /// @param[in] i_modifyMode The modify mode (or/and/xor) + /// @param[in] i_ringMode Ring operation mode. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + template< TargetType K > + inline ReturnCode modifyRing(const Target<K>& i_target, + const scanRingId_t i_address, + const variable_buffer& i_data, + const ChipOpModifyMode i_modifyMode, + const RingMode i_ringMode = 0); +#endif + +#ifdef FAPI_SUPPORT_MULTI_SCOM + /// @brief Performs a multiple SCOM operation + /// This interface performs multiple SCOM operations on a chip in the + /// order specified by the input MultiScom object. + /// See fapiMultiScom.H for details of how to populate the MultiScom + /// object with SCOM operations. + /// + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in,out] io_multiScomObj Reference to a MultiScom object, + /// pre-populated with SingleScomInfo entries + /// to perform multiple SCOMs on input target + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note This is a synchronous interface and would return after all the + /// SCOM operations are completed or on the first failed operation + /// + /// @note SCOMs will be performed in the order they were added to the + /// input MultiScom object + /// + /// @note In case of errors, the platform code is responsible to collect + /// and add all the required error info and FFDC into the error data + /// for debugging + /// + /// @note If the SCOM operations added are specific to a processor chip, + /// then the FSI Shift Engine configured in scatter-gather DMA mode + /// extension would be used to execute the SCOM operations in a + /// performance optimize mode. In this mode, the special + /// SCOM_BULK_READ_MODE and SCOM_BULK_WRITE_MODE operations are + /// supported that allow a large bulk of SCOM access (in multiple of + /// 64 bits) for targets that support auto-increment. The + /// SCOM_WRITE_UNDER_MASK operation is not supported in this mode + /// + /// @note If the SCOM operations added are specific to a memory buffer + /// chip, then the regular SCOM engine is used to execute the SCOM + /// operations. SCOM_WRITE_UNDER_MASK operation is supported in + /// this mode, but the special SCOM_BULK_READ_MODE and + /// SCOM_BULK_WRITE_MODE operations are not supported due to + /// hardware limitations. + /// + template< TargetType K > + fapi2::ReturnCode multiScom (const Target<K>& i_target, + MultiScom& io_multiScomObj); +#endif + + // -------------------------------------------------------------------------- + // NOTE: + // Implement platform Spy access functions if platform supports them. + // -------------------------------------------------------------------------- + + // variable_buffer isn't supported on PPE +#ifndef __PPE__ + /// @brief Reads a spy from a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_spyId Id of the spy whose data to be read. + /// @param[out] o_data Buffer that holds data read from HW target. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependant on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// 1. if the spy name contains a # procedure writers should replace + /// it with an __P__ for example - + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// becomes + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// 2. if the spy name has a number following a "." it must have an + /// underscore prepended to the number. + /// + /// EH.TPCHIP.2KX100_ARY_CLK_EDGES_DLY + /// becomes + /// EH.TPCHIP._2KX100_ARY_CLK_EDGES_DLY + /// + /// Example SPY name: + /// The hardware procedure should call the function like: + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// fapi2::ReturnCode rc = fapiGetSpy( targ, + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS, data ); + /// + /// @note The ID is not in quotes the fapi code will handle adding + /// the quotes for the cronus environment +#if defined(FAPI_SUPPORT_SPY_AS_ENUM) || defined(DOXYGEN) + +#define FAPI_GET_SPY(TARGET, ID, DATA) fapi2::getSpy(TARGET, FAPI_SPY_NAMES::ID.value, DATA) + + template< TargetType K > + inline ReturnCode getSpy(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& o_data); +#endif + +#if defined(FAPI_SUPPORT_SPY_AS_STRING) || defined(DOXYGEN) + +#define FAPI_GET_SPY(TARGET, ID, DATA) fapi2::getSpy(TARGET, #ID, DATA) + + template< TargetType K > + inline ReturnCode getSpy(const Target<K>& i_target, + const char * const i_spyId, + variable_buffer& o_data); +#endif + + /// @brief Writes a spy on a chip. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_spyId Id of the spy to write data to. + /// @param[out] i_data Buffer that holds data to write into spy. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependent on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// 1. if the spy name contains a # procedure writers should replace + /// is with an __P__ for example - + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// becomes + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// 2. if the spy name has a number following a "." it must have an + /// underscore prepended to the number. + /// + /// EH.TPCHIP.2KX100_ARY_CLK_EDGES_DLY + /// becomes + /// EH.TPCHIP._2KX100_ARY_CLK_EDGES_DLY + /// + /// Example SPY name: + /// The hardware procedure should call the function like: + /// + /// ABUS.RX0.RXPACKS#0.RXPACK.RD.LC.LC.ACT_DIS + /// + /// fapi2::ReturnCode rc = fapiPutSpy( targ, + /// ABUS.RX0.RXPACKS__P__0.RXPACK.RD.LC.LC.ACT_DIS, data ); + /// + /// @note The ID is not in quotes the fapi code will handle adding + /// the quotes for the cronus environment + /// +#if defined(FAPI_SUPPORT_SPY_AS_ENUM) || defined(DOXYGEN) + +#define FAPI_PUT_SPY(TARGET, ID, DATA) fapi2::putSpy(TARGET, FAPI_SPY_NAMES::ID.value, DATA) + + template< TargetType K > + inline ReturnCode putSpy(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& i_data); +#endif + +#if defined(FAPI_SUPPORT_SPY_AS_STRING) || defined(DOXYGEN) + +#define FAPI_PUT_SPY(TARGET, ID, DATA) fapi2::putSpy(TARGET, #ID, DATA) + + template< TargetType K > + inline ReturnCode putSpy(const Target<K>& i_target, + const char* const i_spyId, + variable_buffer& i_data); +#endif + + /// @brief Writes spy data into a buffer holding ring data image + /// This API is used by L2/L3 repair to put column repair data + /// into a ring buffer image. + /// @tparam K template parameter, passed in target. + /// @param[in] i_target Target to operate on. + /// @param[in] i_spyId Id of the spy. + /// @param[in] i_data Buffer that holds spy data to write into ring + /// image. + /// @param[out] o_data Buffer that holds updated ring image. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependent on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// See fapiPutSpy for details on spy id specifics. + /// +#if defined(FAPI_SUPPORT_SPY_AS_ENUM) || defined(DOXYGEN) + +#define FAPI_PUT_SPY_IMAGE(TARGET, ID, DATA1, DATA2) \ + fapi2::putSpyImage(TARGET, FAPI_SPY_NAMES::ID.value, \ + DATA1, DATA2) + + template< TargetType K > + inline ReturnCode putSpyImage(const Target<K>& i_target, + const spyId_t i_spyId, + const variable_buffer& i_data, + variable_buffer& o_imageData); +#endif + +#if defined(FAPI_SUPPORT_SPY_AS_STRING) || defined(DOXYGEN) + +#define FAPI_PUT_SPY_IMAGE(TARGET, ID, DATA1, DATA2) \ + fapi2::putSpyImage(TARGET, #ID, DATA1,DATA2) + + template< TargetType K > + inline ReturnCode putSpyImage(const Target<K>& i_target, + const char* const i_spyId, + const variable_buffer& i_data, + variable_buffer& o_imageData); +#endif + + /// @brief Reads spy data from a ring image buffer + /// @param[in] i_target Target to operate on + /// @param[in] i_spyId The spy's id + /// @param[out] o_data Buffer that holds data read from ring image. + /// @param[in] i_imageData Buffer that holds ring image to read data + /// from. + /// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. + /// + /// @note: The string version is only supported for cronus. + /// + /// The fapi design to support both FSP and cronus use of get and + /// put spy functions is dependent on the SPY names being expanded + /// to resemble a valid C identifier. This design places some + /// restrictions on the SPY names which can be used. + /// + /// See fapiPutSpy for details on spy id specifics. + /// +#if defined(FAPI_SUPPORT_SPY_AS_ENUM) || defined(DOXYGEN) + +#define FAPI_GET_SPY_IMAGE(TARGET, ID, DATA1, DATA2) \ + fapi2:getSpyImage(TARGET, FAPI_SPY_NAMES::ID.value, \ + DATA1, DATA2) + + template< TargetType K > + inline ReturnCode getSpyImage(const Target<K>& i_target, + const spyId_t i_spyId, + variable_buffer& o_data, + const variable_buffer& i_imageData); +#endif + +#if defined(FAPI_SUPPORT_SPY_AS_STRING) || defined(DOXYGEN) + +#define FAPI_GET_SPY_IMAGE(TARGET, ID, DATA1, DATA2) \ + fapi2::getSpyImage(TARGET, #ID, DATA1,DATA2) + + template< TargetType K > + inline ReturnCode getSpyImage(const Target<K>& i_target, + const char * const i_spyId, + variable_buffer& o_data, + const variable_buffer& i_imageData); +#endif + +#endif // PPE +}; + +#endif // _FAPI2_HWACCESS_H_ diff --git a/hwpf/plat/include/fapi2_target.H b/hwpf/plat/include/fapi2_target.H new file mode 100644 index 00000000..5c753e9e --- /dev/null +++ b/hwpf/plat/include/fapi2_target.H @@ -0,0 +1,496 @@ +/// +/// @file fapi2_target.H +/// @brief Common definitions for fapi2 targets +/// + +#ifndef __FAPI2_COMMON_TARGET__ +#define __FAPI2_COMMON_TARGET__ + +#include <stdint.h> +#include <vector> +#include <target_types.H> +#include <target_states.H> +#include <plat_target.H> + +namespace fapi2 +{ + /// + /// @brief Class representing a FAPI2 Target + /// @tparam K the type (Kind) of target + /// @tparam V the type of the target's Value + /// @remark TargetLite targets are uint64_t, Targets + /// are uintptr_t (void*). + /// + /// Assuming there are representations of a processor, + /// a membuf and a system here are some examples: + /// @code + /// #define PROCESSOR_CHIP_A 0xFFFF0000 + /// #define MEMBUF_CHIP_B 0x0000FFFF + /// #define SYSTEM_C 0x0000AAAA + /// @endcode + /// + /// * To define a target: + /// @code + /// fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> A(PROCESSOR_CHIP_A); + /// fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> C(SYSTEM_C); + /// fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> B(MEMBUF_CHIP_B); + /// @endcode + /// + /// * Functions which take composite target types + /// @code + /// void takesProcOrMembuf( + /// const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP | + /// fapi2::TARGET_TYPE_MEMBUF_CHIP>& V ); + /// + /// void takesAny(const fapi2::Target<fapi2::TARGET_TYPE_ALL>& V ); + /// + /// @endcode + /// + /// * Traversing the target "tree" + /// @code + /// fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> A(PROCESSOR_CHIP_A); + /// + /// // Get A's parent + /// A.getParent<fapi2::TARGET_TYPE_SYSTEM>(); + /// + /// // Get the 0x53'd core + /// fapi2::getTarget<fapi2::TARGET_TYPE_CORE>(0x53); + /// + /// // Get all *my* present/functional children which are cores + /// A.getChildren<fapi2::TARGET_TYPE_CORE>(); + /// + /// // Get all of the the cores relative to my base target + /// fapi2::getChildren<fapi2::TARGET_TYPE_CORE>(); + /// @endcode + /// + /// * Invalid casts + /// @code + /// // Can't cast to a specialized target + /// fapi2::Target<fapi2::TARGET_TYPE_NONE> D(MEMBUF_CHIP_B); + /// takesProcOrMembuf( D ); + /// + /// // Not one of the shared types + /// fapi2::Target<fapi2::TARGET_TYPE_ABUS_ENDPOINT> E; + /// takesProcOrMembuf( E ); + /// @endcode + template<TargetType K, typename V = plat_target_handle_t> + class Target + { + public: + + /// + /// @brief Create a Target, with a value + /// @param[in] Value the value (i.e., specific element this + /// target represents, or pointer) + /// @note Platforms can mangle the value and K to get a + /// single uint64_t in value which represents all the information + /// they might need. value( K | V ), for example + /// + Target(V Value); + +// Target(V Value): +// iv_handle(Value) +// {} + + /// + /// @brief Assignment Operator. + /// @param[in] i_right Reference to Target to assign from. + /// @return Reference to 'this' Target + /// + Target& operator=(const Target& i_right); + + /// + /// @brief Equality Comparison Operator + /// @param[in] i_right Reference to Target to compare. + /// @return bool. True if equal. + /// @note Platforms need to define this so that the physical + /// targets are determined to be equivilent rather than just the handles + /// + bool operator==(const Target& i_right) const; + + /// + /// @brief Inquality Comparison Operator + /// @param[in] i_right Reference to Target to compare. + /// @return bool. True if not equal. + /// @note Platforms need to define this so that the physical + /// targets are determined to be equivilent rather than just the handles + /// + bool operator!=(const Target& i_right) const; + + /// + /// @brief Get the handle. + /// @return V The target's handle, or value + /// + V get(void) const + { + return this->iv_handle.value; + } + + /// + /// @brief Get the handle as a V + /// @return V The target's handle, or value + /// + inline operator V() const + { + return this->iv_handle.value; + } + + /// + /// @brief Get a target's value + /// @return V The target's handle, or value + /// + inline V& operator()(void) + { + return this->iv_handle.value; + } + + /// + /// @brief Get the target type + /// @return The type of target represented by this target + /// + inline TargetType getType(void) const + { + return iv_type; + } + +#ifdef __PPE__ + + /// Need to optimize PPE Target resoulution in a cheap manner + /// Brian: not sure if the this is the place for this as + /// this is plaform specific. + + /// + /// @brief Get address overlay to reduce runtime processing + /// @return Overlay as a type V + /// + inline V getAddressOverlay(void) const + { + return this->iv_handle.fields.address_overlay; + } + + /// + /// @brief Get address overlay to reduce runtime processing + /// @return Overlay as a type V + /// + inline uint32_t getTargetNumber(void) const + { + return static_cast<uint32_t>(this->iv_handle.fields.type_target_num); + } +#endif + + /// + /// @brief Get this target's immediate parent + /// @tparam T The type of the parent + /// @return Target<T> a target representing the parent + /// + template< TargetType T > + inline Target<T> getParent(void) const; + + /// + /// @brief Is this target a chip? + /// @return Return true if this target is a chip, false otherwise + /// + inline constexpr bool isChip(void) const + { +// return ( (K == TARGET_TYPE_PROC_CHIP) || +// (K == TARGET_TYPE_MEMBUF_CHIP) ); + + return ( (K == TARGET_TYPE_PROC_CHIP) ); + } + + /// + /// @brief Is this target a chiplet? + /// @return Return true if this target is a chiplet, false otherwise + /// + inline constexpr bool isChiplet(void) const + { + return ( (K == TARGET_TYPE_EX) || +// (K == TARGET_TYPE_MBA) || + (K == TARGET_TYPE_MCS) || +// (K == TARGET_TYPE_XBUS) || +// (K == TARGET_TYPE_ABUS) || +// (K == TARGET_TYPE_L4) || + (K == TARGET_TYPE_CORE) || + (K == TARGET_TYPE_EQ) || +// (K == TARGET_TYPE_MCA) || +// (K == TARGET_TYPE_MCBIST) || +// (K == TARGET_TYPE_MI) || +// (K == TARGET_TYPE_DMI) || +// (K == TARGET_TYPE_OBUS) || +// (K == TARGET_TYPE_NV) || +// (K == TARGET_TYPE_SBE) || +// (K == TARGET_TYPE_PPE) || +// (K == TARGET_TYPE_PERV) || + (K == TARGET_TYPE_PERV) ); +// (K == TARGET_TYPE_PEC) || +// (K == TARGET_TYPE_PHB) ); + } + + /// + /// @brief Get this target's children + /// @tparam T The type of the parent + /// @param[in] i_state The desired TargetState of the children + /// @return std::vector<Target<T> > a vector of present/functional + /// children + /// @warning The children of EX's (cores) are expected to be returned + /// in order. That is, core 0 is std::vector[0]. + /// + template< TargetType T> + inline std::vector<Target<T> > + getChildren(const TargetState i_state = TARGET_STATE_FUNCTIONAL) const; + + /// + /// @brief Get the target at the other end of a bus - dimm included + /// @tparam T The type of the parent + /// @param[in] i_state The desired TargetState of the children + /// @return Target<T> a target representing the thing on the other end + /// @note Can be easily changed to a vector if needed + /// + template<TargetType T> + inline Target<T> + getOtherEnd(const TargetState i_state = TARGET_STATE_FUNCTIONAL) const; + + /// + /// @brief Copy from a Target<O> to a Target<K> + /// @tparam O the target type of the other + /// + template<TargetType O> + inline Target( const Target<O>& Other ): + Target<K, V>(Other.get()) + { + // In case of recursion depth failure, use -ftemplate-depth= + static_assert( (K & O) != 0, + "unable to cast Target, no shared types"); + + static_assert( bitCount<K>::count >= bitCount<O>::count, + "unable to cast to specialized Target"); + } + + private: + // Don't use enums here as it makes it hard to assign + // in the platform target cast constructor. + static const TargetType iv_type = K; + + union iv_handle { + V value; + struct { +#ifdef _BIG_ENDIAN + V chiplet_num : 8; + V type_target_num : 8; + V type : 8; + V _reserved_b6 : 6; + V present : 1; + V functional : 1; + V address_overlay : 32; +#else + V address_overlay : 32; + V functional : 1; + V present : 1; + V _reserved_b6 : 6; + V type : 8; + V type_target_num : 8; + V chiplet_num : 8; +#endif + } fields; + // Union Constructor +// iv_handle(V i_value = 0):value(i_value) {} + } iv_handle; + }; + + // EX threads map to CORE threads: + // t0 / t2 / t4 / t6 fused = t0 / t1 / t2 / t3 normal (c0) + // t1 / t3 / t5 / t7 fused = t0 / t1 / t2 / t3 normal (c1) + // So when splitting the EX, we need to map from EX threads + // to CORE threads. + + /// + /// @brief Given a normal core thread id, translate this to + /// a fused core thread id. (normal to fused) + /// @param[in] the ordinal number of the normal core this thread belongs to + /// @param[in] a normal core thread id - 0, ..., 3 + /// @return the fused core thread id + /// + inline uint8_t thread_id_n2f(const uint8_t i_ordinal, const uint8_t i_thread_id) + { + return (i_thread_id << 1) | i_ordinal; + } + + /// + /// @brief Given a fused core thread id, translate this to + /// a normal core thread id. (fused to normal) + /// @param[in] a fused core thread id - 0, ..., 7 + /// @return the normal core thread id + /// + inline uint8_t thread_id_f2n(const uint8_t i_thread_id) + { + return i_thread_id >> 1; + } + + /// + /// @brief Given a normal core thread id, translate this to a + /// normal core bitset. + /// @param[in] a normal core thread id - 0, ..., 3 + /// @return the normal core bitset + /// @note to got from a fused core id to a normal core bitset, + /// translate from a fused core thread id first. + /// + inline uint8_t thread_id2bitset(const uint8_t i_thread_id) + { + // 0xff means "set all bits" + static const uint8_t all_threads = 0xff; + static const uint8_t all_normal_threads_bitset = 0x0f; + + if (i_thread_id == all_threads) + { + return all_normal_threads_bitset; + } + + // A thread_id is really just bit index. + return (1 << (4 - i_thread_id - 1)); + } + + /// + /// @brief Given a bitset of normal core thread ids, translate this to + /// a bit mask of fused core thread id. (normal to fused) + /// @param[in] the ordinal number of the normal core this thread belongs to + /// @param[in] a normal core thread bitset - b0000, ..., b1111 + /// @return the corresponding fused core bitset + /// + inline uint8_t thread_bitset_n2f(const uint8_t i_ordinal, const uint8_t i_threads) + { + // Since we only have 4 bits I think this is better than a shift-type solution + // for interleaving bits + static uint8_t core_map[] = { + 0b00000000, // b0000 + 0b00000010, // b0001 + 0b00001000, // b0010 + 0b00001010, // b0011 + 0b00100000, // b0100 + 0b00100010, // b0101 + 0b00101000, // b0110 + 0b00101010, // b0111 + 0b10000000, // b1000 + 0b10000010, // b1001 + 0b10001000, // b1010 + 0b10001010, // b1011 + 0b10100000, // b1100 + 0b10100010, // b1101 + 0b10101000, // b1110 + 0b10101010, // b1111 + }; + + return core_map[i_threads] >> i_ordinal; + } + + /// + /// @brief Given a fused core thread bitset, translate this to + /// a normal core thread bitset. (fused to normal) + /// @param[in] the ordinal number of the normal core this thread belongs to + /// @param[in] a fused core thread bitset - b00000000, ..., b11111111 + /// @return the corresponding normal core bitset + /// + inline uint8_t thread_bitset_f2n(const uint8_t i_ordinal, const uint8_t i_threads) + { + uint8_t normal_set = 0; + + // core 0 is the left-most bit in the pair + uint8_t pair_mask = (i_ordinal == 0) ? 0x2 : 0x1; + + // For each bit which can be set in the normal core bit_set ... + for( auto i = 0; i <= 3; ++i ) + { + // ... grab the two fused bits which represent it ... + // ... and mask off the bit in the pair which represents this normal core ... + // (the << 1 shifts the masks over as we walk the pairs of bits) + uint8_t bits = (((3 << (i << 1)) & i_threads) & (pair_mask << (i << 1))); + + // ... if either bit is set, set the corresponding bit in + // the normal core bitset. + normal_set |= (bits != 0) << i; + } + return normal_set; + } + + /// + /// @brief Return the string interpretation of this target + /// @tparam T The type of the target + /// @param[in] i_target Target<T> + /// @param[in] i_buffer buffer to write in to + /// @param[in] i_bsize size of the buffer + /// @return void + /// @post The contents of the buffer is replaced with the string + /// representation of the target + /// + template< TargetType T > + inline void toString(const Target<T>& i_target, char* i_buffer, size_t i_bsize); + + /// + /// @brief Return the string interpretation of this target + /// @tparam T The type of the target + /// @tparam B The type of the buffer + /// @param[in] A pointer to the Target<T> + /// @param[in] i_buffer buffer to write in to + /// @param[in] i_bsize size of the buffer + /// @return void + /// @post The contents of the buffer is replaced with the string + /// representation of the target + /// + template< TargetType T > + inline void toString(const Target<T>* i_target, char* i_buffer, size_t i_bsize); + + /// + /// @brief Get an enumerated target of a specific type + /// @tparam T The type of the target + /// @param[in] Ordinal representing the ordinal number of + /// the desired target + /// @return Target<T> the target requested + /// + template<TargetType T> + inline Target<T> getTarget(uint64_t Ordinal); + + // Why has the been removed? For starters, the API name + // is probably wrong as it's already been confused with + // Target::getChildren(). And if I'm going to change it + // I really want to see if we need it. I'm still not + // clear on whether we're alloing this traversal or not. +#if 0 + /// + /// @brief Get the base target's children + /// @tparam T The type of the target + /// @return std::vector<Target<T> > a vector of present/functional + /// children + /// + template<TargetType T> + inline std::vector<Target<T> > getChildren() + { + // For testing + return {Target<T>(), Target<T>()}; + } +#endif + + /// + /// @brief Return the string interpretation of this target + /// @tparam T The type of the target + /// @tparam B The type of the buffer + /// @param[in] i_target Target<T> + /// @param[in] i_buffer buffer + /// @return void + /// @post The contents of the buffer is replaced with the string + /// representation of the target + /// + template<TargetType T, typename B> + inline void toString(const Target<T>& i_target, B& i_buffer); + + /// + /// @brief Check if the target is of a type, or in a type subset. + /// @tparam K the TargetType to check + /// @tparam T TargetType or TargetType composite to check against + /// @return True, iff K is a proper T + /// + template< TargetType K, TargetType T > + inline constexpr bool is_same(void) + { return (K & T) != 0; } + + +} +#endif diff --git a/hwpf/plat/include/hw_access.H b/hwpf/plat/include/hw_access.H index 591eab27..12da736b 100644 --- a/hwpf/plat/include/hw_access.H +++ b/hwpf/plat/include/hw_access.H @@ -38,6 +38,7 @@ #include <variable_buffer.H> #endif +#include <utils.H> #include <plat_hw_access.H> #include <fapi2_hw_access.H> @@ -102,11 +103,7 @@ namespace fapi2 inline void getScom(const Target<K>& i_target, const uint64_t i_address, buffer<uint64_t>& o_data) { - // PLAT_GETSCOM(i_target, -// (uint32_t)(i_address & BITS(40,24)), -// &(o_data())); - -// fapi2::ReturnCode l_rc; + PLAT_GETSCOM(current_err, i_target, (uint32_t)(i_address & BITS(40,24)), @@ -122,12 +119,13 @@ namespace fapi2 /// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. template< TargetType K > inline void putScom(const Target<K>& i_target, const uint64_t i_address, - buffer<uint64_t>& i_data) + buffer<uint64_t> i_data) { - PLAT_PUTSCOM(i_target, + PLAT_PUTSCOM(current_err, + i_target, (uint32_t)(i_address & BITS(40,24)), - &(i_data())); + i_data()); } /// @brief Read-modify-write a SCOM register on a chip @@ -140,12 +138,13 @@ namespace fapi2 template< TargetType K > inline void modifyScom( const Target<K>& i_target, const uint64_t i_address, - const buffer<uint64_t>& i_data, + const buffer<uint64_t> i_data, const ChipOpModifyMode i_modifyMode) { fapi2::buffer<uint64_t> l_modifyDataBuffer; - PLAT_GETSCOM(i_target, + PLAT_GETSCOM(current_err, + i_target, (uint32_t)(i_address & BITS(40,24)), &(l_modifyDataBuffer())); @@ -164,9 +163,10 @@ namespace fapi2 l_modifyDataBuffer ^= i_data; } - PLAT_PUTSCOM(i_target, + PLAT_PUTSCOM(current_err, + i_target, (uint32_t)(i_address & BITS(40,24)), - &(l_modifyDataBuffer())); + l_modifyDataBuffer()); return; } @@ -180,16 +180,17 @@ namespace fapi2 template< TargetType K > inline void putScomUnderMask(const Target<K>& i_target, const uint64_t i_address, - buffer<uint64_t>& i_data, - buffer<uint64_t>& i_mask) + buffer<uint64_t> i_data, + buffer<uint64_t> i_mask) { fapi2::buffer<uint64_t> l_modifyDataBuffer = i_data; l_modifyDataBuffer &= i_mask; - PLAT_PUTSCOM(i_target, + PLAT_PUTSCOM(current_err, + i_target, (uint32_t)(i_address & BITS(40,24)), - &(l_modifyDataBuffer())); + l_modifyDataBuffer()); return; } diff --git a/hwpf/plat/include/plat_attributes.H b/hwpf/plat/include/plat_attributes.H new file mode 100644 index 00000000..2a55b221 --- /dev/null +++ b/hwpf/plat/include/plat_attributes.H @@ -0,0 +1,36 @@ +/* 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 plat_attributes.H + * @brief Platform specific attribute headers + */ + +#ifndef __PLAT_ATTTRIBUTE_H__ +#define __PLAT_ATTTRIBUTE_H__ + +#include <fapi2AttributeService.H> +#include <fapi2AttributeIds.H> // Generated file + +#endif // __PLAT_ATTTRIBUTE_H__ diff --git a/hwpf/plat/include/plat_error_scope.H b/hwpf/plat/include/plat_error_scope.H new file mode 100644 index 00000000..a2de6bd5 --- /dev/null +++ b/hwpf/plat/include/plat_error_scope.H @@ -0,0 +1,65 @@ +/* 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 plat_error_scope.H + * @brief platform definitions which create a scope for automatic error handling + */ + +#ifndef __FAPI2_PLAT_ERROR_SCOPE__ +#define __FAPI2_PLAT_ERROR_SCOPE__ + +/// @cond +#define PLAT_FAPI_TRY_NO_TRACE( __operation__ ) \ + (__operation__) + +#define PLAT_FAPI_TRY_TRACE( __operation__, ... ) \ + FAPI_DBG(__VA_ARGS)); \ + (__operation__) + +/// +/// @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 PLAT_FAPI_ASSERT( __conditional__, __ffdc__, ... ) \ + if (! (__conditional__)) \ + { \ + (__ffdc__).execute(); \ + FAPI_ERR(__VA_ARGS__); \ + goto fapi_try_exit; \ + } + + +/// +/// @brief Temporary macro for error label until all are removed. +/// @todo REMOVE this in time. +#define FAPI_CLEANUP() \ +fapi_try_exit: +/// @endcond + +#endif diff --git a/hwpf/plat/include/plat_hw_access.H b/hwpf/plat/include/plat_hw_access.H index 9bfccfcc..7d8e3c86 100644 --- a/hwpf/plat/include/plat_hw_access.H +++ b/hwpf/plat/include/plat_hw_access.H @@ -51,8 +51,8 @@ asm volatile \ PPE_LVDX(_m_base.getAddressOverlay(), (uint32_t)(_m_offset & BITS(40,24)), _m_data) /// PutScom -#define PLAT_PUTSCOM(_m_base, _m_offset, _m_data) \ - PPE_STVDX(_m_rc, _m_base.getAddressOverlay(), (uint32_t)(_m_offset & BITS(40,24)), _m_data) +#define PLAT_PUTSCOM(_m_rc, _m_base, _m_offset, _m_data) \ + PPE_STVDX(_m_base.getAddressOverlay(), (uint32_t)(_m_offset & BITS(40,24)), _m_data) /// ModifyScom #define PLAT_MODSCOM(_m_base, _m_offset, _m_data, _m_mode) \ diff --git a/hwpf/plat/include/plat_trace.H b/hwpf/plat/include/plat_trace.H index 9104e767..423ef6ea 100644 --- a/hwpf/plat/include/plat_trace.H +++ b/hwpf/plat/include/plat_trace.H @@ -38,6 +38,15 @@ #include <stdio.h> #include <stdint.h> +// @todo update these headers with extern "C" in a future commit +// or not and leave this just as it is. +extern "C" +{ +#include "pk.h" +#include <pk_trace.h> +#include "trac_interface.h" +} + // Why not a #define, why is this in the fapi2 namespace? // To prevent problems with Cronus and the fapi1 definitions. namespace fapi2 @@ -47,9 +56,16 @@ namespace fapi2 // Information traces (go into fast trace buffer that can wrap often) #define FAPI_TRACE(_id_, _fmt_, _args_...) \ - printf("%s: %s:%d ", _id_, __func__, __LINE__); \ - printf(_fmt_, ##_args_); \ - printf("\n") + PK_TRACE(_fmt_, ##_args_); + + +/* The following is a desirous trace entry but the second line has a + compilation issue that is unresolved + +#define FAPI_TRACE(_id_, _fmt_, _args_...) \ + PK_TRACE("%s: %s:%d ", _id_, __FUNCTION__, __LINE__); \ + PK_TRACE(_fmt_, ##_args_); +*/ #define FAPI_INF(_fmt_, _args_...) FAPI_TRACE("inf", _fmt_, ##_args_) diff --git a/hwpf/plat/include/return_code.H b/hwpf/plat/include/return_code.H new file mode 100644 index 00000000..fd2f7c29 --- /dev/null +++ b/hwpf/plat/include/return_code.H @@ -0,0 +1,108 @@ +/* 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 return_code.H + * @brief definitions for fapi2 return codes + */ + +#ifndef __FAPI2_RETURN_CODE__ +#define __FAPI2_RETURN_CODE__ + +#include <stdint.h> +#include <return_code_defs.H> + +#ifndef FAPI2_NO_FFDC + #include <ffdc.H> +#endif + +namespace fapi2 +{ + /// + /// @brief Class representing a FAPI2 ReturnCode + /// + // Remove the inheritance relationship with FirstFailureData if + // the platform doesn't support FFDC. +#ifdef FAPI2_NO_FFDC + class ReturnCode +#else + class ReturnCode : public FirstFailureData<ReturnCode> +#endif + { + public: + + /// + /// @brief Constructor. + /// @param[in] i_rc the rc to set + /// + ReturnCode(const uint64_t i_rc = FAPI2_RC_SUCCESS): + iv_rc(i_rc) + {}; + + /// + /// @brief integral type conversion function. Returns the error code + /// @return The error code + /// + inline operator uint64_t() const { return iv_rc; } + + /// + /// @brief Returns true iff iv_rc == SUCCESS + /// @return true or false + /// + inline operator bool() const { return iv_rc == FAPI2_RC_SUCCESS; } + + /// + /// @brief Assignement operator + /// +#ifdef DOXYGEN + inline ReturnCode& operator=(const uint64_t& rhs) + inline ReturnCode& operator=(const ReturnCodes& rhs) +#endif + + inline bool operator==(const uint64_t& rhs) const + { return rhs == iv_rc; } + + inline bool operator==(const ReturnCodes& rhs) const + { return rhs == iv_rc; } + + inline bool operator!=(const uint64_t& rhs) const + { return rhs != iv_rc; } + + inline bool operator!=(const ReturnCodes& rhs) const + { return rhs != iv_rc; } + + private: + uint64_t iv_rc; + }; + + /// This implementation assumes no exception handling and leverages thread-local + /// storage. For platforms without thread support, a global variable will + /// suffice for the error state. +// extern thread_local ReturnCode current_err; /// the current error state + extern ReturnCode current_err; /// the current error state + 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/hwpf/plat/include/target.H b/hwpf/plat/include/target.H index 0d7832b5..e2fe550b 100644 --- a/hwpf/plat/include/target.H +++ b/hwpf/plat/include/target.H @@ -24,530 +24,281 @@ /* IBM_PROLOG_END_TAG */ /** * @file target.H - * @brief definitions for fapi2 targets + * @brief platform specializations for fapi2 targets */ #ifndef __FAPI2_TARGET__ #define __FAPI2_TARGET__ -#include <stdint.h> -//#include <vector> -#include <target_types.H> +#include <plat_target.H> +#include <plat_target_parms.H> +#include <fapi2_target.H> #include <utils.H> -#include "plat_target_parms.H" - -#define MC_ENABLE 0x1 << 6 -#define MC_WRITE 5 -#define MC_READ_OR 0 -#define MC_READ_AND 1 - -#define EX_ADDRESS_MASK 0x0000FF00 - -#ifdef __ASSEMBLER__ - -#ifndef ULL -#define ULL(x) x -#endif - -#else - -#ifndef ULL -#define ULL(x) x##ull - -#endif - -#endif // __ASSEMBLER - -/// Create a multi-bit mask of \a n bits starting at bit \a b -#define BITS(b, n) ((ULL(0xffffffffffffffff) << (64 - (n))) >> (b)) - -/// Create a single bit mask at bit \a b -#define BIT(b) BITS((b), 1) - +#include <stdio.h> namespace fapi2 -{ - /// - /// @brief Class representing a FAPI2 Target - /// @tparam K the type (Kind) of target - /// @tparam V the type of the target's Value - /// @remark TargetLite targets are uint64_t, Targets - /// are uintptr_t (void*). - /// - /// Assuming there are representations of a processor, - /// a membuf and a system here are some examples: - /// @code - /// #define PROCESSOR_CHIP_A 0xFFFF0000 - /// #define MEMBUF_CHIP_B 0x0000FFFF - /// #define SYSTEM_C 0x0000AAAA - /// @endcode - /// - /// * To define a target: - /// @code - /// fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> A(PROCESSOR_CHIP_A); - /// fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> C(SYSTEM_C); - /// fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> B(MEMBUF_CHIP_B); - /// @endcode - /// - /// * Functions which take composite target types - /// @code - /// void takesProcOrMembuf( - /// const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP | - /// fapi2::TARGET_TYPE_MEMBUF_CHIP>& V ); - /// - /// void takesAny(const fapi2::Target<fapi2::TARGET_TYPE_ALL>& V ); +{ + /// @brief Create a Target, with a value + /// @param[in] Value the value (i.e., specific element this + /// target represents, or pointer) + /// @note Platforms can mangle the value and K to get a + /// single uint64_t in value which represents all the information + /// they might need. value( K | V ), for example /// - /// @endcode - /// - /// * Traversing the target "tree" - /// @code - /// fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> A(PROCESSOR_CHIP_A); - /// - /// // Get A's parent - /// A.getParent<fapi2::TARGET_TYPE_SYSTEM>(); - /// - /// // Get the 0x53'd core - /// fapi2::getTarget<fapi2::TARGET_TYPE_CORE>(0x53); - /// - /// // Get all *my* present/functional children which are cores - /// A.getChildren<fapi2::TARGET_TYPE_CORE>(); - /// - /// // Get all of the the cores relative to my base target - /// fapi2::getChildren<fapi2::TARGET_TYPE_CORE>(); - /// @endcode - /// - /// * Invalid casts - /// @code - /// // Can't cast to a specialized target - /// fapi2::Target<fapi2::TARGET_TYPE_NONE> D(MEMBUF_CHIP_B); - /// takesProcOrMembuf( D ); - /// - /// // Not one of the shared types - /// fapi2::Target<fapi2::TARGET_TYPE_ABUS_ENDPOINT> E; - /// takesProcOrMembuf( E ); - /// @endcode - template<TargetType K, typename V = uint64_t> - class Target + template<TargetType K, typename V> + Target<K, V>::Target(V Value) { - public: - - /// - /// @brief Create a Target, with a value - /// @param[in] V the value (i.e., specific element this - /// target represents, or pointer) - /// @note Platforms can mangle the value and K to get a - /// single uint64_t in value which represents all the information - /// they might need. value( K | V ), for example - /// + static_assert( ((K == TARGET_TYPE_CORE) & + (K == TARGET_TYPE_EQ) ) != true, + "TARGET_TYPE_CORE and TARGET_TYPE_EQ cannot be specified at the same time"); - /// Default constructor is basically a TARGET_TYPE_ALL - Target() + this->iv_handle.value = 0; + if(K & TARGET_TYPE_PROC_CHIP) { - this->iv_handle.fields.chiplet_num = 0; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; + this->iv_handle.fields.chiplet_num = Value; + this->iv_handle.fields.type = TARGET_TYPE_PROC_CHIP; + this->iv_handle.fields.type_target_num = Value; // TODO: check this } - - Target( V Value ) - { - static_assert( ((K == TARGET_TYPE_CORE) & - (K == TARGET_TYPE_EQ) ) != true, - "TARGET_TYPE_CORE and TARGET_TYPE_EQ cannot be specified at the same time"); - - if(K & TARGET_TYPE_PROC_CHIP) - { - this->iv_handle.fields.chiplet_num = Value; - this->iv_handle.fields.type = TARGET_TYPE_PROC_CHIP; - this->iv_handle.fields.type_target_num = Value; // TODO: check this -// this->iv_address.fields.chiplet_num = Value; - } - - if(K & TARGET_TYPE_PERV) - { - this->iv_handle.fields.chiplet_num = Value; - this->iv_handle.fields.type = TARGET_TYPE_PERV | TARGET_TYPE_PROC_CHIP; - this->iv_handle.fields.type_target_num = Value; // TODO: check this -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - - if(K & TARGET_TYPE_CORE) - { - /* - if (Value > CORE_CHIPLET_COUNT) - { - PK_TRACE("Chiplet number is greater than CORE_CHIPLET_COUNT"); - return -1; - } - */ - this->iv_handle.fields.chiplet_num = Value + CORE_CHIPLET_OFFSET; - this->iv_handle.fields.type = TARGET_TYPE_CORE; - this->iv_handle.fields.type_target_num = Value; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - if(K & TARGET_TYPE_EQ) - { - this->iv_handle.fields.chiplet_num = Value + EQ_CHIPLET_OFFSET; - this->iv_handle.fields.type = TARGET_TYPE_EQ; - this->iv_handle.fields.type_target_num = Value; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - - if(K & TARGET_TYPE_EX) - { - - this->iv_handle.fields.chiplet_num = (Value / 2) + EX_CHIPLET_OFFSET; - this->iv_handle.fields.type = TARGET_TYPE_EX; - this->iv_handle.fields.type_target_num = Value; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - - if(K & TARGET_TYPE_EQ_MC_WRITE) - { - this->iv_handle.fields.chiplet_num = - (((MC_ENABLE) | - ((MC_WRITE << 3) | (Value & 0x07))) & - BITS(57,7)); - this->iv_handle.fields.type = TARGET_TYPE_EQ_MC_WRITE; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - - if(K & TARGET_TYPE_EQ_MC_READOR) - { - this->iv_handle.fields.chiplet_num = - (((MC_ENABLE) | - ((MC_READ_OR << 3) | (Value & 0x07))) & - BITS(57,7)); - this->iv_handle.fields.type = TARGET_TYPE_EQ_MC_READOR; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - - if(K & TARGET_TYPE_EQ_MC_READAND) - { - this->iv_handle.fields.chiplet_num = - (((MC_ENABLE) | - ((MC_READ_AND << 3) | (Value & 0x07))) & - BITS(57,7)); - this->iv_handle.fields.type = TARGET_TYPE_EQ_MC_READAND; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - - if(K & TARGET_TYPE_CORE_MC_WRITE) - { - this->iv_handle.fields.chiplet_num = - (((MC_ENABLE) | - ((MC_WRITE << 3) | (Value & 0x07))) & - BITS(57,7)); - this->iv_handle.fields.type = TARGET_TYPE_CORE_MC_WRITE; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - - if(K & TARGET_TYPE_CORE_MC_READOR) - { - this->iv_handle.fields.chiplet_num = - (((MC_ENABLE) | - ((MC_READ_OR << 3) | (Value & 0x07))) & - BITS(57,7)); - this->iv_handle.fields.type = TARGET_TYPE_CORE_MC_READOR; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - - if(K & TARGET_TYPE_CORE_MC_READAND) - { - this->iv_handle.fields.chiplet_num = - (((MC_ENABLE) | - ((MC_READ_AND << 3) | (Value & 0x07))) & - BITS(57,7)); - this->iv_handle.fields.type = TARGET_TYPE_CORE_MC_READAND; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - - if(K == TARGET_TYPE_ALL) - { - this->iv_handle.fields.chiplet_num = Value; - this->iv_handle.fields.type = TARGET_TYPE_ALL; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; - } - -// if(K == TARGET_TYPE_ADDRESS) -// { -// this->iv_handle.fields.chiplet_num = Value; -// this->iv_address.fields.chiplet_num = this->iv_handle.fields.chiplet_num; -// } - } - - /// - /// @brief Assignment Operator. - /// @param[in] i_right Reference to Target to assign from. - /// @return Reference to 'this' Target - /// - Target<K,V>& operator=(const Target<K,V>& i_right) + if(K & TARGET_TYPE_PERV) { - this->iv_handle.value = i_right->iv_handle.value; - this->iv_addresss.value = i_right->iv_address.value; - return *this; - } - - /// - /// @brief Equality Comparison Operator - /// @param[in] i_right Reference to Target to compare. - /// @return bool. True if equal. - /// - bool operator==(const Target<K,V>& i_right) const - { - if (this->iv_handle.value == i_right->iv_handle.value) - return true; - else - return false; - } - /// - /// @brief Inquality Comparison Operator - /// @param[in] i_right Reference to Target to compare. - /// @return bool. True if equal. - /// - bool operator!=(const Target<K,V>& i_right) const - { - if (this->iv_handle.value != i_right->iv_handle.value) - return true; - else - return false; + this->iv_handle.fields.chiplet_num = Value; + this->iv_handle.fields.type = TARGET_TYPE_PERV | TARGET_TYPE_PROC_CHIP; + this->iv_handle.fields.type_target_num = Value; // TODO: check this } - /// - /// @brief Get the handle. - /// @return V The target's handle, or value - /// - V get(void) const - { - return this->iv_handle.value; - } - - /// - /// @brief Get the handle as a V - /// @return V The target's handle, or value - /// - operator V() const + if(K & TARGET_TYPE_CORE) { - return this->iv_handle.value; - } - - /// - /// @brief Get a target's value - /// @return V The target's handle, or value - /// - V& operator()(void) - { - return *this->iv_handle; + /* + if (Value > CORE_CHIPLET_COUNT) + { + PK_TRACE("Chiplet number is greater than CORE_CHIPLET_COUNT"); + return -1; + } + */ + this->iv_handle.fields.chiplet_num = Value + CORE_CHIPLET_OFFSET; + this->iv_handle.fields.type = TARGET_TYPE_CORE; + this->iv_handle.fields.type_target_num = Value; } - /// - /// @brief Get the target type - /// @return The type of target represented by this target - /// - TargetType getType(void) const + if(K & TARGET_TYPE_EQ) { - return (TargetType)this->iv_handle.fields.type; + this->iv_handle.fields.chiplet_num = Value + EQ_CHIPLET_OFFSET; + this->iv_handle.fields.type = TARGET_TYPE_EQ; + this->iv_handle.fields.type_target_num = Value; } - /// - /// @brief Get address overlay to reduce runtime processing - /// @return Overlay as a type V - /// - V getAddressOverlay(void) const - { - return this->iv_handle.fields.address_overlay; + if(K & TARGET_TYPE_EX) + { + + this->iv_handle.fields.chiplet_num = (Value / 2) + EX_CHIPLET_OFFSET; + this->iv_handle.fields.type = TARGET_TYPE_EX; + this->iv_handle.fields.type_target_num = Value; + this->iv_handle.fields.present = 1; } +// if(K & TARGET_TYPE_EQ_MC_WRITE) +// { +// this->iv_handle.fields.chiplet_num = +// (((MC_ENABLE) | +// ((MC_WRITE << 3) | (Value & 0x07))) & +// BITS(57,7)); +// this->iv_handle.fields.type = TARGET_TYPE_EQ_MC_WRITE; +// } +// +// if(K & TARGET_TYPE_EQ_MC_READOR) +// { +// this->iv_handle.fields.chiplet_num = +// (((MC_ENABLE) | +// ((MC_READ_OR << 3) | (Value & 0x07))) & +// BITS(57,7)); +// this->iv_handle.fields.type = TARGET_TYPE_EQ_MC_READOR; +// } +// +// if(K & TARGET_TYPE_EQ_MC_READAND) +// { +// this->iv_handle.fields.chiplet_num = +// (((MC_ENABLE) | +// ((MC_READ_AND << 3) | (Value & 0x07))) & +// BITS(57,7)); +// this->iv_handle.fields.type = TARGET_TYPE_EQ_MC_READAND; +// } +// +// if(K & TARGET_TYPE_CORE_MC_WRITE) +// { +// this->iv_handle.fields.chiplet_num = +// (((MC_ENABLE) | +// ((MC_WRITE << 3) | (Value & 0x07))) & +// BITS(57,7)); +// this->iv_handle.fields.type = TARGET_TYPE_CORE_MC_WRITE; +// } +// +// if(K & TARGET_TYPE_CORE_MC_READOR) +// { +// this->iv_handle.fields.chiplet_num = +// (((MC_ENABLE) | +// ((MC_READ_OR << 3) | (Value & 0x07))) & +// BITS(57,7)); +// this->iv_handle.fields.type = TARGET_TYPE_CORE_MC_READOR; +// } +// +// if(K & TARGET_TYPE_CORE_MC_READAND) +// { +// this->iv_handle.fields.chiplet_num = +// (((MC_ENABLE) | +// ((MC_READ_AND << 3) | (Value & 0x07))) & +// BITS(57,7)); +// this->iv_handle.fields.type = TARGET_TYPE_CORE_MC_READAND; +// } -#if 0 - /// - /// @brief Get this target's immediate parent - /// @tparam T The type of the parent - /// @return Target<T> a target representing the parent - /// - template<TargetType T> - Target<T,V> getParent(void) const - { - static_assert((T & ~(TARGET_TYPE_PROC_CHIP | TARGET_TYPE_PERV) != 0), - "Only TARGET_TYPE_PROC_CHIP and TARGET_TYPE_PERV parent types supported"); - - static_assert( ((((T & TARGET_TYPE_PROC_CHIP) == 0) & - (T & TARGET_TYPE_PERV ) == 0) ), - "Either TARGET_TYPE_PROC_CHIP or TARGET_TYPE_PERV parent type must be specified"); - } - - /// - /// @brief Get this target's children - /// @tparam T The type of the parent - /// @return std::vector<Target<T> > a vector of present/functional - /// children - /// - template< TargetType T> - std::vector<Target<T,V> > getChildren(void) const - { - static_assert( ((T & ~TARGET_TYPE_PROC_CHIP) != 0 ) != true, - "Only TARGET_TYPE_CHIP and TARGET_TYPE_EQ child types supported"); - - if(K & TARGET_TYPE_PROC_CHIP) - { - std::vector<Target<T,V> chip_children(CHIPLET_COUNT); - for (int i = 0; i < CHIPLET_COUNT; i++) - { - if (this->iv_handle.fields.type == TARGET_TYPE_PROC_CHIP & - this->iv_handle.fields.present = 1 & - this->iv_handle.fields.functional = 1 ) - { - chip_children.push_back(this->iv_handle) - } - } - return chip_children; - } - - if(K & TARGET_TYPE_PERV) - { - this->iv_handle.fields.chiplet_num = Value; - // this->iv_handle.fields.type_perv = 1; - this->iv_handle.fields.type_target_num = 0; - } + if(K == TARGET_TYPE_ALL) + { + this->iv_handle.fields.chiplet_num = Value; + this->iv_handle.fields.type = TARGET_TYPE_ALL; + } + this->iv_handle.fields.present = 1; + this->iv_handle.fields.address_overlay = + this->iv_handle.fields.chiplet_num << 24; + + } - } + /// + /// @brief Assignment Operator. + /// @param[in] i_right Reference to Target to assign from. + /// @return Reference to 'this' Target + /// + template<TargetType K, typename V> + Target<K, V>& Target<K, V>::operator=(const Target& i_right) + { + this->iv_handle.value = i_right->iv_handle.value; + return *this; + } + /// + /// @brief Equality Comparison Operator + /// @param[in] i_right Reference to Target to compare. + /// @return bool. True if equal. + /// @note Platforms need to define this so that the physical + /// targets are determined to be equivilent rather than just the handles + /// + template<TargetType K, typename V> + bool Target<K, V>::operator==(const Target& i_right) const + { + if (this->iv_handle.value == i_right->iv_handle.value) + return true; + else + return false; + } - /// - /// @brief Get the target at the other end of a bus - dimm included - /// @tparam T The type of the parent - /// @return Target<T> a target representing the thing on the other end - /// @note Can be easily changed to a vector if needed - /// - template<TargetType T> - Target<T,K> getOtherEnd(void) const - { - static_assert( false, "getOtherEnd() is not supported on PPE platforms"); - } -#endif + /// + /// @brief Inquality Comparison Operator + /// @param[in] i_right Reference to Target to compare. + /// @return bool. True if not equal. + /// @note Platforms need to define this so that the physical + /// targets are determined to be equivilent rather than just the handles + /// + template<TargetType K, typename V> + bool Target<K, V>::operator!=(const Target& i_right) const + { + if (this->iv_handle.value != i_right->iv_handle.value) + return true; + else + return false; + } - /// - /// @brief Copy from a Target<O> to a Target<K> - /// @tparam O the target type of the other - /// - template<TargetType O> - Target<K,V>( const Target<O>& Other ): - Target<K,V>(Other.get()) - { - static_assert( (K & O) != 0, - "unable to cast Target, no shared types"); + /// + /// @brief Get this target's immediate parent + /// @tparam T The type of the parent + /// @return Target<T> a target representing the parent + /// + template<TargetType K, typename V> + template<TargetType T> + inline Target<T> Target<K, V>::getParent(void) const + { + return this->iv_handle.value; + } - static_assert( bitCount<K>::count >= bitCount<O>::count, - "unable to cast to specialized Target"); - } + /// + /// @brief Get this target's children + /// @tparam T The type of the parent + /// @param[in] i_state The desired TargetState of the children + /// @return std::vector<Target<T> > a vector of present/functional + /// children + /// @warning The children of EX's (cores) are expected to be returned + /// in order. That is, core 0 is std::vector[0]. + /// + template<TargetType K, typename V> + template< TargetType T> + inline std::vector<Target<T> > + Target<K, V>::getChildren(const TargetState i_state) const + { + // To keep the compiler quiet about unused variables + static_cast<void>(i_state); + // For testing + return {Target<T>(), Target<T>()}; + } - private: + /// + /// @brief Get the target at the other end of a bus - dimm included + /// @tparam T The type of the parent + /// @param[in] i_state The desired TargetState of the children + /// @return Target<T> a target representing the thing on the other end + /// @note Can be easily changed to a vector if needed + /// + template<TargetType K, typename V> + template<TargetType T> + inline Target<T> + Target<K, V>::getOtherEnd(const TargetState i_state) const + { +// static_assert( false, "getOtherEnd() is not supported on PPE platforms"); + } -// union { -// V value; -// struct { -// #ifdef _BIG_ENDIAN -// V chiplet_num : 8; -// V _reserved_b24 : 24; -// #else -// V _reserved_b24 : 24; -// V chiplet_num : 8; -// #endif -// } fields; -// -// } iv_address; -// - union { - V value; - struct { -#ifdef _BIG_ENDIAN - V chiplet_num : 8; - V type_target_num : 8; - V type : 8; - V _reserved_b6 : 6; - V present : 1; - V functional : 1; - V address_overlay : 32; -#else - V address_overlay : 32; - V functional : 1; - V present : 1; - V _reserved_b6 : 6; - V type : 8; - V type_target_num : 8; - V chiplet_num : 8; -#endif - } fields; - } iv_handle ; - -// uint64_t iv_present_children; -// uint64_t iv_functional_children; - }; - + /// + /// @brief Return the string interpretation of this target + /// @tparam T The type of the target + /// @param[in] i_target Target<T> + /// @param[in] i_buffer buffer to write in to + /// @param[in] i_bsize size of the buffer + /// @return void + /// @post The contents of the buffer is replaced with the string + /// representation of the target + /// + template< TargetType T > + inline void toString(const Target<T>& i_target, char* i_buffer, size_t i_bsize) + { + snprintf(i_buffer, i_bsize, "Target 0x%lx/0x%x", i_target.get(), T); + } -#if 0 /// /// @brief Return the string interpretation of this target /// @tparam T The type of the target /// @tparam B The type of the buffer - /// @param[in] The Target<T> - /// @param[in] The buffer + /// @param[in] A pointer to the Target<T> + /// @param[in] i_buffer buffer to write in to + /// @param[in] i_bsize size of the buffer /// @return void /// @post The contents of the buffer is replaced with the string /// representation of the target /// - template<TargetType T, typename B> - void toString(const Target<T>& i_target, B& i_buffer) + template< TargetType T > + inline void toString(const Target<T>* i_target, char* i_buffer, size_t i_bsize) { - static_assert( false, "toString is not supported on PPE platforms"); + snprintf(i_buffer, i_bsize, "Target 0x%lx/0x%x", i_target->get(), T); } /// /// @brief Get an enumerated target of a specific type /// @tparam T The type of the target - /// @param[in] uint64_t representing the ordinal number of + /// @param[in] Ordinal representing the ordinal number of /// the desired target /// @return Target<T> the target requested /// template<TargetType T> - Target<T> getTarget(uint64_t Ordinal) + inline Target<T> getTarget(uint64_t Ordinal) { // For testing return Target<T>(Ordinal); } -#endif - // Why has the been removed? For starters, the API name - // is probably wrong as it's already been confused with - // Target::getChildren(). And if I'm going to change it - // I really want to see if we need it. I'm still not - // clear on whether we're alloing this traversal or not. -#if 0 - /// - /// @brief Get the base target's children - /// @tparam T The type of the target - /// @return std::vector<Target<T> > a vector of present/functional - /// children - /// - template<TargetType T> - std::vector<Target<T> > getChildren() - { - // For testing - return {Target<T>(), Target<T>()}; - } -#endif - - /// - /// @brief Check if the target is of a type, or in a type subset. - /// @tparam K the TargetType to check - /// @tparam T TargetType or TargetType composite to check against - /// @return True, iff K is a proper T - /// - template< TargetType K, TargetType T > - constexpr bool is_same(void) - { return (K & T) != 0; } - - - +} -}; -//#include "plat_ppe_targets_hold.H" #endif diff --git a/hwpf/plat/include/target_types.H b/hwpf/plat/include/target_types.H index 19465982..4db4cf26 100644 --- a/hwpf/plat/include/target_types.H +++ b/hwpf/plat/include/target_types.H @@ -94,8 +94,6 @@ namespace fapi2 // TARGET_TYPE_CME_CORE1 = 0x80000000, ///< CME Core1 (CME only) // TARGET_TYPE_ADDRESS = 0xAAAAAAAA, ///< Address Overlay Type // TARGET_TYPE_ALL = 0xFFFFFFFF, ///< Any/All types - }; - // Mappings to target types found in the error xml files TARGET_TYPE_EX_CHIPLET = TARGET_TYPE_EX, diff --git a/hwpf/plat/include/utils.H b/hwpf/plat/include/utils.H index 8a86e2ed..216656c8 100644 --- a/hwpf/plat/include/utils.H +++ b/hwpf/plat/include/utils.H @@ -52,5 +52,20 @@ /// Create a single bit mask at bit \a b #define BIT(b) BITS((b), 1) +#ifdef _BIG_ENDIAN + +#define revle16(x) x +#define revle32(x) x +#define revle64(x) x + +#else + +uint16_t revle16(uint16_t i_x); +uint32_t revle32(uint32_t i_x); +uint64_t revle64(uint64_t i_x); + +#endif + + #endif // FAPI2_UTILS_H_ diff --git a/hwpf/plat/src/fapi2ppefiles.mk b/hwpf/plat/src/fapi2ppefiles.mk index debd93f5..1f913872 100644 --- a/hwpf/plat/src/fapi2ppefiles.mk +++ b/hwpf/plat/src/fapi2ppefiles.mk @@ -19,6 +19,8 @@ FAPI2-C-SOURCES += fapi2PlatAttributeService.C +FAPI2-C-SOURCES += plat_utils.C + FAPI2-S-SOURCES = diff --git a/hwpf/plat/src/plat_utils.C b/hwpf/plat/src/plat_utils.C index bc23c4b5..18aa4444 100644 --- a/hwpf/plat/src/plat_utils.C +++ b/hwpf/plat/src/plat_utils.C @@ -1,3 +1,4 @@ + /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ @@ -28,6 +29,8 @@ #include <stdint.h> #include <plat_trace.H> #include <return_code.H> + +#ifndef __PPE__ #include <error_info.H> namespace fapi2 @@ -74,7 +77,7 @@ namespace fapi2 (*i)->iv_procedure, (*i)->iv_calloutPriority); } - FAPI_DBG("busCallouts: %lu", ei->iv_busCallouts.size()); +e FAPI_DBG("busCallouts: %lu", ei->iv_busCallouts.size()); for( auto i = ei->iv_busCallouts.begin(); i != ei->iv_busCallouts.end(); ++i ) { @@ -133,3 +136,77 @@ namespace fapi2 return FAPI2_RC_SUCCESS; } }; + + +/// Byte-reverse a 16-bit integer if on a little-endian machine + +uint16_t +revle16(uint16_t i_x) +{ + uint16_t rx; + +#ifndef _BIG_ENDIAN + uint8_t *pix = (uint8_t*)(&i_x); + uint8_t *prx = (uint8_t*)(&rx); + + prx[0] = pix[1]; + prx[1] = pix[0]; +#else + rx = i_x; +#endif + + return rx; +} + +#endif + +/// Byte-reverse a 32-bit integer if on a little-endian machine + +uint32_t +revle32(uint32_t i_x) +{ + uint32_t rx; + +#ifndef _BIG_ENDIAN + uint8_t *pix = (uint8_t*)(&i_x); + uint8_t *prx = (uint8_t*)(&rx); + + prx[0] = pix[3]; + prx[1] = pix[2]; + prx[2] = pix[1]; + prx[3] = pix[0]; +#else + rx = i_x; +#endif + + return rx; +} + + +/// Byte-reverse a 64-bit integer if on a little-endian machine + +uint64_t +revle64(const uint64_t i_x) +{ + uint64_t rx; + +#ifndef _BIG_ENDIAN + uint8_t *pix = (uint8_t*)(&i_x); + uint8_t *prx = (uint8_t*)(&rx); + + prx[0] = pix[7]; + prx[1] = pix[6]; + prx[2] = pix[5]; + prx[3] = pix[4]; + prx[4] = pix[3]; + prx[5] = pix[2]; + prx[6] = pix[1]; + prx[7] = pix[0]; +#else + rx = i_x; +#endif + + return rx; +} + + |