diff options
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H')
-rw-r--r-- | src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H | 291 |
1 files changed, 227 insertions, 64 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H index c4b1e82c5..6c9ad087c 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,6 +46,8 @@ // mss lib #include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> +#include <lib/utils/conversions.H> +#include <lib/freq/sync.H> namespace mss { @@ -60,6 +62,50 @@ enum class loading : size_t IS_3DS, }; +enum freq_select : uint8_t +{ + BIN_DOWN, ///< option to bin down frequency + HIGHEST_COMMON ///< option to find highest common freq w/o bin down - useful for testing +}; + +/// +/// @brief Returns the iterator if a given freq is found +/// @tparam T the freq_select type +/// @param[in] i_supported_freqs a vector of sorted frequences +/// @param[im] i_dimm_freq current dimm speed +/// @return FAPI2_RC_SUCESS iff okay +/// +template< freq_select T > +static inline std::vector<uint32_t>::const_iterator search_list( const std::vector<uint32_t>& i_supported_freqs, + const uint32_t i_dimm_freq); + +/// +/// @brief Returns the iterator if a given freq is found - BIN_DOWN specialization +/// @param[in] i_supported_freqs a vector of sorted frequences +/// @param[in] i_dimm_freq current dimm speed +/// @return FAPI2_RC_SUCESS iff okay +/// +template< > +inline std::vector<uint32_t>::const_iterator search_list<BIN_DOWN>( const std::vector<uint32_t>& i_supported_freqs, + const uint32_t i_dimm_freq) +{ + return std::lower_bound(i_supported_freqs.begin(), i_supported_freqs.end(), i_dimm_freq); +} + +/// +/// @brief Returns the iterator if a given freq is found - HIGHEST_COMMON specialization +/// @param[in] i_supported_freqs a vector of sorted frequences +/// param[in] i_dimm_freq current dimm speed +/// @return FAPI2_RC_SUCESS iff okay +/// +template< > +inline std::vector<uint32_t>::const_iterator search_list<HIGHEST_COMMON>( const std::vector<uint32_t>& + i_supported_freqs, + const uint32_t i_dimm_freq) +{ + return std::upper_bound(i_supported_freqs.begin(), i_supported_freqs.end(), i_dimm_freq); +} + /// /// @class cas_latency /// @brief CAS latency class that encapsulates JEDEC calculation algorithm @@ -79,28 +125,34 @@ class cas_latency cas_latency() = delete; /// - /// @brief Class constructor that retrieves required SPD data held by internal state - /// @param[in] i_target the controller target - /// @param[in] i_caches decoder caches + /// @brief Class constructor that retrieves required SPD data held by internal state + /// @param[in] i_target the controller target + /// @param[in] i_caches decoder caches + /// @param[in] i_supported_freqs vector of supported frequencies /// @param[out] o_rc returns FAPI2_RC_SUCCESS if constructor initialzed successfully /// cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target_mcs, const std::vector< std::shared_ptr<spd::decoder> >& i_caches, + const std::vector<uint32_t>& i_supported_freqs, fapi2::ReturnCode& o_rc); /// - /// @brief Constructor that allows the user to set desired data in lieu of SPD - /// @param[in] i_target the controller target - /// @param[in] i_taa_min largest tAAmin we want to set in picoseconds - /// @param[in] i_tck_min proposed tCKmin in picoseconds - /// @param[in] i_common_cl_mask common CAS latency mask we want to use (bitmap) - /// @param[in] i_is_3ds loading::IS_3DS if this is for 3DS, loading::NOT_3DS otherwise + /// @brief Constructor that allows the user to set desired data in lieu of SPD - helpful for testing + /// @param[in] i_target the controller target + /// @param[in] i_taa_min largest tAAmin we want to set in picoseconds + /// @param[in] i_tck_min proposed tCKmin in picoseconds + /// @param[in] i_common_cl_mask common CAS latency mask we want to use (bitmap) + /// @param[in] i_is_3ds loading::IS_3DS if this is for 3DS, loading::NOT_3DS otherwise + /// @param[in] i_req_sync_mode required synchronous mode -- defaulted to SYNCH_MODE_UNDETERMINED, + /// @param[in] i_supported_freqs vector of supported frequencies -- defaulted to NIMBUS_SUPPORTED_FREQS /// cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, const uint64_t i_taa_min, const uint64_t i_tck_min, const uint64_t i_common_cl_mask, - const loading i_is_3ds); + const loading i_is_3ds, + const uint8_t i_req_sync_mode = fapi2::ENUM_ATTR_REQUIRED_SYNCH_MODE_UNDETERMINED, + const std::vector<uint32_t>& i_supported_freqs = NIMBUS_SUPPORTED_FREQS); /// /// @brief Default destructor @@ -108,14 +160,83 @@ class cas_latency ~cas_latency() = default; /// - /// @brief Calculates CAS latency and checks if it is supported and within JEDEC spec. + /// @brief Calculates CAS latency and checks if it is supported and within JEDEC spec. /// @param[out] o_cas_latency selected CAS latency /// @param[out] o_tck cycle time corresponding to seleted CAS latency - /// @return fapi2::FAPI2_RC_SUCCESS if ok + /// @return fapi2::FAPI2_RC_SUCCESS iff ok /// fapi2::ReturnCode find_cl(uint64_t& o_cas_latency, uint64_t& o_tck); + /// + /// @brief Selects DIMM frequency to run based on supported system frequencies -- helper function for testing + /// @tparam TT the freq_select type + /// @param[in] i_supported_freqs vector supported frequencies + /// @param[in,out] io_dimm_freq input is current dimm freq & output is next + /// lowest dimm freq between 1866 MT/s - 2666 MT/s + /// @return FAPI2_RC_SUCCESS iff ok + /// @note Frequency values obtained from: + /// @note From P9 User's Manual Version 0.8 - June 08, 2015 + /// @note Memory Controller Unit - page 199 of 456 + /// + template< freq_select TT > + inline fapi2::ReturnCode select_supported_freq_helper( const std::vector<uint32_t>& i_supported_freqs, + uint64_t& io_dimm_freq) + { + FAPI_ASSERT( !i_supported_freqs.empty(), + fapi2::MSS_EMPTY_VECTOR(). + set_FUNCTION(SELECT_SUPPORTED_FREQ). + set_TARGET(iv_target), + "Empty supported frequency vector received for %s", + mss::c_str(iv_target)); + + for( const auto& freq : i_supported_freqs ) + { + FAPI_DBG("Supported freqs taking into account VPD, SPD, & MRW constraints %d for %s", freq, mss::c_str(iv_target) ); + } + + FAPI_DBG("Input frequency %d for %s", io_dimm_freq, mss::c_str(iv_target) ); + { + auto l_iterator = search_list<TT>(i_supported_freqs, io_dimm_freq); + + // Doing this because the HB compiler freaks out if we have it within the FAPI_ASSERT. + // Outputting the value and then incrementing the iterator, that's why it's a post increment + // We have at most 4 memory freqs (1866, 2133, 2400, & 2666), if we ever get a list with < 4 items + // a value of 0 is logged in FFDC once we hit i_supported_freqs.end()...which is better than no logging. + auto l_supported = i_supported_freqs.begin(); + + const auto l_freq0 = (l_supported != i_supported_freqs.end()) ? *(l_supported++) : 0; + const auto l_freq1 = (l_supported != i_supported_freqs.end()) ? *(l_supported++) : 0; + const auto l_freq2 = (l_supported != i_supported_freqs.end()) ? *(l_supported++) : 0; + const auto l_freq3 = (l_supported != i_supported_freqs.end()) ? *(l_supported++) : 0; + + // We can't choose a lower freq than the 1st element of this vector, + // hitting this case means that we exhausted all possible frequencies + FAPI_ASSERT( l_iterator != i_supported_freqs.begin(), + fapi2::MSS_SELECTED_FREQ_NOT_SUPPORTED() + .set_FREQ(io_dimm_freq) + .set_SUPPORTED_FREQ_0( l_freq0 ) + .set_SUPPORTED_FREQ_1( l_freq1 ) + .set_SUPPORTED_FREQ_2( l_freq2 ) + .set_SUPPORTED_FREQ_3( l_freq3 ) + .set_TARGET(iv_target), + "%s Error finding selected freq (%d) from list", + mss::c_str(iv_target), + io_dimm_freq ); + + // Lower bound checks for greater than or equal to input freq, + // we decrement to get the next lowest freq + io_dimm_freq = *(--l_iterator); + + FAPI_DBG("Output frequency %d for %s", io_dimm_freq, mss::c_str(iv_target) ); + } + + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + return fapi2::current_err; + } + private: enum @@ -147,89 +268,131 @@ class cas_latency fapi2::Target<fapi2::TARGET_TYPE_MCA> iv_target; uint64_t iv_largest_taamin;// cas latency time uint64_t iv_proposed_tck;// cycle time - uint64_t iv_common_cl; // common cas latency loading iv_is_3ds; + uint64_t iv_common_cl_bitmap; + bool iv_enable_freq_overrides; + std::vector<uint64_t> iv_common_cl; // common cas latency + uint8_t iv_req_sync_mode; + std::vector<uint32_t> iv_supported_freqs; /// - /// @brief Retrieves SDRAM Minimum CAS Latency Time (tAAmin) from SPD - /// @param[in] i_pDecoder the SPD decoder + /// @brief Retrieves SDRAM Minimum CAS Latency Time (tAAmin) from SPD + /// @param[in] i_pDecoder the SPD decoder /// @param[out] o_value tCKmin value in ps - /// @return FAPI2_RC_SUCCESS iff ok + /// @return FAPI2_RC_SUCCESS iff ok /// fapi2::ReturnCode get_taamin(const std::shared_ptr<mss::spd::decoder>& i_pDecoder, uint64_t& o_value); + /// - /// @brief Retrieves SDRAM Minimum Cycle Time (tCKmin) from SPD - /// @param[in] i_pDecoder the SPD decoder - /// @param[out] o_value tCKmin value in ps - /// @return FAPI2_RC_SUCCESS iff ok + /// @brief Gets max CAS latency (CL) for the appropriate High/Low Range + /// @param[in] i_supported_cl + /// @return the maximum supported CL + /// @note Depends on bit 7 of byte 23 from the DDR4 SPD /// - fapi2::ReturnCode get_tckmin(const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value); + uint64_t get_max_cl(const fapi2::buffer<uint64_t> i_supported_cl) const; /// - /// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD - /// @param[in] i_pDecoder SPD decoder - /// @param[out] o_value tCKmax value in ps - /// @return FAPI2_RC_SUCCESS iff ok + /// @brief Gets min CAS latency (CL) for the appropriate High/Low Range + /// @param[in] i_supported_cl + /// @return the minimum supported CL + /// @note Depends on bit 7 of byte 23 from the DDR4 SPD /// - fapi2::ReturnCode get_tckmax(const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value); + uint64_t get_min_cl(const fapi2::buffer<uint64_t>& i_supported_cl) const; /// - /// @brief Gets max CAS latency (CL) for the appropriate High/Low Range - /// @param[in] i_supported_cl - /// @return the maximum supported CL - /// @note Depends on bit 7 of byte 23 from the DDR4 SPD + /// @brief Calculates CAS latency time from tCK and tAA + /// @param[in] i_taa cas latency time + /// @param[in] i_tck min cycle time + /// @param[out] o_cas_latency calculated CAS latency + /// @return FAPI2_RC_SUCCESS iff okay /// - inline uint64_t get_max_cl(const fapi2::buffer<uint64_t> i_supported_cl) const; + fapi2::ReturnCode calc_cas_latency(const uint64_t i_taa, + const uint64_t i_tck, + uint64_t& o_cas_latency) const; /// - /// @brief Gets min CAS latency (CL) for the appropriate High/Low Range - /// @param[in] i_supported_cl - /// @return the minimum supported CL - /// @note Depends on bit 7 of byte 23 from the DDR4 SPD + /// @brief Helper function to create a vector of supported CAS latencies from a bitmap + /// @param[in] i_common_cl common CAS latency bitmap + /// @return vector of supported CAS latencies /// - inline uint64_t get_min_cl(const fapi2::buffer<uint64_t>& i_supported_cl) const; + std::vector<uint64_t> integral_bitmap_to_vector(const uint64_t i_bitmap) const; /// - /// @brief Calculates CAS latency time from tCK and tAA - /// @param[in] i_taa cas latency time - /// @param[in] i_tck min cycle time - /// @param[out] o_cas_latency calculated CAS latency - /// @return FAPI2_RC_SUCCESS iff okay + /// @brief Determines if a requested CAS latency (CL) is supported in the bin of common CLs + /// @param[in] i_common_cls vector of common CAS latencies + /// @param[in] i_cas_latency CAS latency we are comparing against + /// @return true iff desired CL was found in the bitmap of common CLs, false otherwise /// - inline fapi2::ReturnCode calc_cas_latency(const uint64_t i_taa, - const uint64_t i_tck, - uint64_t& o_cas_latency) const; + bool is_cl_supported_in_common(const std::vector<uint64_t>& i_common_cls, + const uint64_t i_cas_latency) const; /// - /// @brief Helper function to create a vector of supported CAS latencies from a bitmap - /// @param[in] i_common_cl common CAS latency bitmap - /// @return vector of supported CAS latencies + /// @brief Checks that CAS latency doesn't exceed largest CAS latency time + /// @param[in] i_cas_latency cas latency + /// @param[in] i_tck cycle time + /// @return true iff CL exceeds tAAmax, false otherwise /// - std::vector<uint64_t> integral_bitmap_to_vector(const uint64_t i_bitmap) const; + bool is_cl_exceeding_taa_max(const uint64_t i_cas_latency, + const uint64_t i_tck) const; /// - /// @brief Determines if a requested CAS latency (CL) is supported in the bin of common CLs - /// @param[in] i_common_cls vector of common CAS latencies - /// @param[in] i_cas_latency CAS latency we are comparing against - /// @return fapi2::FAPI2_RC_SUCCESS if ok + /// @brief Selects DIMM frequency to run based on supported system frequencies + /// @tparam TT the freq_select type + /// @param[in,out] io_dimm_freq input is current dimm freq & output is next + /// lowest dimm freq between 1866 MT/s - 2666 MT/s + /// @return FAPI2_RC_SUCCESS iff ok + /// @note Frequency values obtained from: + /// @note From P9 User's Manual Version 0.8 - June 08, 2015 + /// @note Memory Controller Unit - page 199 of 456 /// - inline fapi2::ReturnCode is_cl_supported_in_common(const std::vector<uint64_t>& i_common_cls, - const uint64_t i_cas_latency) const; + template< freq_select TT > + inline fapi2::ReturnCode select_supported_freq(uint64_t& io_dimm_freq) + { + FAPI_TRY( (select_supported_freq_helper<TT>(iv_supported_freqs, io_dimm_freq)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief Checks that CAS latency doesn't exceed largest CAS latency time - /// @param[in] i_cas_latency cas latency - /// @param[in] i_tck cycle time - /// @return fapi2::FAPI2_RC_SUCCESS if ok + /// @brief Limits tCK to system constraints (VPD and MRW) + /// @tparam T freq_select type + /// @param[in,out] io_tck input is current tCK, output is highest supported tCK (HIGHEST_COMMON specialization) + /// or the next highest supported tCK (BIN_DOWN specialization) + /// @return FAPI2_RC_SUCCESS iff okay /// - inline fapi2::ReturnCode is_cl_exceeding_taa_max(const uint64_t i_cas_latency, - const uint64_t i_tck) const; + template< freq_select T > + fapi2::ReturnCode apply_freq_constraints(uint64_t& io_tck) + { + uint64_t l_proposed_freq = 0; + FAPI_TRY( mss::ps_to_freq(io_tck, l_proposed_freq) ); -};// cas_latency + FAPI_TRY( (select_supported_freq<T>(l_proposed_freq)), + "%s. Failed select_supported_freq()", mss::c_str(iv_target) ); + + FAPI_TRY( freq_to_ps(l_proposed_freq, io_tck), + "%s. Failed freq_to_ps()", mss::c_str(iv_target) ); + FAPI_INF("%s Supported dimm speed override %d MT/s (Clock period %d in ps)", + mss::c_str(iv_target), l_proposed_freq, io_tck); + + // Sanity check + FAPI_ASSERT(io_tck > 0, + fapi2::MSS_INVALID_CALCULATED_TCK(). + set_TAAMIN(iv_largest_taamin). + set_PROPOSED_TCK(io_tck). + set_IS_3DS(iv_is_3ds). + set_MCA_TARGET(iv_target), + "%s. Invalid calculated clock period(<= 0 nCK) : %d", + mss::c_str(iv_target), + io_tck); + + fapi_try_exit: + return fapi2::current_err; + } + +};// cas_latency }// mss |