From a69715d78e44ca4d69009bdd829a8ed778bcd845 Mon Sep 17 00:00:00 2001 From: Louis Stermole Date: Wed, 4 Dec 2019 11:33:19 -0500 Subject: Add p9a_mss_utils_to_throttle Also move some shared code into gen_throttle.H Change-Id: I74ada8a0ee99db511813e04a58f434d779a90930 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/88093 Reviewed-by: Mark Pizzutillo Tested-by: FSP CI Jenkins Tested-by: Jenkins Server Tested-by: Hostboot CI Tested-by: HWSV CI Reviewed-by: STEPHEN GLANCY Reviewed-by: Michael D Pardeik Reviewed-by: Jennifer A Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/88121 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Daniel M Crowell --- .../hwp/memory/p9_mss_utils_to_throttle.C | 85 ++++++--------- .../hwp/memory/p9a_mss_utils_to_throttle.C | 117 +++++++++++++++++++-- .../memory/lib/utils/power_thermal/gen_throttle.H | 85 ++++++++++++++- 3 files changed, 225 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C index 8efba3f4b..01bd44749 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* Contributors Listed Below - COPYRIGHT 2015,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -72,6 +72,8 @@ extern "C" /// fapi2::ReturnCode p9_mss_utils_to_throttle( const std::vector< fapi2::Target >& i_targets ) { + constexpr uint64_t l_min_util = mss::power_thermal::throttle_traits::MIN_UTIL; + FAPI_INF("Entering p9_mss_utils_to_throttle"); std::vector< fapi2::Target > l_exceeded_power; @@ -88,20 +90,24 @@ extern "C" uint32_t l_max_databus_util = {}; uint32_t l_dram_clocks = 0; uint16_t l_safemode_throttle_per_port = 0; - double l_calc_util_safemode = 0; + uint32_t l_calc_util = 0; uint16_t l_n_port[mss::PORTS_PER_MCS] = {}; uint16_t l_n_slot[mss::PORTS_PER_MCS] = {}; uint32_t l_max_power[mss::PORTS_PER_MCS] = {}; - FAPI_TRY( mss::mrw_mem_m_dram_clocks(l_dram_clocks) ); + FAPI_TRY(mss::mrw_mem_m_dram_clocks(l_dram_clocks) ); //Util attribute set by OCC - FAPI_TRY( mss::databus_util(l_mcs, l_input_databus_util) ); - FAPI_TRY( mss::mrw_max_dram_databus_util(l_max_databus_util)); + FAPI_TRY(mss::databus_util(l_mcs, l_input_databus_util) ); + FAPI_TRY(mss::mrw_max_dram_databus_util(l_max_databus_util)); + FAPI_TRY(mss::mrw_safemode_mem_throttled_n_commands_per_port(l_safemode_throttle_per_port)); for( const auto& l_mca : mss::find_targets(l_mcs) ) { + fapi2::ReturnCode l_rc; + bool l_safemode = false; + FAPI_INF("Input databus utilization for %s is %d", mss::c_str(l_mca), l_input_databus_util[mss::index(l_mca)]); @@ -114,58 +120,31 @@ extern "C" } // If input utilization is zero, use mrw safemode throttle values for utilization - bool l_safemode = false; - - if (l_input_databus_util[l_port_num] == 0) - { - FAPI_TRY(mss::mrw_safemode_mem_throttled_n_commands_per_port(l_safemode_throttle_per_port), - "Error in getting safemode throttles" ); - FAPI_TRY( mss::power_thermal::calc_util_from_throttles(l_safemode_throttle_per_port, l_dram_clocks, - l_calc_util_safemode), - "%s Error calculating utilization from safemode throttle %d and mem clocks %d", - mss::c_str(l_mca), - l_safemode_throttle_per_port, - l_dram_clocks); - FAPI_INF( "%s Safemode throttles being used since input util is zero: Using N=%d, Utilization %f", - mss::c_str(l_mca), - l_safemode_throttle_per_port, - l_calc_util_safemode); - l_safemode = true; - l_input_databus_util[l_port_num] = l_calc_util_safemode; - } - - using TT = mss::power_thermal::throttle_traits<>; - const uint64_t l_min_util = TT::MIN_UTIL; - //Make sure MIN_UTIL <= input_utilization <= max_utilization - const uint32_t l_databus_util = ( l_input_databus_util[l_port_num] >= l_min_util) ? - std::min(l_input_databus_util[l_port_num], l_max_databus_util) - : l_min_util; + // else make sure we're within our maximum utilization limit + FAPI_TRY(mss::power_thermal::calc_utilization(l_mca, + l_input_databus_util[l_port_num], + l_dram_clocks, + l_safemode_throttle_per_port, + l_max_databus_util, + l_calc_util, + l_util_error, + l_safemode)); // Error if utilization is less than MIN_UTIL // Don't exit, let HWP finish and return error at end - if (l_input_databus_util[l_port_num] < l_min_util) - { - FAPI_ASSERT_NOEXIT( false, - fapi2::MSS_MIN_UTILIZATION_ERROR() - .set_INPUT_UTIL_VALUE(l_input_databus_util[l_port_num]) - .set_MIN_UTIL_VALUE(l_min_util), - "%s Input utilization (%d) less than minimum utilization allowed (%d)", - mss::c_str(l_mca), l_input_databus_util[l_port_num], l_min_util); - l_util_error = true; - } - - //Make a throttle object in order to calculate the port power - fapi2::ReturnCode l_rc; - - mss::power_thermal::throttle<> l_throttle (l_mca, l_rc); - FAPI_TRY(l_rc, "Error calculating mss::power_thermal::throttle constructor in p9_mss_utils_to_throttles"); + FAPI_ASSERT_NOEXIT(!l_util_error, + fapi2::MSS_MIN_UTILIZATION_ERROR() + .set_INPUT_UTIL_VALUE(l_input_databus_util[l_port_num]) + .set_MIN_UTIL_VALUE(l_min_util), + "%s Input utilization (%d) less than minimum utilization allowed (%d)", + mss::c_str(l_mca), l_input_databus_util[l_port_num], l_min_util); - FAPI_INF( "%s MRW dram clock window: %d, databus utilization: %d", - mss::c_str(l_mca), - l_dram_clocks, - l_databus_util); + // Make a throttle object in order to calculate the port power + mss::power_thermal::throttle l_throttle (l_mca, l_rc); + FAPI_TRY(l_rc, "%s Error calculating mss::power_thermal::throttle constructor in p9_mss_utils_to_throttles", + mss::c_str(l_mca)); - FAPI_TRY( l_throttle.calc_slots_and_power(l_databus_util)); + FAPI_TRY( l_throttle.calc_slots_and_power(l_calc_util)); FAPI_INF( "%s Calculated N commands per port %d, per slot %d, commands per dram clock window %d, maxpower is %d", mss::c_str(l_mca), @@ -197,7 +176,7 @@ extern "C" // Return a failing RC code if we had any input utilization values less than MIN_UTIL if (l_util_error) { - fapi2::current_err = fapi2::FAPI2_RC_FALSE; + fapi2::current_err = fapi2::RC_MSS_MIN_UTILIZATION_ERROR; } fapi_try_exit: diff --git a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_utils_to_throttle.C b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_utils_to_throttle.C index 0666a8772..7d8afb81f 100644 --- a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_utils_to_throttle.C +++ b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_utils_to_throttle.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -38,10 +38,16 @@ // *HWP Consumed by: FSP:HB #include +#include +#include +#include +#include // fapi2 #include +extern "C" +{ /// /// @brief Determines throttle and power values for a given port databus utilization. /// @param[in] i_targets vector of OCMB_CHIPs to set throttle and power attributes on @@ -49,11 +55,106 @@ /// @note ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT will be set to worst case of all slots passed in /// @note input ATTR_MSS_DATABUS_UTIL and ATTR_MSS_MEM_WATT_TARGET /// @note output ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, and ATTR_MSS_PORT_MAXPOWER -/// @note Does not set runtime throttles or set registers to throttle values` +/// @note Does not set runtime throttles or set registers to throttle values /// -fapi2::ReturnCode p9a_mss_utils_to_throttle( const std::vector< fapi2::Target >& - i_targets ) -{ - FAPI_INF("Entering p9a_mss_utils_to_throttle"); - return fapi2::FAPI2_RC_SUCCESS; -} + fapi2::ReturnCode p9a_mss_utils_to_throttle(const std::vector>& i_targets) + { + constexpr uint64_t l_min_util = mss::power_thermal::throttle_traits::MIN_UTIL; + + FAPI_INF("Entering p9a_mss_utils_to_throttle"); + + std::vector> l_exceeded_power; + bool l_util_error = false; + + for (const auto& l_ocmb : i_targets) + { + if (mss::count_dimm(l_ocmb) == 0) + { + FAPI_INF("Skipping %s because it has no DIMM targets", mss::c_str(l_ocmb)); + continue; + } + + uint32_t l_max_databus_util = 0; + uint32_t l_dram_clocks = 0; + uint32_t l_safemode_util = 0; + uint32_t l_safemode_throttle_per_port = 0; + uint32_t l_calc_util = 0; + + FAPI_TRY(mss::attr::get_mrw_mem_m_dram_clocks(l_dram_clocks)); + FAPI_TRY(mss::attr::get_mrw_max_dram_databus_util(l_max_databus_util)); + FAPI_TRY(mss::attr::get_mrw_safemode_dram_databus_util(l_safemode_util)); + + l_safemode_throttle_per_port = mss::power_thermal::calc_n_from_dram_util( + (l_safemode_util / mss::power_thermal::throttle_const::PERCENT_CONVERSION), + l_dram_clocks); + + for(const auto& l_port : mss::find_targets(l_ocmb)) + { + fapi2::ReturnCode l_rc; + uint32_t l_input_databus_util = 0; + bool l_safemode = false; + + // Util attribute set by OCC + FAPI_TRY( mss::attr::get_databus_util(l_port, l_input_databus_util) ); + + FAPI_INF("Input databus utilization for %s is %d", + mss::c_str(l_port), + l_input_databus_util); + + // If input utilization is zero, use mrw safemode throttle values for utilization + // else make sure we're within our maximum utilization limit + FAPI_TRY(mss::power_thermal::calc_utilization(l_port, + l_input_databus_util, + l_dram_clocks, + l_safemode_throttle_per_port, + l_max_databus_util, + l_calc_util, + l_util_error, + l_safemode)); + + // Error if utilization is less than MIN_UTIL + // Don't exit, let HWP finish and return error at end + FAPI_ASSERT_NOEXIT( !l_util_error, + fapi2::MSS_MIN_UTILIZATION_ERROR() + .set_INPUT_UTIL_VALUE(l_input_databus_util) + .set_MIN_UTIL_VALUE(l_min_util), + "%s Input utilization (%d) less than minimum utilization allowed (%d)", + mss::c_str(l_port), l_input_databus_util, l_min_util); + + // Make a throttle object in order to calculate the port power + mss::power_thermal::throttle l_throttle(l_port, l_rc); + FAPI_TRY(l_rc, "%s Error calculating mss::power_thermal::throttle constructor in p9a_mss_utils_to_throttles", + mss::c_str(l_port)); + + FAPI_TRY(l_throttle.calc_slots_and_power(l_calc_util)); + + FAPI_INF( "%s Calculated N commands per port %d, per slot %d, commands per dram clock window %d, maxpower is %d", + mss::c_str(l_port), + l_throttle.iv_n_port, + l_throttle.iv_n_slot, + l_dram_clocks, + l_throttle.iv_calc_port_maxpower); + + FAPI_TRY(mss::attr::set_port_maxpower(l_port, l_throttle.iv_calc_port_maxpower)); + FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_slot(l_port, + (l_safemode) ? l_safemode_throttle_per_port : l_throttle.iv_n_slot)); + FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_port(l_port, + (l_safemode) ? l_safemode_throttle_per_port : l_throttle.iv_n_port)); + } // ports + } // ocmbs + + // Equalize throttles to prevent variable performance + // Note that we don't do anything with any port that exceed the power limit here, as we don't have an input power limit to go from + FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, mss::throttle_type::POWER, + l_exceeded_power)); + + // Return a failing RC code if we had any input utilization values less than MIN_UTIL + if (l_util_error) + { + fapi2::current_err = fapi2::RC_MSS_MIN_UTILIZATION_ERROR; + } + + fapi_try_exit: + return fapi2::current_err; + } +}// extern C diff --git a/src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H b/src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H index e8b4f0f61..c65ffb637 100644 --- a/src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H +++ b/src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -68,6 +68,29 @@ enum throttle_const : size_t }; +/// +/// @brief Calculate the N throttle for a given dram data bus utilization value +/// +/// @tparam T1 template parameter, type of input to be processed +/// @tparam T2 template parameter, type of input to be processed +/// @param[in] i_dram_util dram data bus utilization value +/// @param[in] i_throttle_m M throttle value in N/M throttling +/// +/// @return int32_t calculated N throttle value +/// +template +inline uint32_t calc_n_from_dram_util(const T1 i_dram_util, const T2 i_throttle_m) +{ + constexpr uint64_t CONVERT_ADDR_UTIL_TO_DATA_UTIL = 4; + + return (static_cast(static_cast(i_dram_util) + * (i_throttle_m) + / (CONVERT_ADDR_UTIL_TO_DATA_UTIL) + / (PERCENT_CONVERSION) + ) + ); +} + /// /// @brief Calculate N (address operations) allowed within a window of M DRAM clocks /// @param[in] i_databus_util databus utilization percentage (e.g. 5% = 5) @@ -1097,6 +1120,66 @@ fapi_try_exit: } +/// +/// @brief set the safemode throttle register +/// @tparam MC mss::mc_type +/// @tparam T the fapi2 target type of the target +/// @tparam TT portTraits port traits for the given MC target type +/// @param[in] i_target the port target +/// @return fapi2::FAPI2_RC_SUCCESS if ok +/// @note sets FARB4Q +/// @note used to set throttle window (N throttles / M clocks) +/// +template> +fapi2::ReturnCode calc_utilization(const fapi2::Target& i_target, + const uint32_t i_input_databus_util, + const uint32_t i_dram_clocks, + const uint16_t i_safemode_throttle_per_port, + const uint32_t i_max_databus_util, + uint32_t& o_util, + bool& o_util_error, + bool& o_safemode) +{ + constexpr uint64_t l_min_util = TT::MIN_UTIL; + + o_util = i_input_databus_util; + o_safemode = false; + + // Use MRW safemode throttle values if input utilization is zero + if (i_input_databus_util == 0) + { + FAPI_TRY(calc_util_from_throttles(i_safemode_throttle_per_port, + i_dram_clocks, + o_util), + "%s Error calculating utilization from safemode throttle %d and mem clocks %d", + mss::c_str(i_target), + i_safemode_throttle_per_port, + i_dram_clocks); + FAPI_INF("%s Safemode throttles being used since input util is zero: Using N=%d, Utilization %f", + mss::c_str(i_target), + i_safemode_throttle_per_port, + o_util); + o_safemode = true; + } + else if (i_input_databus_util < l_min_util) + { + o_util_error = true; + } + + // Make sure MIN_UTIL <= input_utilization <= max_utilization + o_util = (o_util >= l_min_util) ? std::min(o_util, i_max_databus_util) : l_min_util; + + FAPI_INF("%s MRW dram clock window: %d, databus utilization: %d", + mss::c_str(i_target), + i_dram_clocks, + o_util); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + /// /// @brief Equalize the throttles and estimated power at those throttle levels /// @tparam MC mss::mc_type -- cgit v1.2.1