From 6c22f61fc163823ec0ef677c2fce851fe704c466 Mon Sep 17 00:00:00 2001 From: Jacob Harvey Date: Wed, 31 Aug 2016 13:55:41 -0500 Subject: Implement L2 eff_config_thermal, bulk_pwr_throttle Implemented p9_mss_bulk_pwr_throttles p9_mss_utils_to_throttles p9_mss_eff_config_thermal Updated throttle xml Change-Id: I0492f9fe8a5bd027ff5875f236711bcf55af88f5 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31804 Tested-by: Jenkins Server Tested-by: Hostboot CI Reviewed-by: Christian R. Geddes Reviewed-by: Louis Stermole Reviewed-by: Brian R. Silver Reviewed-by: Matt K. Light Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31813 Reviewed-by: Hostboot Team Tested-by: Jenkins OP Build CI Tested-by: FSP CI Jenkins --- .../hwp/memory/lib/eff_config/eff_config.C | 2 +- .../hwp/memory/lib/eff_config/eff_config.H | 2 +- .../hwp/memory/lib/mss_attribute_accessors.H | 164 ++++++--- .../hwp/memory/lib/power_thermal/decoder.C | 73 ++-- .../hwp/memory/lib/power_thermal/decoder.H | 11 +- .../hwp/memory/lib/power_thermal/throttle.C | 389 ++++++++++++++++----- .../hwp/memory/lib/power_thermal/throttle.H | 164 ++++++--- .../p9/procedures/hwp/memory/lib/utils/find.H | 3 - .../hwp/memory/p9_mss_bulk_pwr_throttles.C | 90 +++-- .../hwp/memory/p9_mss_bulk_pwr_throttles.H | 2 +- .../p9/procedures/hwp/memory/p9_mss_eff_config.C | 12 - .../hwp/memory/p9_mss_eff_config_thermal.C | 87 +++-- .../hwp/memory/p9_mss_eff_config_thermal.H | 8 +- .../p9/procedures/hwp/memory/p9_mss_throttle_mem.C | 4 +- .../hwp/memory/p9_mss_utils_to_throttle.C | 43 ++- .../xml/attribute_info/memory_mcs_attributes.xml | 23 +- .../xml/attribute_info/memory_mrw_attributes.xml | 4 +- .../xml/error_info/p9_memory_mss_eff_config.xml | 2 +- .../targeting/common/xmltohb/attribute_types.xml | 36 +- src/usr/targeting/common/xmltohb/target_types.xml | 1 + 20 files changed, 789 insertions(+), 331 deletions(-) diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C index 2feba70b5..15df95deb 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C @@ -184,7 +184,7 @@ fapi_try_exit: }// dimm_type /// -/// @brief Determines & sets effective config for dram_mfg_id type from SPD +/// @brief Determines & sets effective config for eff_dram_mfg_id type from SPD /// @param[in] i_target FAPI2 target /// @return fapi2::FAPI2_RC_SUCCESS if okay /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H index a85ed96d3..e6f780d88 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H @@ -129,7 +129,7 @@ class eff_config const std::vector& i_spd_data); /// - /// @brief Determines & sets effective config for dram_mfg_id type from SPD + /// @brief Determines & sets effective config for eff_dram_mfg_id type from SPD /// @param[in] i_target FAPI2 target /// @return fapi2::FAPI2_RC_SUCCESS if okay /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H index e1cb7e4ac..bdf5c4979 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H @@ -5642,16 +5642,16 @@ fapi_try_exit: /// /// @brief ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] ref to the value uint32_t +/// @param[out] ref to the value uint16_t /// @note Generated by gen_accessors.pl generateParameters (D) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note This is the throttled N commands per window of M DRAM clocks setting for /// cfg_nm_n_per_port. /// inline fapi2::ReturnCode mem_throttled_n_commands_per_port(const fapi2::Target& i_target, - uint32_t& o_value) + uint16_t& o_value) { - uint32_t l_value[2]; + uint16_t l_value[2]; FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, i_target.getParent(), l_value) ); @@ -5667,16 +5667,16 @@ fapi_try_exit: /// /// @brief ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] ref to the value uint32_t +/// @param[out] ref to the value uint16_t /// @note Generated by gen_accessors.pl generateParameters (D.1) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note This is the throttled N commands per window of M DRAM clocks setting for /// cfg_nm_n_per_port. /// inline fapi2::ReturnCode mem_throttled_n_commands_per_port(const fapi2::Target& i_target, - uint32_t& o_value) + uint16_t& o_value) { - uint32_t l_value[2]; + uint16_t l_value[2]; auto l_mca = i_target.getParent(); FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mca.getParent(), @@ -5693,14 +5693,14 @@ fapi_try_exit: /// /// @brief ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] uint32_t* memory to store the value +/// @param[out] uint16_t* memory to store the value /// @note Generated by gen_accessors.pl generateParameters (E) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note This is the throttled N commands per window of M DRAM clocks setting for /// cfg_nm_n_per_port. /// inline fapi2::ReturnCode mem_throttled_n_commands_per_port(const fapi2::Target& i_target, - uint32_t* o_array) + uint16_t* o_array) { if (o_array == nullptr) { @@ -5708,10 +5708,10 @@ inline fapi2::ReturnCode mem_throttled_n_commands_per_port(const fapi2::Target -/// @param[out] ref to the value uint32_t +/// @param[out] ref to the value uint16_t /// @note Generated by gen_accessors.pl generateParameters (D) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note This is the throttle numerator setting for /// cfg_nm_n_per_slot /// inline fapi2::ReturnCode mem_throttled_n_commands_per_slot(const fapi2::Target& i_target, - uint32_t& o_value) + uint16_t& o_value) { - uint32_t l_value[2]; + uint16_t l_value[2]; FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, i_target.getParent(), l_value) ); @@ -5827,16 +5827,16 @@ fapi_try_exit: /// /// @brief ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] ref to the value uint32_t +/// @param[out] ref to the value uint16_t /// @note Generated by gen_accessors.pl generateParameters (D.1) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note This is the throttle numerator setting for /// cfg_nm_n_per_slot /// inline fapi2::ReturnCode mem_throttled_n_commands_per_slot(const fapi2::Target& i_target, - uint32_t& o_value) + uint16_t& o_value) { - uint32_t l_value[2]; + uint16_t l_value[2]; auto l_mca = i_target.getParent(); FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mca.getParent(), @@ -5853,14 +5853,14 @@ fapi_try_exit: /// /// @brief ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] uint32_t* memory to store the value +/// @param[out] uint16_t* memory to store the value /// @note Generated by gen_accessors.pl generateParameters (E) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note This is the throttle numerator setting for /// cfg_nm_n_per_slot /// inline fapi2::ReturnCode mem_throttled_n_commands_per_slot(const fapi2::Target& i_target, - uint32_t* o_array) + uint16_t* o_array) { if (o_array == nullptr) { @@ -5868,10 +5868,10 @@ inline fapi2::ReturnCode mem_throttled_n_commands_per_slot(const fapi2::Target +/// @param[out] ref to the value uint32_t +/// @note Generated by gen_accessors.pl generateParameters (F) +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK +/// @note DIMM Max Power based on a thermal limit Decoded from +/// ATTR_MSS_MRW_THERMAL_POWER_LIMIT +/// +inline fapi2::ReturnCode dimm_thermal_limit(const fapi2::Target& i_target, uint32_t& o_value) +{ + uint32_t l_value[2][2]; + auto l_mca = i_target.getParent(); + auto l_mcs = l_mca.getParent(); + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_DIMM_THERMAL_LIMIT, l_mcs, l_value) ); + o_value = l_value[mss::index(l_mca)][mss::index(i_target)]; + return fapi2::current_err; + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_MSS_DIMM_THERMAL_LIMIT: 0x%lx (target: %s)", + uint64_t(fapi2::current_err), mss::c_str(i_target)); + return fapi2::current_err; +} + +/// +/// @brief ATTR_MSS_DIMM_THERMAL_LIMIT getter +/// @param[in] const ref to the fapi2::Target +/// @param[out] uint32_t* memory to store the value +/// @note Generated by gen_accessors.pl generateParameters (G) +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK +/// @note DIMM Max Power based on a thermal limit Decoded from +/// ATTR_MSS_MRW_THERMAL_POWER_LIMIT +/// +inline fapi2::ReturnCode dimm_thermal_limit(const fapi2::Target& i_target, uint32_t* o_array) +{ + if (o_array == nullptr) + { + FAPI_ERR("nullptr passed to attribute accessor %s", __func__); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + } + + uint32_t l_value[2][2]; + auto l_mcs = i_target.getParent(); + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_DIMM_THERMAL_LIMIT, l_mcs, l_value) ); + memcpy(o_array, &(l_value[mss::index(i_target)][0]), 8); + return fapi2::current_err; + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_MSS_DIMM_THERMAL_LIMIT: 0x%lx (target: %s)", + uint64_t(fapi2::current_err), mss::c_str(i_target)); + return fapi2::current_err; +} + +/// +/// @brief ATTR_MSS_DIMM_THERMAL_LIMIT getter +/// @param[in] const ref to the fapi2::Target +/// @param[out] uint32_t* memory to store the value +/// @note Generated by gen_accessors.pl generateParameters (H) +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK +/// @note DIMM Max Power based on a thermal limit Decoded from +/// ATTR_MSS_MRW_THERMAL_POWER_LIMIT +/// +inline fapi2::ReturnCode dimm_thermal_limit(const fapi2::Target& i_target, uint32_t* o_array) +{ + if (o_array == nullptr) + { + FAPI_ERR("nullptr passed to attribute accessor %s", __func__); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + } + + uint32_t l_value[2][2]; + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_DIMM_THERMAL_LIMIT, i_target, l_value) ); + memcpy(o_array, &l_value, 16); + return fapi2::current_err; + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_MSS_DIMM_THERMAL_LIMIT: 0x%lx (target: %s)", + uint64_t(fapi2::current_err), mss::c_str(i_target)); + return fapi2::current_err; +} + /// /// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] ref to the value uint32_t +/// @param[out] ref to the value uint16_t /// @note Generated by gen_accessors.pl generateParameters (D) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Runtime throttled N commands per M DRAM clocks setting for /// cfg_nm_n_per_port. /// inline fapi2::ReturnCode runtime_mem_throttled_n_commands_per_port(const fapi2::Target& - i_target, uint32_t& o_value) + i_target, uint16_t& o_value) { - uint32_t l_value[2]; + uint16_t l_value[2]; FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, i_target.getParent(), l_value) ); @@ -6737,16 +6821,16 @@ fapi_try_exit: /// /// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] ref to the value uint32_t +/// @param[out] ref to the value uint16_t /// @note Generated by gen_accessors.pl generateParameters (D.1) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Runtime throttled N commands per M DRAM clocks setting for /// cfg_nm_n_per_port. /// inline fapi2::ReturnCode runtime_mem_throttled_n_commands_per_port(const fapi2::Target& - i_target, uint32_t& o_value) + i_target, uint16_t& o_value) { - uint32_t l_value[2]; + uint16_t l_value[2]; auto l_mca = i_target.getParent(); FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, @@ -6763,14 +6847,14 @@ fapi_try_exit: /// /// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] uint32_t* memory to store the value +/// @param[out] uint16_t* memory to store the value /// @note Generated by gen_accessors.pl generateParameters (E) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Runtime throttled N commands per M DRAM clocks setting for /// cfg_nm_n_per_port. /// inline fapi2::ReturnCode runtime_mem_throttled_n_commands_per_port(const fapi2::Target& - i_target, uint32_t* o_array) + i_target, uint16_t* o_array) { if (o_array == nullptr) { @@ -6778,10 +6862,10 @@ inline fapi2::ReturnCode runtime_mem_throttled_n_commands_per_port(const fapi2:: return fapi2::FAPI2_RC_INVALID_PARAMETER; } - uint32_t l_value[2]; + uint16_t l_value[2]; FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, i_target, l_value) ); - memcpy(o_array, &l_value, 8); + memcpy(o_array, &l_value, 4); return fapi2::current_err; fapi_try_exit: @@ -6874,16 +6958,16 @@ fapi_try_exit: /// /// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] ref to the value uint32_t +/// @param[out] ref to the value uint16_t /// @note Generated by gen_accessors.pl generateParameters (D) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Runtime throttle numerator setting for /// cfg_nm_n_per_slot /// inline fapi2::ReturnCode runtime_mem_throttled_n_commands_per_slot(const fapi2::Target& - i_target, uint32_t& o_value) + i_target, uint16_t& o_value) { - uint32_t l_value[2]; + uint16_t l_value[2]; FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT, i_target.getParent(), l_value) ); @@ -6899,16 +6983,16 @@ fapi_try_exit: /// /// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] ref to the value uint32_t +/// @param[out] ref to the value uint16_t /// @note Generated by gen_accessors.pl generateParameters (D.1) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Runtime throttle numerator setting for /// cfg_nm_n_per_slot /// inline fapi2::ReturnCode runtime_mem_throttled_n_commands_per_slot(const fapi2::Target& - i_target, uint32_t& o_value) + i_target, uint16_t& o_value) { - uint32_t l_value[2]; + uint16_t l_value[2]; auto l_mca = i_target.getParent(); FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT, @@ -6925,14 +7009,14 @@ fapi_try_exit: /// /// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT getter /// @param[in] const ref to the fapi2::Target -/// @param[out] uint32_t* memory to store the value +/// @param[out] uint16_t* memory to store the value /// @note Generated by gen_accessors.pl generateParameters (E) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Runtime throttle numerator setting for /// cfg_nm_n_per_slot /// inline fapi2::ReturnCode runtime_mem_throttled_n_commands_per_slot(const fapi2::Target& - i_target, uint32_t* o_array) + i_target, uint16_t* o_array) { if (o_array == nullptr) { @@ -6940,10 +7024,10 @@ inline fapi2::ReturnCode runtime_mem_throttled_n_commands_per_slot(const fapi2:: return fapi2::FAPI2_RC_INVALID_PARAMETER; } - uint32_t l_value[2]; + uint16_t l_value[2]; FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT, i_target, l_value) ); - memcpy(o_array, &l_value, 8); + memcpy(o_array, &l_value, 4); return fapi2::current_err; fapi_try_exit: diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.C b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.C index a6129774a..11da9b2dd 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.C @@ -115,6 +115,30 @@ fapi2::ReturnCode decoder::generate_encoding() fapi_try_exit: return fapi2::current_err; } +/// +///@brief a compare functor for the decoder::find_attr functions below +///@note AND's the input hash with the generated hash from the DIMM to see if they match +///@note Using an AND instead of == because not all DIMM configs have power slopes, so defaults are needed +/// +struct is_match +{ + /// + ///@brief functor constructor + ///@param[in] i_gen_key the class object's constructed hash for the installed dimm, to be compared with the attr array + /// + is_match(const fapi2::buffer i_gen_key) : iv_gen_key(i_gen_key) {} + const fapi2::buffer iv_gen_key; + + /// + ///@brief Boolean compare used for find_if function + /// + bool operator()(const fapi2::buffer i_hash) + { + uint32_t l_temp = 0; + i_hash.extractToRight(l_temp); + return ((l_temp & iv_gen_key) == iv_gen_key); + } +}; /// /// @brief Finds a value for the power curve slope attributes by matching the generated hashes @@ -124,27 +148,18 @@ fapi_try_exit: /// fapi2::ReturnCode decoder::find_slope (const std::vector>& i_slope) { - - // Comparator lambda expression - const auto compare = [this](const fapi2::buffer& i_hash) - { - uint32_t l_temp = 0; - i_hash.extractToRight(l_temp); - return ((l_temp & iv_gen_key) == iv_gen_key); - }; - // Find iterator to matching key (if it exists) const auto l_value_iterator = std::find_if(i_slope.begin(), i_slope.end(), - compare); + is_match(iv_gen_key)); - //Should have matched with the all default ATTR at least + //Should have matched with the default ATTR value at least //The last value should always be the default value FAPI_ASSERT(l_value_iterator != i_slope.end(), fapi2::MSS_NO_POWER_THERMAL_ATTR_FOUND() .set_GENERATED_KEY(iv_gen_key) .set_DIMM_TARGET(iv_kind.iv_target), - "Couldn't find %s value for generated key:%016lx, for target %s. " + "Couldn't find %s value for generated key:%08lx, for target %s. " "DIMM values for generated key are " "size is %d, gen is %d, type is %d, width is %d, density %d, stack %d, mfgid %d, dimms %d", "ATTR_MSS_MRW_POWER_CURVE_SLOPE", @@ -159,8 +174,8 @@ fapi2::ReturnCode decoder::find_slope (const std::vector iv_kind.iv_mfgid, iv_dimms_per_port); - (*l_value_iterator).extractToRight( iv_vddr_slope); - (*l_value_iterator).extractToRight(iv_total_slope); + l_value_iterator->extractToRight( iv_vddr_slope); + l_value_iterator->extractToRight(iv_total_slope); fapi_try_exit: return fapi2::current_err; @@ -174,18 +189,10 @@ fapi_try_exit: /// fapi2::ReturnCode decoder::find_intercept (const std::vector>& i_intercept) { - // Comparator lambda expression - const auto compare = [this](const fapi2::buffer& i_hash) - { - uint32_t l_temp = 0; - i_hash.extractToRight(l_temp); - return ((l_temp & iv_gen_key) == iv_gen_key); - }; - // Find iterator to matching key (if it exists) const auto l_value_iterator = std::find_if(i_intercept.begin(), i_intercept.end(), - compare); + is_match(iv_gen_key)); //Should have matched with the all default ATTR at least //The last value should always be the default value @@ -193,7 +200,7 @@ fapi2::ReturnCode decoder::find_intercept (const std::vector( iv_vddr_intercept); - (*l_value_iterator).extractToRight(iv_total_intercept); + l_value_iterator->extractToRight( iv_vddr_intercept); + l_value_iterator->extractToRight(iv_total_intercept); fapi_try_exit: return fapi2::current_err; @@ -223,18 +230,10 @@ fapi_try_exit: /// fapi2::ReturnCode decoder::find_thermal_power_limit (const std::vector>& i_thermal_limits) { - // Comparator lambda expression - const auto compare = [this](const fapi2::buffer& i_hash) - { - uint32_t l_temp = 0; - i_hash.extractToRight(l_temp); - return ((l_temp & iv_gen_key) == iv_gen_key); - }; - // Find iterator to matching key (if it exists) const auto l_value_iterator = std::find_if(i_thermal_limits.begin(), i_thermal_limits.end(), - compare); + is_match(iv_gen_key)); //Should have matched with the all default ATTR at least //The last value should always be the default value @@ -242,7 +241,7 @@ fapi2::ReturnCode decoder::find_thermal_power_limit (const std::vector( iv_thermal_power_limit); + l_value_iterator->extractToRight( iv_thermal_power_limit); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H index d7ca5bf71..aa339fd93 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H @@ -41,17 +41,17 @@ #include namespace mss { + +namespace power_thermal +{ + enum size_of_attrs : size_t { SIZE_OF_POWER_CURVES_ATTRS = 100, SIZE_OF_THERMAL_ATTR = 10, }; - -namespace power_thermal -{ //Currently needs to be in sorted order for lookup to work - static const std::vector< std::pair > DIMM_SIZE_MAP = { {4, 0b0000}, @@ -162,8 +162,8 @@ enum ATTR_DECODE_INFO /// class decoder { - private: public: + //IVs for all of the attributes per MCS const mss::dimm::kind iv_kind; @@ -252,7 +252,6 @@ fapi2::ReturnCode get_power_attrs (const fapi2::Target& uint16_t o_total_slope [PORTS_PER_MCS][MAX_DIMM_PER_PORT], uint16_t o_total_int [PORTS_PER_MCS][MAX_DIMM_PER_PORT], uint32_t o_thermal_power [PORTS_PER_MCS][MAX_DIMM_PER_PORT]); - /// /// @brief Encode the attribute into a bit encoding /// @tparam[in] S *ATTR*_SIZE enum used for fapi2::buffer position diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C index f468ec708..031c846b1 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C @@ -23,15 +23,16 @@ /* */ /* IBM_PROLOG_END_TAG */ /// -/// @file eff_config.C -/// @brief Determine effective config for mss settings +/// @file throttle.C +/// @brief Determine throttle settings for memory /// // *HWP HWP Owner: Jacob Harvey // *HWP HWP Backup: Brian Silver // *HWP Team: Memory // *HWP Level: 2 // *HWP Consumed by: FSP:HB - +//std lib +#include // fapi2 #include @@ -48,8 +49,6 @@ namespace mss { namespace power_thermal { - - /// /// @brief Constructor /// @param[in] i_target MCS target to call power thermal stuff on @@ -63,23 +62,20 @@ throttle::throttle( const fapi2::Target& i_mca, fapi2::R iv_n_slot(0), iv_n_port(0), iv_port_power_limit(0), - iv_port_maxpower(0), iv_calc_port_maxpower(0) { + //holder for watt_target to add up for port uint32_t l_dimm_power_limits [MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( mem_throttled_n_commands_per_slot( iv_target, iv_n_slot) ); - FAPI_TRY( mem_throttled_n_commands_per_port( iv_target, iv_n_port) ); - FAPI_TRY( port_maxpower ( iv_target, iv_port_maxpower) ); FAPI_TRY( mrw_max_dram_databus_util(iv_databus_port_max) ); - FAPI_TRY( mrw_dimm_power_curve_percent_uplift( iv_power_uplift) ); - FAPI_TRY( mrw_dimm_power_curve_percent_uplift_idle( iv_power_uplift_idle) ); - //FAPI_TRY( mrw_thermal_memory_power_limit( iv_dimm_thermal_limit) ); - + FAPI_TRY( mrw_dimm_power_curve_percent_uplift(iv_power_uplift) ); + FAPI_TRY( mrw_dimm_power_curve_percent_uplift_idle(iv_power_uplift_idle) ); + FAPI_TRY( dimm_thermal_limit( iv_target, iv_dimm_thermal_limit) ); + FAPI_TRY( total_pwr_intercept( iv_target, iv_pwr_int)); + FAPI_TRY( total_pwr_slope( iv_target, iv_pwr_slope)); FAPI_TRY( runtime_mem_throttled_n_commands_per_slot(iv_target, iv_runtime_n_slot ) ); FAPI_TRY( runtime_mem_throttled_n_commands_per_port(iv_target, iv_runtime_n_port ) ); - FAPI_TRY( mem_watt_target( iv_target, &(l_dimm_power_limits[0])) ); + FAPI_TRY( mem_watt_target( iv_target, l_dimm_power_limits) ); FAPI_TRY( mrw_mem_m_dram_clocks(iv_m_clocks) ); //Port power limit = sum of dimm power limits @@ -88,15 +84,35 @@ throttle::throttle( const fapi2::Target& i_mca, fapi2::R iv_port_power_limit += l_dimm_power_limits[mss::index(l_dimm)]; } + FAPI_INF("Setting up throttle for target %s, Values are: max databus is %d, uplifts are %d %d, runtime throttles are %d %d", + mss::c_str(iv_target), + iv_databus_port_max, + iv_power_uplift, + iv_power_uplift_idle, + iv_runtime_n_slot, + iv_runtime_n_port); + + FAPI_INF("The dimm power limit is %d, port power limit is %d, dram clocks are %d, dimm power curve slopes are %d %d,", + l_dimm_power_limits[0], + iv_port_power_limit, + iv_m_clocks, + iv_pwr_slope[0], + iv_pwr_slope[1]); + + FAPI_INF("DIMM power curve intercepts are %d %d, DIMM power thermal limits are %d %d", + iv_pwr_int[0], + iv_pwr_int[1], + iv_dimm_thermal_limit[0], + iv_dimm_thermal_limit[1]); + + o_rc = fapi2::FAPI2_RC_SUCCESS; FAPI_ASSERT ( (iv_databus_port_max != 0), fapi2::MSS_NO_DATABUS_UTILIZATION() .set_PORT_DATABUS_UTIL(iv_databus_port_max) .set_MCA_TARGET(iv_target), "Failed to get max databus utilization for target %s", mss::c_str(iv_target)); - o_rc = fapi2::FAPI2_RC_SUCCESS; return; - fapi_try_exit: o_rc = fapi2::current_err; FAPI_ERR("Error getting attributes for mss::power_thermal::throttle ctor"); @@ -113,6 +129,54 @@ fapi_try_exit: /// fapi2::ReturnCode throttle::power_regulator_throttles () { + double l_port_power_calc_idle = 0; + double l_port_power_calc_max = 0; + uint32_t l_port_power_slope = 0; + uint32_t l_port_power_int = 0; + double l_calc_util_port = 0; + double l_databus_dimm_max[MAX_DIMM_PER_PORT] = {}; + double l_calc_databus_port_idle[MAX_DIMM_PER_PORT] = {IDLE_UTIL, IDLE_UTIL}; + + FAPI_INF("Starting power regulator throttles"); + + //Decide utilization for each dimm based off of dimm count and power slopes + FAPI_TRY( calc_databus(iv_databus_port_max, l_databus_dimm_max)); + + //Use the dimm utilizations and dimm power slopes to calculate port min and max power + calc_port_power(l_calc_databus_port_idle, + l_databus_dimm_max, + l_port_power_calc_idle, + l_port_power_calc_max); + FAPI_INF("POWER calculated port power is %f", l_port_power_calc_max); + + //Calculate the power curve slope and intercept using the port's min and max power values + FAPI_TRY(calc_power_curve(l_port_power_calc_idle, + l_port_power_calc_max, + l_port_power_slope, + l_port_power_int)); + + FAPI_INF("POWER Port power limit is %d", iv_port_power_limit); + //Calculate the port's utilization to get under watt target using the port's calculated slopes + calc_util_usage(l_port_power_slope, + l_port_power_int, + iv_port_power_limit, + l_calc_util_port); + + FAPI_INF("POWER calc util port is %f", l_calc_util_port); + + //Calculate the N throttles + iv_n_port = power_thermal::throttled_cmds(l_calc_util_port, iv_m_clocks); + + //Set iv_n_slot to the lower value between the slot runtime and iv_n_port + iv_n_slot = (iv_runtime_n_slot != 0) ? std::min (iv_n_port, iv_runtime_n_slot) : iv_n_port; + + //Choose the lowest value of the runtime and the calculated + iv_n_port = (iv_runtime_n_port != 0) ? std::min (iv_n_port, iv_runtime_n_port) : iv_n_port; + + //Use the throttle value to calculate the power that gets to exactly that value + iv_calc_port_maxpower = calc_power_from_n(iv_n_port); + +fapi_try_exit: return fapi2::current_err; } @@ -125,12 +189,70 @@ fapi2::ReturnCode throttle::power_regulator_throttles () /// fapi2::ReturnCode throttle::thermal_throttles () { + double l_dimm_power_idle [MAX_DIMM_PER_PORT] = {}; + double l_dimm_power_max [MAX_DIMM_PER_PORT] = {}; + uint32_t l_dimm_power_slope [MAX_DIMM_PER_PORT] = {}; + uint32_t l_dimm_power_int [MAX_DIMM_PER_PORT] = {}; + double l_calc_util [MAX_DIMM_PER_PORT] = {}; + uint16_t l_n_slots [MAX_DIMM_PER_PORT] = {}; + const auto l_count = count_dimm (iv_target); + + //Calculate the dimm power range for each dimm at max utilization for each + calc_dimm_power(power_thermal::IDLE_UTIL, + iv_databus_port_max, + l_dimm_power_idle, + l_dimm_power_max); + + //Let's calculate the N throttle for each DIMM + for ( const auto& l_dimm : find_targets(iv_target) ) + { + uint8_t l_pos = mss::index(l_dimm); + //Calculate the power curve taking the thermal limit into account + FAPI_TRY( calc_power_curve(l_dimm_power_idle[l_pos], + l_dimm_power_max[l_pos], + l_dimm_power_slope[l_pos], + l_dimm_power_int[l_pos])); + + //Calculate the databus utilization at the calculated power curve + calc_util_usage(l_dimm_power_slope[l_pos], + l_dimm_power_int[l_pos], + iv_dimm_thermal_limit[l_pos], + l_calc_util[l_pos]); + + FAPI_INF("THERMAL Dimm at pos %d's util is %f", l_pos, l_calc_util[l_pos]); + + l_n_slots[l_pos] = power_thermal::throttled_cmds (l_calc_util[l_pos], iv_m_clocks); + + //Set to the min between the two value + //If iv_n_slot == 0 (so uninitialized), set it to the calculated slot value + //The l_n_slot value can't be equal to 0 because there's a dimm installed + if ((l_n_slots[l_pos] < iv_n_slot) || (iv_n_slot == 0)) + { + iv_n_slot = l_n_slots[l_pos]; + } + } + + //Set to lowest value between calculated and runtime + FAPI_INF("THERMAL runtime slot is %d, calc n slot is %d", iv_runtime_n_slot, iv_n_slot); + //Taking the min of the SLOT * (# of dimms on the port) and that maximum allowed port throttle (iv_runtime_port) + //So it's the min of either to actually utilized to the maximum allowed utilization + iv_n_port = std::min(iv_runtime_n_port, uint16_t(iv_n_slot * l_count)); + + iv_n_slot = std::min(iv_n_slot, iv_runtime_n_slot); + + //Now time to get and set iv_calc_port_max from the calculated N throttle + iv_calc_port_maxpower = calc_power_from_n(iv_n_port); return fapi2::FAPI2_RC_SUCCESS; +fapi_try_exit: + FAPI_ERR("Error calculating mss::power_thermal::thermal_throttles()"); + return fapi2::current_err; } + + /// -/// @brief Calculates the min and max power usage for a port based off of power curves and utilizati +/// @brief Calculates the min and max power usage for a port based off of power curves and utilizations /// @param[in] i_idle_util the utilization of the databus in idle mode /// @param[in] i_max_util the utilization of the port at maximum possible (mrw or calculated) /// @param[out] o_port_power_idle max value of port power in cW @@ -138,108 +260,147 @@ fapi2::ReturnCode throttle::thermal_throttles () /// @note Called twice in p9_mss_bulk_pwr_throttles /// @note uses dimm power curves from class variables /// -void throttle::calc_port_power( const double i_idle_util [MAX_DIMM_PER_PORT], - const double i_max_util [MAX_DIMM_PER_PORT], - double& o_port_power_idle, - double& o_port_power_max) +void throttle::calc_port_power(const double i_idle_util [MAX_DIMM_PER_PORT], + const double i_max_util [MAX_DIMM_PER_PORT], + double& o_port_power_idle, + double& o_port_power_max) { //Playing it safe o_port_power_idle = 0; o_port_power_max = 0; + FAPI_INF("max util is %f, %f", i_max_util[0], i_max_util[1]); //Calculate the port power curve info by summing the dimms on the port for ( const auto& l_dimm : mss::find_targets(iv_target) ) { uint32_t l_pos = mss::index(l_dimm); //Sum up the dim's power to calculate the port power curve - o_port_power_idle += - ( i_idle_util[l_pos] / UTIL_CONVERSION * iv_pwr_slope[l_pos]) + iv_pwr_int[l_pos]; - - o_port_power_max += - ( i_max_util[l_pos] / UTIL_CONVERSION * iv_pwr_slope[l_pos]) + iv_pwr_int[l_pos]; + o_port_power_idle += calc_power(i_idle_util[l_pos], l_pos); + o_port_power_max += calc_power(i_max_util[l_pos], l_pos); } //Raise the powers by the uplift percent - o_port_power_idle *= (1 + (double(iv_power_uplift_idle) / PERCENT_CONVERSION)); - o_port_power_max *= (1 + (double(iv_power_uplift) / PERCENT_CONVERSION)); + calc_power_uplift(iv_power_uplift_idle, o_port_power_idle); + calc_power_uplift(iv_power_uplift, o_port_power_max); } /// -/// @brief Calculate the port power curve in order to calculate the port utilization -/// @paramp[in] i_port_power_calc_idle double of the port's power consumption at idle -/// @paramp[in] i_port_power_calc_max double of the port's power consumption at max utilization -/// @paramp[out] o_port_power_slope -/// @paramp[out] o_port_power_int +/// @brief Calculates max and min power usages based off of DIMM power curves +/// @param[in] i_databus_idle idle databus utilization (either calculated or mrw) +/// @param[in] i_databus_max max databus utilization (either calculated or mrw) +/// @param[out] o_dimm_power_idle array of dimm power in cW +/// @param[out] o_dimm_power_max array of dimm power in cW +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK /// @note Called in p9_mss_bulk_pwr_throttles -/// @note Port power curve needed to calculate the port utilization +/// @note used for the thermal throttles /// -fapi2::ReturnCode throttle::calc_port_power_curve (const double& i_port_power_calc_idle, - const double& i_port_power_calc_max, - uint32_t& o_port_power_slope, - uint32_t& o_port_power_int) +void throttle::calc_dimm_power(const double i_databus_idle, + const double i_databus_max, + double o_dimm_power_idle [MAX_DIMM_PER_PORT], + double o_dimm_power_max [MAX_DIMM_PER_PORT]) { - double l_denominator = ((double(iv_databus_port_max) / UTIL_CONVERSION) - IDLE_UTIL); + for ( const auto& l_dimm : mss::find_targets(iv_target) ) + { + const uint8_t l_pos = mss::index(l_dimm); + o_dimm_power_idle[l_pos] = calc_power(i_databus_idle, l_pos); + o_dimm_power_max[l_pos] = calc_power(i_databus_max, l_pos); - FAPI_ASSERT(l_denominator != 0, - fapi2::MSS_CALC_PORT_POWER_CURVE_DIVIDE_BY_ZERO(). - set_PORT_DATABUS_UTIL(iv_databus_port_max). - set_UTIL_CONVERSION(UTIL_CONVERSION). - set_IDLE_UTIL(IDLE_UTIL), - "Denominator = (databus(%d) / UTIL_CONVERSION (%d)) - IDLE_UTIL(%d)", - iv_databus_port_max, - UTIL_CONVERSION, - IDLE_UTIL); + //Raise the powers by the uplift percent - o_port_power_slope = (i_port_power_calc_max - i_port_power_calc_idle) / l_denominator; - o_port_power_int = i_port_power_calc_idle - (o_port_power_slope * IDLE_UTIL); + calc_power_uplift(iv_power_uplift_idle, o_dimm_power_idle[l_pos]); + calc_power_uplift(iv_power_uplift, o_dimm_power_max[l_pos]); + FAPI_INF("Calc_dimm_power: dimm (%d) power max is %f, %f for dimm slope of %d, intercept of %d", + l_pos, + o_dimm_power_max[l_pos], + o_dimm_power_max[l_pos], + iv_pwr_slope[l_pos], + iv_pwr_int[l_pos]); + } +} + +/// +/// @brief Calculate the port power curve in order to calculate the port utilization +/// @param[in] i_power_idle double of the port's power consumption at idle +/// @param[in] i_power_max double of the port's power consumption at max utilization +/// @param[out] o_slope +/// @param[out] o_int +/// @note Called in p9_mss_bulk_pwr_throttles +/// @note Port power curve needed to calculate the port utilization +/// +fapi2::ReturnCode throttle::calc_power_curve(const double i_power_idle, + const double i_power_max, + uint32_t& o_slope, + uint32_t& o_int) +{ + double l_divisor = ((double(iv_databus_port_max) / UTIL_CONVERSION) - IDLE_UTIL); + FAPI_ASSERT ((l_divisor != 0), + fapi2::MSS_CALC_POWER_CURVE_DIVIDE_BY_ZERO() + .set_PORT_DATABUS_UTIL(iv_databus_port_max) + .set_UTIL_CONVERSION(UTIL_CONVERSION) + .set_IDLE_UTIL(IDLE_UTIL), + "Calculated zero for the divisor in calc_power_curve on target %s, the equation is %s", + mss::c_str(iv_target), + "(double(iv_databus_port_max) / UTIL_CONVERSION) - IDLE_UTIL"); + + o_slope = (i_power_max - i_power_idle) / l_divisor; + o_int = i_power_idle - (o_slope * IDLE_UTIL); + FAPI_INF("Calc_power_curve: power idle is %f, max is %f, slope is %d, int is %d", + i_power_idle, + i_power_max, + o_slope, + o_int); return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: + FAPI_INF("Error calculating mss::power_thermal::calc_power_curve"); return fapi2::current_err; + } /// -/// @brief Calculate the port's databus utilization given the port's power curve -/// @paramp[in] i_port_power_slope -/// @paramp[in] i_port_power_int -/// @paramp[out] o_port_util the port's databus utilization +/// @brief Calculate the databus utilization given the power curve +/// @param[in] i_slope +/// @param[in] i_int +/// @param[in] i_power_limit either the port_power_limit or the dimm thermal power limit +/// @param[out] o_port_util the port's databus utilization /// @note Called in p9_mss_bulk_pwr_throttles /// @note Chooses worst case between the maximum allowed databus utilization and the calculated value -/// @notes makes sure that the utilization isn't 0 /// -void throttle::calc_port_util_usage (const uint32_t& i_port_power_slope, - const uint32_t& i_port_power_int, - double& o_port_util) +void throttle::calc_util_usage(const uint32_t i_slope, + const uint32_t i_int, + const uint32_t i_power_limit, + double& o_util) { - o_port_util = (double(iv_port_power_limit) - i_port_power_int) / i_port_power_slope * UTIL_CONVERSION; - o_port_util = (uint32_t(o_port_util) < iv_databus_port_max) ? o_port_util : iv_databus_port_max; - o_port_util = (o_port_util == 0) ? 1 : o_port_util; + o_util = (double(i_power_limit) - i_int) / i_slope * UTIL_CONVERSION; + o_util = (uint32_t(o_util) < iv_databus_port_max) ? o_util : iv_databus_port_max; + o_util = (o_util == 0) ? MIN_UTIL : o_util; } /// -/// @brief Calculates the power max and idle for each dimm using power curves and databus utilization -/// @param[out] o_dimm_power_idle double type for precision, the DIMM power limit in idle state (0 utilization) -/// @param[out] o_dimm_power_max double type for precision, the DIMM power limit at max utilization -/// @note Called in p9_mss_bulk_pwr_throttle for thermal_throttles, eff_config_thermal -/// @note power values are as if dimm is alone on port, using port_databus_util_max +///@brief calculated the output power estimate from the calculated N throttle +///@param[in] i_n_throttle is the throtte N (address operations) that the power (cW) should be calculated fro +///@return the power calculated from the uint /// -void throttle::calc_dimm_power( double o_dimm_power_idle [MAX_DIMM_PER_PORT], - double o_dimm_power_max [MAX_DIMM_PER_PORT]) +uint32_t throttle::calc_power_from_n (const uint16_t i_n_throttle) { - for ( const auto& l_dimm : mss::find_targets(iv_target) ) - { - const auto l_pos = mss::index(l_dimm); + double l_calc_util; + double l_calc_databus_port_max[MAX_DIMM_PER_PORT] = {}; + double l_calc_databus_port_idle[MAX_DIMM_PER_PORT] = {}; + double l_port_power_max = 0; + double l_port_power_idle = 0; - o_dimm_power_idle[l_pos] = iv_pwr_int[l_pos]; - o_dimm_power_max[l_pos] = (double(iv_databus_port_max) / UTIL_CONVERSION) * iv_pwr_slope[l_pos] + - iv_pwr_int[l_pos]; + l_calc_util = calc_util_from_throttles(i_n_throttle, iv_m_clocks); + //Now do everything as port stuff + calc_databus(l_calc_util, l_calc_databus_port_max); - //Raise the powers by the uplift percent - o_dimm_power_idle[l_pos] *= (1 + (iv_power_uplift_idle / PERCENT_CONVERSION)); - o_dimm_power_max[l_pos] *= (1 + (iv_power_uplift / PERCENT_CONVERSION)); - } + calc_port_power(l_calc_databus_port_idle, + l_calc_databus_port_max, + l_port_power_idle, + l_port_power_max); + + return uint32_t(power_thermal::round_up (l_port_power_max)); } /// @@ -250,7 +411,7 @@ void throttle::calc_dimm_power( double o_dimm_power_idle [MAX_DIMM_PER_PORT], /// @note Called in p9_mss_bulk_pwr_throttles /// @used to calculate the port power based off of DIMM power curves /// -fapi2::ReturnCode throttle::calc_databus( const double& i_databus_port_max, +fapi2::ReturnCode throttle::calc_databus( const double i_databus_port_max, double o_databus_dimm_max [MAX_DIMM_PER_PORT]) { uint8_t l_count_dimms = count_dimm (iv_target); @@ -267,22 +428,21 @@ fapi2::ReturnCode throttle::calc_databus( const double& i_databus_port_max, o_databus_dimm_max[mss::index(l_dimm)] = i_databus_port_max / l_count_dimms; } - //If not equal power slopes, set the dimm with the highest power slope - //Should be correct even if only one DIMM installed + //If the power slopes aren't equal, set the dimm with the highest power slope + //Should be correct even if only one DIMM is installed if (iv_pwr_slope[0] != iv_pwr_slope[1]) { o_databus_dimm_max[0] = (iv_pwr_slope[0] > iv_pwr_slope[1]) ? i_databus_port_max : 0; o_databus_dimm_max[1] = (iv_pwr_slope[1] > iv_pwr_slope[0]) ? i_databus_port_max : 0; } - //make sure both aren't equal to 0 + //make sure both are not 0 FAPI_ASSERT ( (o_databus_dimm_max[0] != 0) || (o_databus_dimm_max[1] != 0), fapi2::MSS_NO_DATABUS_UTILIZATION() - .set_PORT_DATABUS_UTIL(iv_databus_port_max) + .set_PORT_DATABUS_UTIL(i_databus_port_max) .set_MCA_TARGET(iv_target), "Failed to calculated databus utilization for target %s", mss::c_str(iv_target)); - fapi_try_exit: return fapi2::current_err; } @@ -291,28 +451,71 @@ fapi_try_exit: /// @brief Perform thermal calculations as part of the effective configuration /// @param[in] i_target the MCS target in which the runtime throttles will be reset /// @return FAPI2_RC_SUCCESS iff ok -/// TK implement/ will be overun? /// fapi2::ReturnCode restore_runtime_throttles( const fapi2::Target& i_target ) { - uint32_t l_run_throttles [PORTS_PER_MCS] = {}; + uint16_t l_run_throttles [MAX_DIMM_PER_PORT] = {}; uint32_t l_max_databus = 0; - uint32_t l_throttle_m_clocks [PORTS_PER_MCS] = {}; + uint32_t l_throttle_m_clocks = {}; - FAPI_TRY( runtime_mem_m_dram_clocks(i_target, l_throttle_m_clocks) ); + FAPI_TRY( mrw_mem_m_dram_clocks(l_throttle_m_clocks) ); FAPI_TRY( mrw_max_dram_databus_util(l_max_databus) ); - for (const auto& l_mca : find_targets (i_target)) + //set runtime throttles to unthrottled value, using max dram utilization and M throttle + //Do I need to check to see if any DIMMS configured on the port? + for (const auto& l_mca : find_targets(i_target)) { - const uint8_t l_pos = mss::index(l_mca); - l_run_throttles[l_pos] = mss::power_thermal::throttled_cmds(l_max_databus, l_throttle_m_clocks[0]); + const auto l_pos = mss::index(l_mca); + + if (mss::count_dimm (l_mca) != 0) + { + l_run_throttles[l_pos] = mss::power_thermal::throttled_cmds (l_max_databus, l_throttle_m_clocks); + } } FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, i_target, l_run_throttles) ); + FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT, i_target, l_run_throttles) ); fapi_try_exit: return fapi2::current_err; } -}//namespace power_thermal +/// +/// @brief Update the runtime throttles to the worst case of the general throttle values and the runtime values +/// @param[in] i_target the MCS target in which the runtime throttles will be set +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode update_runtime_throttles( const std::vector< fapi2::Target >& i_targets ) +{ + for (const auto& l_mcs : i_targets) + { + uint16_t l_run_slot [PORTS_PER_MCS] = {}; + uint16_t l_run_port [PORTS_PER_MCS] = {}; + uint16_t l_calc_slot [PORTS_PER_MCS] = {}; + uint16_t l_calc_port [PORTS_PER_MCS] = {}; + + FAPI_TRY(runtime_mem_throttled_n_commands_per_slot(l_mcs, l_run_slot)); + FAPI_TRY(runtime_mem_throttled_n_commands_per_port(l_mcs, l_run_port)); + FAPI_TRY(mem_throttled_n_commands_per_slot(l_mcs, l_calc_slot)); + FAPI_TRY(mem_throttled_n_commands_per_port(l_mcs, l_calc_port)); + + for (const auto& l_mca : find_targets(l_mcs)) + { + const auto l_pos = mss::index(l_mca); + //Choose the worst case between runtime and calculated throttles + //Have to make sure the calc_slot isn't equal to 0 though + l_run_slot[l_pos] = (l_calc_slot[l_pos] != 0) ? std::min(l_run_slot[l_pos], l_calc_slot[l_pos]) : l_run_slot[l_pos]; + l_run_port[l_pos] = (l_calc_port[l_pos] != 0) ? std::min(l_run_port[l_pos], l_calc_port[l_pos]) : l_run_port[l_pos]; + FAPI_INF("New runtime throttles dimm %d for slot are %d, port are %d", l_pos, l_run_slot[l_pos], l_run_port[l_pos]); + } + + FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_run_port) ); + FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_run_slot) ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +}//namespace power_thermal }//namespace mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H index 3259608ce..876e277a3 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H @@ -46,9 +46,12 @@ enum throttle_const : size_t { // Dram data bus utilization is bus utilization / 4 DRAM_BUS_UTILS = 4, + //10000 to convert to and from c% UTIL_CONVERSION = 10000, PERCENT_CONVERSION = 100, - MIN_UTIL = 1, + + //MIN_UTIL and IDLE_UTIL are in c% + MIN_UTIL = 100, IDLE_UTIL = 0, }; /// @@ -58,25 +61,47 @@ enum throttle_const : size_t class throttle { private: + /// + /// @brief Calculate the power (cW) of inputs and the power curve + /// @tparam T + /// @param[in] i_util the databus utilization that the power will be based on + /// @param[in] l_pos the dimm position for the power value being calculated. + /// @return Integral type T + /// + template + inline T calc_power (const T i_util, const size_t i_pos) + { + return ((i_util / UTIL_CONVERSION) * iv_pwr_slope[i_pos]) + iv_pwr_int[i_pos]; + } + + /// + /// @brief Raise the o_value by the percent passed in + /// @param[in] i_uplift the percent the o_Value should be raised by + /// @param[out] o_value the value that will be modified + /// + inline void calc_power_uplift (const uint8_t i_uplift, double& o_value) + { + o_value *= (1 + (double(i_uplift) / PERCENT_CONVERSION)); + } public: const fapi2::Target& iv_target; //dimm level uint32_t iv_databus_port_max; + //TK change thermal limit as well as power curves uint8_t iv_power_uplift_idle; uint8_t iv_power_uplift; - uint32_t iv_runtime_n_slot; - uint32_t iv_runtime_n_port; + uint16_t iv_runtime_n_slot; + uint16_t iv_runtime_n_port; uint32_t iv_m_clocks; uint32_t iv_dimm_thermal_limit[MAX_DIMM_PER_PORT] = {}; uint16_t iv_pwr_slope[MAX_DIMM_PER_PORT] = {}; uint16_t iv_pwr_int[MAX_DIMM_PER_PORT] = {}; - uint32_t iv_n_slot; - uint32_t iv_n_port; + uint16_t iv_n_slot; + uint16_t iv_n_port; uint32_t iv_port_power_limit; - uint32_t iv_port_maxpower; uint32_t iv_calc_port_maxpower; //default ctor deleted @@ -95,71 +120,82 @@ class throttle ~throttle() = default; /// - /// @brief Calculates the min and max power usage for a port based off of power curves and utilizati + /// @brief Calculates the min and max power usage for a port /// @param[in] i_idle_util the utilization of the databus in idle mode /// @param[in] i_max_util the utilization of the port at maximum possible (mrw or calculated) /// @param[out] o_port_power_idle max value of port power in cW /// @param[out] o_port_power_max max value of port power in cW /// @note Called twice in p9_mss_bulk_pwr_throttles - /// @note uses dimm power curves from class variables - /// - void calc_port_power(const double i_idle_util [MAX_DIMM_PER_PORT], - const double i_max_util [MAX_DIMM_PER_PORT], - double& o_port_power_idle, - double& o_port_power_max); - /// - /// @brief Calculate the port power curve in order to calculate the port utilization - /// @paramp[in] i_port_power_calc_idle double of the port's power consumption at idle - /// @paramp[in] i_port_power_calc_max double of the port's power consumption at max utilization - /// @paramp[out] o_port_power_slope - /// @paramp[out] o_port_power_int - /// @return FAPI2_RC_SUCCESS iff success + /// + void calc_port_power( const double i_idle_util [MAX_DIMM_PER_PORT], + const double i_max_util [MAX_DIMM_PER_PORT], + double& o_port_power_idle, + double& o_port_power_max); + /// + /// @brief Calculates max and min power usages based off of DIMM power curves + /// @param[in] i_databus_port_max max databus utilization for the port (either calculated or mrw) + /// @param[in] i_port_power_calc_idle double of the port's power consumption at idle + /// @param[out] o_dimm_power_idle array of dimm power in cW + /// @param[out] o_dimm_power_max array of dimm power in cW /// @note Called in p9_mss_bulk_pwr_throttles - /// @note Port power curve needed to calculate the port utilization + /// @note used for the thermal throttles /// - fapi2::ReturnCode calc_port_power_curve(const double& i_port_power_calc_idle, - const double& i_port_power_calc_max, - uint32_t& o_port_power_slope, - uint32_t& o_port_power_int); + void calc_dimm_power(const double i_databus_idle, + const double i_databus_max, + double o_dimm_power_idle [MAX_DIMM_PER_PORT], + double o_dimm_power_max [MAX_DIMM_PER_PORT]); + /// - /// @brief Calculate the port's databus utilization given the port's power curve - /// @paramp[in] i_port_power_slope - /// @paramp[in] i_port_power_int - /// @paramp[out] o_port_util the port's databus utilization + /// @brief Calculate the power curve in order to calculate databus utilization + /// @param[in] i_power_idle double of the port's power consumption at idle + /// @param[in] i_power_max double of the port's power consumption at max utilization + /// @param[out] o_power_slope + /// @param[out] o_power_int + /// @note Called in p9_mss_bulk_pwr_throttles + /// @note Power curve needed to calculate the utilization + /// + fapi2::ReturnCode calc_power_curve(const double i_power_idle, + const double i_power_max, + uint32_t& o_power_slope, + uint32_t& o_power_int); + /// + /// @brief Calculate the databus utilization given the power curve + /// @param[in] i_slope + /// @param[in] i_int + /// @param[in] i_power_limit either iv_port_power_limit or thermal_power_limit depending on throttle type + /// @param[out] o_port_util the port's databus utilization /// @note Called in p9_mss_bulk_pwr_throttles /// @note Chooses worst case between the maximum allowed databus utilization and the calculated value - /// @notes makes sure that the utilization isn't 0 /// - void calc_port_util_usage(const uint32_t& i_port_power_slope, - const uint32_t& i_port_power_int, - double& o_port_util); - + void calc_util_usage(const uint32_t i_slope, + const uint32_t i_int, + const uint32_t i_power_limit, + double& o_util); /// - /// @brief Calculates the power max and idle for each dimm using power curves and databus utilization - /// @param[out] o_dimm_power_idle double type for precision, the DIMM power limit in idle state (0 utilization) - /// @param[out] o_dimm_power_max double type for precision, the DIMM power limit at max utilization - /// @note Called in p9_mss_bulk_pwr_throttle for thermal_throttles, eff_config_thermal - /// @note power values are as if dimm is alone on port, using port_databus_util_max + ///@brief calculated the output power estimate from the calculated N throttle + ///@param[in] i_n_port is the throtte N (address operations) that the power (cW) is be calculated from + ///@return the power calculated from the uint /// - void calc_dimm_power(double o_dimm_power_idle [MAX_DIMM_PER_PORT], - double o_dimm_power_max [MAX_DIMM_PER_PORT]); + uint32_t calc_power_from_n (const uint16_t i_n_port); + /// - /// @brief Converts the port maximum databus to a dimm level based on powerslopes and dimms installed + /// @brief Converts the port maximum databus util to a dimm level based on powerslopes and dimms installed /// @param[in] i_databus_port_max max databus utilization for the port (either calculated or mrw) /// @param[out] o_databus_dimm_max array of dimm utilization values /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK /// @note Called in p9_mss_bulk_pwr_throttles /// @used to calculate the port power based off of DIMM power curves /// - fapi2::ReturnCode calc_databus(const double& i_databus_port_max, - double o_databus_dimm_max [MAX_DIMM_PER_PORT]); + fapi2::ReturnCode calc_databus( const double i_databus_port_max, + double o_databus_dimm_max [MAX_DIMM_PER_PORT]); /// - /// @brief Set ATTR_MSS_CHANNEL_PAIR_MAXPOWER and ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, + /// @brief Calculate ATTR_MSS_CHANNEL_PAIR_MAXPOWER and ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Called in p9_mss_bulk_pwr_throttles - /// @note determines the throttle levels based off of the port's power curve, - /// sets the slot throttles to the same + /// @note determines the throttle levels based off of the port's power curve, max databus utilization, + /// and memwat target. + /// @note currently sets the slot and port throttles to the same value /// fapi2::ReturnCode power_regulator_throttles (); @@ -179,15 +215,16 @@ class throttle /// @param[in] i_num_dram_clocks window of M DRAM clocks /// @return number of throttled commands allowed /// @note Uses N/M Throttling. -/// Equation: (DRAM data bus utilization Percent / 10000 ) = ((N * M) / 4 ) -/// Equation: N = (DRAM data bus utilization Percent * M) / (4 * 10000) +/// Equation: N = (DRAM data bus utilization * M) / (4 * 10000) +/// inline uint32_t throttled_cmds(const uint32_t i_databus_util, const uint32_t i_num_dram_clocks) { constexpr uint64_t l_divisor = DRAM_BUS_UTILS * UTIL_CONVERSION; const uint64_t l_dividend = i_databus_util * i_num_dram_clocks; const uint64_t l_result = l_dividend / l_divisor; - return l_result; + //Make sure N is not equal to 0, or we brick the dram until reboot + return ((l_result == 0) ? 1 : l_result); } /// @@ -196,7 +233,7 @@ inline uint32_t throttled_cmds(const uint32_t i_databus_util, const uint32_t i_n /// @param[in] i_num_dram_clocks window of M DRAM clocks /// @return number of throttled commands allowed /// @note Uses N/M Throttling. -/// Equation: databus utilization = (N * 4 * 100000) / M +/// @note DRAM databus utilization = N * 4 * 10000 / M /// inline double calc_util_from_throttles(const uint16_t i_n_throttles, const uint32_t i_num_dram_clocks) { @@ -205,6 +242,24 @@ inline double calc_util_from_throttles(const uint16_t i_n_throttles, const uint3 } +/// +/// @brief Determines if the double has decimal digits and adds 1 and rounds if true +/// @param[in] io_val the double to be rounded up if trialing digits +/// @return the input value rounded up to the next whole digit +/// @note Called in p9_mss_bulk_pwr_throttles +/// +inline uint32_t round_up(double i_val) +{ + //convert to uint to truncate decimals and convert back to double for comparison + uint32_t temp = uint32_t (i_val); + + //if not equal, lost something from truncating, so add 1 + temp += (temp == i_val) ? 0 : 1; + + //Truncate final value + return temp; +} + /// /// @brief Perform thermal calculations as part of the effective configuration /// @param[in] i_target the MCS target in which the runtime throttles will be reset @@ -212,6 +267,13 @@ inline double calc_util_from_throttles(const uint16_t i_n_throttles, const uint3 /// fapi2::ReturnCode restore_runtime_throttles( const fapi2::Target& i_target ); +/// +/// @brief Update the runtime throttles to the worst case of the general throttle values and the runtime values +/// @param[in] i_target the MCS target in which the runtime throttles will be set +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode update_runtime_throttles(const std::vector< fapi2::Target >& i_targets); + }//power_thermal }// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H index c00bbac72..ffc2b59ff 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H @@ -127,7 +127,6 @@ inline fapi2::Target find_target( const fapi2::Target return i_target.getParent(); } - /// /// @brief find all the dimm connected to an MCS /// @param[in] i_target a fapi2::Target MCS @@ -453,8 +452,6 @@ fapi2::ReturnCode find_key_from_value(const std::vector >& i_ve }// find_value_from_key - - /// /// @brief find a key value from a C-style array of STL pairs /// @tparam T input type diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C index 77cbacf5d..2b7d43395 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C @@ -30,7 +30,7 @@ // *HWP HWP Owner: Jacob Harvey // *HWP HWP Backup: Brian Silver // *HWP Team: Memory -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HB #include @@ -38,6 +38,7 @@ #include #include #include +#include #include using fapi2::TARGET_TYPE_MCS; @@ -46,35 +47,58 @@ using fapi2::TARGET_TYPE_DIMM; extern "C" { - /// - /// @brief Set ATTR_MSS_PORT_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT - /// @param[in] i_targets vector of MCS's on the same VDDR domain - /// @param[in] thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits - /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK - /// @note Called in p9_mss_bulk_pwr_throttles - /// @note determines the throttle levels based off of the port's power curve, - /// sets the slot throttles to the same - /// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles - /// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value - /// +/// +/// @brief Set ATTR_MSS_PORT_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT +/// @param[in] i_targets vector of MCS's on the same VDDR domain +/// @param[in] thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK +/// @note Called in p9_mss_bulk_pwr_throttles +/// @note determines the throttle levels based off of the port's power curve, +/// sets the slot throttles to the same +/// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles +/// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value +/// fapi2::ReturnCode p9_mss_bulk_pwr_throttles( const std::vector< fapi2::Target >& i_targets, throttle_type t) { FAPI_INF("Start bulk_pwr_throttles"); -//To be implemented in next commit -#if 0 //Check for THERMAL if (t == THERMAL) { for ( const auto& l_mcs : i_targets) { + uint16_t l_slot [mss::PORTS_PER_MCS] = {}; + uint16_t l_port [mss::PORTS_PER_MCS] = {}; + uint32_t l_power [mss::PORTS_PER_MCS] = {}; + for (const auto& l_mca : mss::find_targets(l_mcs)) { - //mss::power_thermal::throttle l_pwr_struct(l_mca); - //FAPI_TRY (l_pwr_struct.thermal_throttles() ); + //Don't run if there are no dimms on the port + if (mss::count_dimm(l_mca) == 0) + { + continue; + } + + const uint8_t l_pos = mss::index(l_mca); + fapi2::ReturnCode l_rc; + mss::power_thermal::throttle l_pwr_struct(l_mca, l_rc); + FAPI_TRY(l_rc, "Error constructing mss:power_thermal::throttle object for target %s", + mss::c_str(l_mca)); + FAPI_TRY (l_pwr_struct.thermal_throttles()); + + l_slot[l_pos] = l_pwr_struct.iv_n_slot; + l_port[l_pos] = l_pwr_struct.iv_n_port; + l_power[l_pos] = l_pwr_struct.iv_calc_port_maxpower; } + + FAPI_INF("Port maxpower is %d, %d slot is %d, %d, port is %d %d", + l_power[0], l_power[1], l_slot[0], l_slot[1], l_port[0], l_port[1]); + + FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_PORT_MAXPOWER, l_mcs, l_power)); + FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_slot)); + FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_port)); } //Equalize throttles @@ -84,20 +108,46 @@ extern "C" { for ( const auto& l_mcs : i_targets) { + uint16_t l_slot [mss::PORTS_PER_MCS] = {}; + uint16_t l_port [mss::PORTS_PER_MCS] = {}; + uint32_t l_power [mss::PORTS_PER_MCS] = {}; + for (const auto& l_mca : mss::find_targets(l_mcs)) { - //mss::power_thermal::throttle l_pwr_struct(l_mca); - //FAPI_TRY (l_pwr_struct.power_regulator_throttles() ); + //Don't run if there are no dimms on the port + if (mss::count_dimm(l_mca) == 0) + { + continue; + } + + uint8_t l_pos = mss::index(l_mca); + fapi2::ReturnCode l_rc; + mss::power_thermal::throttle l_pwr_struct(l_mca, l_rc); + FAPI_TRY(l_rc, "Error constructing mss:power_thermal::throttle object for target %s", + mss::c_str(l_mca)); + + FAPI_TRY (l_pwr_struct.power_regulator_throttles()); + + l_slot[l_pos] = l_pwr_struct.iv_n_slot; + l_port[l_pos] = l_pwr_struct.iv_n_port; + l_power[l_pos] = l_pwr_struct.iv_calc_port_maxpower; } + + FAPI_INF("Port maxpower is %d, %d slot is %d, %d, port is %d %d", + l_power[0], l_power[1], l_slot[0], l_slot[1], l_port[0], l_port[1]); + FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_PORT_MAXPOWER, l_mcs, l_power)); + FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_slot)); + FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_port)); } //Equalize throttles } - FAPI_INF("End bulk_pwr_throttles"); + return fapi2::FAPI2_RC_SUCCESS; + fapi_try_exit: -#endif + FAPI_ERR("Error calculating bulk_pwr_throttles"); return fapi2::current_err; } } //extern C diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.H b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.H index 25215dbc4..f0acad89b 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.H +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.H @@ -30,7 +30,7 @@ // *HWP HWP Owner: Jacob Harvey // *HWP HWP Backup: Brian Silver // *HWP Team: Memory -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HB #ifndef __P9_MSS_BULK_PWR_THROTTLES__ diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C index 8306dc750..2e755c647 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C @@ -196,18 +196,6 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_WATT_TARGET, i_target, l_mem_watt_target ) ); } - //Values taken from Mike Pardeik. Calculated to reach 90% util, will be removed once eff_config_thermal is implemented - { - uint32_t l_throttled_n_commands[mss::PORTS_PER_MCS] = {0x73, 0x73}; - FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, i_target, - l_throttled_n_commands ) ); - } - - { - uint32_t l_throttled_n_commands[mss::PORTS_PER_MCS] = {0x73, 0x73}; - FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT, i_target, - l_throttled_n_commands ) ); - } { uint16_t l_cal_step[mss::PORTS_PER_MCS] = {0xFAC0, 0xFAC0}; diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C index 361c3dbe6..3935ef805 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C @@ -30,7 +30,7 @@ // *HWP HWP Owner: Jacob Harvey // *HWP HWP Backup: Brian Silver // *HWP Team: Memory -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HB #include @@ -40,14 +40,15 @@ #include #include #include +#include #include extern "C" { -/// -/// @brief Perform thermal calculations as part of the effective configuration -/// @param[in] i_targets an array of MCS targets all on the same VDDR domain -/// @return FAPI2_RC_SUCCESS iff ok -/// + /// + /// @brief Perform thermal calculations as part of the effective configuration + /// @param[in] i_targets an array of MCS targets all on the same VDDR domain + /// @return FAPI2_RC_SUCCESS iff ok + /// fapi2::ReturnCode p9_mss_eff_config_thermal( const std::vector< fapi2::Target >& i_targets ) { @@ -61,17 +62,18 @@ extern "C" //Gotta convert into fapi2::buffers. Not very elegant //Do it here or in the encode and decode functions - std::vector< uint64_t > l_tslope (mss::SIZE_OF_POWER_CURVES_ATTRS, 0); - std::vector< uint64_t > l_tintercept (mss::SIZE_OF_POWER_CURVES_ATTRS, 0); - std::vector< uint64_t > l_tthermal_power_limit (mss::SIZE_OF_THERMAL_ATTR, 0); + //Not that pretty :( + std::vector< uint64_t > l_tslope (mss::power_thermal::SIZE_OF_POWER_CURVES_ATTRS, 0); + std::vector< uint64_t > l_tintercept (mss::power_thermal::SIZE_OF_POWER_CURVES_ATTRS, 0); + std::vector< uint64_t > l_tthermal_power_limit (mss::power_thermal::SIZE_OF_THERMAL_ATTR, 0); - std::vector< fapi2::buffer< uint64_t > > l_slope (mss::SIZE_OF_POWER_CURVES_ATTRS); - std::vector< fapi2::buffer< uint64_t > > l_intercept (mss::SIZE_OF_POWER_CURVES_ATTRS); - std::vector< fapi2::buffer< uint64_t > > l_thermal_power_limit (mss::SIZE_OF_THERMAL_ATTR); + std::vector> l_slope (mss::power_thermal::SIZE_OF_POWER_CURVES_ATTRS); + std::vector> l_intercept (mss::power_thermal::SIZE_OF_POWER_CURVES_ATTRS); + std::vector> l_thermal_power_limit (mss::power_thermal::SIZE_OF_THERMAL_ATTR); - FAPI_TRY ( mss::mrw_pwr_slope (l_tslope.data() )); - FAPI_TRY ( mss::mrw_pwr_intercept (l_tintercept.data()) ); - FAPI_TRY ( mss::mrw_thermal_memory_power_limit (l_tthermal_power_limit.data()) ); + FAPI_TRY( mss::mrw_pwr_slope (l_tslope.data() )); + FAPI_TRY( mss::mrw_pwr_intercept (l_tintercept.data()) ); + FAPI_TRY( mss::mrw_thermal_memory_power_limit (l_tthermal_power_limit.data()) ); for (size_t i = 0; i < l_slope.size(); ++i) { @@ -79,9 +81,22 @@ extern "C" l_intercept[i] = fapi2::buffer(l_tintercept[i]); } - for ( const auto& l_mcs : i_targets ) + for (size_t i = 0; i < l_thermal_power_limit.size(); ++i) + { + l_thermal_power_limit[i] = fapi2::buffer (l_tthermal_power_limit[i]); + } + + //Restore runtime_throttles from safemode setting + //Decode and set power curve attributes at the same time + for (const auto& l_mcs : i_targets ) { - FAPI_TRY (mss::power_thermal::get_power_attrs(l_mcs, + //Not doing any work if there are no dimms installed + if (mss::count_dimm(l_mcs) == 0) + { + continue; + } + + FAPI_TRY( mss::power_thermal::get_power_attrs(l_mcs, l_slope, l_intercept, l_thermal_power_limit, @@ -90,13 +105,11 @@ extern "C" l_total_slope, l_total_int, l_thermal_power)); - + //Sets throttles to max_databus_util value + FAPI_INF("Restoring throttles"); FAPI_TRY( mss::power_thermal::restore_runtime_throttles(l_mcs)); - //Set the power attribute (TOTAL_PWR) to just VDDR for IPL, restoreto vddr+vpp later for OCC - //Set here because bulk_pwr_throttles takes input as attributes, and I can't change which attribute it takes - //So we have to use TOTAL_PWR_SLOPE - //Setting here and not in set_power_attrs because get_power_attrs decodes the attributes and stores them + //Set the power attribute (TOTAL_PWR) to just VDDR for the POWER bulk_pwr_throttles, restore to vddr+vpp later for OCC FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_TOTAL_PWR_SLOPE, l_mcs, l_vddr_slope)); @@ -104,15 +117,27 @@ extern "C" FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_TOTAL_PWR_INTERCEPT, l_mcs, l_vddr_int)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_DIMM_THERMAL_LIMIT, + l_mcs, + l_thermal_power)); } + FAPI_INF("Starting bulk_pwr"); //get the thermal limits, done per dimm and set to worst case for the slot and port throttles - FAPI_TRY (p9_mss_bulk_pwr_throttles(i_targets, THERMAL)); + //Bulk_pwr sets the general, all purpose ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, _PER_PORT, and MAXPOWER ATTRs + FAPI_TRY( p9_mss_bulk_pwr_throttles(i_targets, POWER)); + + //Set runtime throttles to worst case between ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT + //and ATTR_MSS_MEM_RUNTIME_THROTTLED_N_COMMANDS_PER_SLOT and the _PORT equivalents also + FAPI_INF("Starting update"); + FAPI_TRY( mss::power_thermal::update_runtime_throttles (i_targets)); + FAPI_INF("finished update"); - //Set VDDR+VPP + //Set VDDR+VPP power curve values for ( const auto& l_mcs : i_targets ) { - FAPI_TRY (mss::power_thermal::get_power_attrs(l_mcs, + FAPI_TRY( mss::power_thermal::get_power_attrs(l_mcs, l_slope, l_intercept, l_thermal_power_limit, @@ -122,9 +147,10 @@ extern "C" l_total_int, l_thermal_power)); - FAPI_TRY( mss::power_thermal::restore_runtime_throttles(l_mcs)); + FAPI_INF( "VDDR+VPP power curve slope is %d, int is %d, thermal_power is %d", l_total_slope[0][0], l_total_int[0][0], + l_thermal_power[0][0]); - //Set the power attribute (TOTAL_PWR) to just VDDR for IPL, restoreto vddr+vpp later for OCC + //Set the power attribute (TOTAL_PWR) to vpp+vdd power slope FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_TOTAL_PWR_SLOPE, l_mcs, l_total_slope)); @@ -134,8 +160,13 @@ extern "C" l_total_int)); } + //Run thermal throttles with the VDDR+VPP power curves + FAPI_TRY( p9_mss_bulk_pwr_throttles(i_targets, THERMAL)); + //Update everything to worst case + FAPI_TRY( mss::power_thermal::update_runtime_throttles (i_targets)); - FAPI_INF("End effective config thermal"); + //Done + FAPI_INF( "End effective config thermal"); fapi_try_exit: return fapi2::FAPI2_RC_SUCCESS; diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.H b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.H index 9071f5a1c..0822da50c 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.H +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.H @@ -27,10 +27,10 @@ /// @file p9_mss_eff_config_thermal.H /// @brief Perform thermal calculations as part of the effective configuration /// -// *HWP HWP Owner: Andre Marin +// *HWP HWP Owner: Jacob Harvey // *HWP HWP Backup: Brian Silver // *HWP Team: Memory -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HB #ifndef __P9_MSS_EFF_CONFIG_THERMAL__ @@ -39,7 +39,8 @@ #include #include -typedef fapi2::ReturnCode (*p9_mss_eff_config_thermal_FP_t) (const std::vector>&); +typedef fapi2::ReturnCode (*p9_mss_eff_config_thermal_FP_t) (const + std::vector< fapi2::Target >&); extern "C" { @@ -50,7 +51,6 @@ extern "C" /// @return FAPI2_RC_SUCCESS iff ok /// fapi2::ReturnCode p9_mss_eff_config_thermal( const std::vector< fapi2::Target >& i_targets ); - } #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_throttle_mem.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_throttle_mem.C index e1c27e4b3..15783f487 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_throttle_mem.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_throttle_mem.C @@ -53,8 +53,8 @@ extern "C" for (const auto& l_mca : mss::find_targets (i_target)) { - uint32_t l_runtime_port = 0; - uint32_t l_runtime_slot = 0; + uint16_t l_runtime_port = 0; + uint16_t l_runtime_slot = 0; uint32_t l_throttle_denominator = 0; FAPI_TRY( mss::mem_m_dram_clocks( l_mca, l_throttle_denominator) ); 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 8809ad0f4..cbf1fe988 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 @@ -33,7 +33,7 @@ // *HWP HWP Owner: Jacob Harvey // *HWP HWP Backup: Brian Silver // *HWP Team: Memory -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HB #include @@ -46,6 +46,7 @@ #include #include #include +#include #include using fapi2::TARGET_TYPE_MCS; @@ -65,43 +66,49 @@ extern "C" { for( const auto& l_mcs : i_targets ) { - //TODO RTC 160048 Complete implementing (calculating power and per slot throttles) - JLH uint32_t l_databus_util [mss::PORTS_PER_MCS]; - uint32_t l_throttled_cmds_port[mss::PORTS_PER_MCS]; - uint32_t l_throttled_cmds_slot[mss::PORTS_PER_MCS]; + uint32_t l_dram_clocks = 0; + + uint16_t l_throttled_cmds_port[mss::PORTS_PER_MCS]; + uint16_t l_throttled_cmds_slot[mss::PORTS_PER_MCS]; uint32_t l_max_power[mss::PORTS_PER_MCS]; - uint32_t l_dram_clocks = 0; FAPI_TRY( mss::mrw_mem_m_dram_clocks(l_dram_clocks) ); - + //Util attribute set by OCC FAPI_TRY( mss::databus_util(l_mcs, l_databus_util) ); for( const auto& l_mca : mss::find_targets(l_mcs) ) { const auto l_port_num = mss::index( l_mca ); + //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_INF( "MRW dram clock window: %d, databus utilization: %d", l_dram_clocks, - l_databus_util ); - - // Calculate programmable N address operations within M dram clock window - l_throttled_cmds_port[l_port_num] = mss::power_thermal::throttled_cmds( l_databus_util[l_port_num], l_dram_clocks ); - l_throttled_cmds_slot[l_port_num] = mss::power_thermal::throttled_cmds( l_databus_util[l_port_num], l_dram_clocks ); - //TK - actually implement function - JLH - //Quick hard code for API purposes - l_max_power[l_port_num] = 2088; - FAPI_INF( "Calculated N commands per port [%d] = %d", + l_databus_util); + + //Calculate programmable N address operations within M dram clock window + l_throttled_cmds_port[l_port_num] = mss::power_thermal::throttled_cmds(l_databus_util[l_port_num], + l_dram_clocks ); + l_throttled_cmds_slot[l_port_num] = l_throttled_cmds_port[l_port_num]; + //Calculate the port power needed to reach the calculated N value + l_max_power[l_port_num] = l_throttle.calc_power_from_n(l_throttled_cmds_slot[l_port_num]); + + FAPI_INF( "Calculated N commands per port [%d] = %d commands, maxpower is %d", l_port_num, - l_throttled_cmds_port[l_port_num]); + l_throttled_cmds_port[l_port_num], + l_max_power[l_port_num]); }// end for FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_PORT_MAXPOWER, l_mcs, l_max_power) ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT, + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_throttled_cmds_slot) ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_throttled_cmds_port) ); } diff --git a/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml index b0353804e..7762d231b 100644 --- a/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml +++ b/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml @@ -1182,7 +1182,7 @@ of M DRAM clocks setting for cfg_nm_n_per_port. - uint32 + uint16 2 mem_throttled_n_commands_per_port @@ -1209,7 +1209,7 @@ TARGET_TYPE_MCS This is the throttle numerator setting for cfg_nm_n_per_slot - uint32 + uint16 2 mem_throttled_n_commands_per_slot @@ -1345,6 +1345,21 @@ port_maxpower + + ATTR_MSS_DIMM_THERMAL_LIMIT + TARGET_TYPE_MCS + + DIMM Max Power based on a thermal limit + Decoded from ATTR_MSS_MRW_THERMAL_POWER_LIMIT + + + uint32 + + cW + 2 2 + dimm_thermal_limit + + ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT TARGET_TYPE_MCS @@ -1353,7 +1368,7 @@ M DRAM clocks setting for cfg_nm_n_per_port. - uint32 + uint16 2 runtime_mem_throttled_n_commands_per_port @@ -1375,7 +1390,7 @@ TARGET_TYPE_MCS Runtime throttle numerator setting for cfg_nm_n_per_slot - uint32 + uint16 2 runtime_mem_throttled_n_commands_per_slot diff --git a/src/import/chips/p9/procedures/xml/attribute_info/memory_mrw_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/memory_mrw_attributes.xml index f4737af85..8c59ba71f 100755 --- a/src/import/chips/p9/procedures/xml/attribute_info/memory_mrw_attributes.xml +++ b/src/import/chips/p9/procedures/xml/attribute_info/memory_mrw_attributes.xml @@ -102,6 +102,7 @@ 100 + 0xffffe00002CC03AE mrw_pwr_intercept @@ -132,6 +133,7 @@ 100 + 0xffffe00003FD0546 mrw_pwr_slope @@ -246,7 +248,7 @@ ATTR_MSS_MRW_POWER_CONTROL_REQUESTED TARGET_TYPE_SYSTEM - Memory power control settings programmed during IPL + Memory power control settings programmed during IPL Used by OCC when exiting idle power-save mode uint8 diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml index 12336a55b..7007f8c39 100644 --- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml +++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml @@ -161,7 +161,7 @@ - RC_MSS_CALC_PORT_POWER_CURVE_DIVIDE_BY_ZERO + RC_MSS_CALC_POWER_CURVE_DIVIDE_BY_ZERO Denominator equals 0 diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index 3a2ce60d9..77e1be280 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -9118,8 +9118,8 @@ firmware notes: Used as override attribute for pstate procedure Initialized and used by HWPs. - - + + 2 volatile-zeroed @@ -9159,8 +9159,8 @@ firmware notes: Used as override attribute for pstate procedure This is the throttle numerator setting for cfg_nm_n_per_slot - - + + 2 volatile-zeroed @@ -9172,6 +9172,26 @@ firmware notes: Used as override attribute for pstate procedure + + MSS_DIMM_THERMAL_LIMIT + + DIMM Max Power based on a thermal limit + Decoded from ATTR_MSS_MRW_THERMAL_POWER_LIMIT + + + + + 2,2 + + volatile-zeroed + + + + ATTR_MSS_DIMM_THERMAL_LIMIT + DIRECT + + + EFF_NUM_DIES_PER_PACKAGE Specifies the number of DRAM dies per package. Initialized and used by HWPs. @@ -9632,8 +9652,8 @@ firmware notes: Used as override attribute for pstate procedure Initialized and used by HWPs. - - + + 2 volatile-zeroed @@ -9670,8 +9690,8 @@ firmware notes: Used as override attribute for pstate procedure Runtime throttle numerator setting for cfg_nm_n_per_slot - - + + 2 volatile-zeroed diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml index 7b821437a..11cb44eb5 100755 --- a/src/usr/targeting/common/xmltohb/target_types.xml +++ b/src/usr/targeting/common/xmltohb/target_types.xml @@ -1812,6 +1812,7 @@ EFF_DRAM_MFG_ID EFF_DRAM_TRRD_DLR BAD_DQ_BITMAP + MSS_DIMM_THERMAL_LIMIT -- cgit v1.2.1