From fe09e7b9d29b238b07f8d1017fc0c195843c654f Mon Sep 17 00:00:00 2001 From: Michael Pardeik Date: Tue, 1 Oct 2019 15:55:23 -0500 Subject: exp_mss_eff_config_thermal fixes Fix pwr_throttles call for thermal throttle type Fix equalize throttles call for power throttling type Updates to handle DDIMM and non-DDIMM differences Clarify related power and thermal MRW attribute descriptions Change-Id: I34ecfd4bbb97f1e74c258a474e0b5daf3a4dcbbb Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/84620 Tested-by: FSP CI Jenkins Tested-by: Jenkins Server Dev-Ready: STEPHEN GLANCY Tested-by: HWSV CI Tested-by: Hostboot CI Reviewed-by: STEPHEN GLANCY Reviewed-by: Mark Pizzutillo Reviewed-by: Jennifer A Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/84699 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Christian R Geddes --- .../hwp/memory/exp_mss_eff_config_thermal.C | 127 ++++++++++++--------- .../hwp/memory/lib/power_thermal/exp_decoder.C | 74 +++++++----- .../hwp/memory/lib/power_thermal/exp_throttle.C | 6 +- .../hwp/memory/lib/power_thermal/exp_throttle.H | 1 + .../memory/lib/power_thermal/exp_throttle_traits.H | 15 ++- .../hwp/memory/lib/mss_attribute_accessors.H | 63 +++++----- .../hwp/memory/lib/power_thermal/throttle.H | 1 + .../memory/lib/utils/power_thermal/gen_throttle.H | 44 +++++-- .../generic_memory_mrw_attributes.xml | 40 ++++--- 9 files changed, 221 insertions(+), 150 deletions(-) (limited to 'src/import') diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_mss_eff_config_thermal.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_mss_eff_config_thermal.C index 1891eb75e..82771e69f 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_mss_eff_config_thermal.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_mss_eff_config_thermal.C @@ -62,8 +62,14 @@ extern "C" fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; FAPI_INF("Start exp_mss_eff_config_thermal"); + // For regulaor power/current throttling or thermal throtling + // Do thermal throttling last so the attributes end up representing a total power value for later usage + // Need to have ATTR_EXP_TOTAL_PWR_SLOPE and ATTR_EXP_TOTAL_PWR_INTERCEPT with total DIMM power + // (not regulator current values) after exp_mss_eff_config_thermal is run, so when OCC calls + // exp_bulk_pwr_throttles at runtime the total DIMM power will be used for any memory bulk supply throttling + const std::vector throttle_types{ mss::throttle_type::POWER, mss::throttle_type::THERMAL}; + // Return error if safemode throttle utilization is less than MIN_UTIL - // This section needs to be in braces otherwise the compile will fail const uint64_t l_min_util = TT::MIN_UTIL; uint32_t l_safemode_util = 0; FAPI_TRY( mss::attr::get_mrw_safemode_dram_databus_util(l_safemode_util), "Error in exp_mss_eff_config_thermal" ); @@ -76,49 +82,53 @@ extern "C" for ( const auto& l_ocmb : i_targets) { - //Restore runtime_throttles from safemode setting + //Restore runtime_throttles //Sets throttles to max_databus_util value FAPI_INF("Restoring throttles for %s", mss::c_str(l_ocmb)); FAPI_TRY( mss::power_thermal::restore_runtime_throttles<>(l_ocmb), "Error in exp_mss_eff_config_thermal"); + } - //Not doing any work if there are no dimms installed - if (mss::count_dimm(l_ocmb) == 0) + for (const auto& l_throttle_type : throttle_types ) + { + for ( const auto& l_ocmb : i_targets) { - FAPI_INF("Skipping eff_config thermal because no dimms for %s", mss::c_str(l_ocmb)); - continue; - } - - // Thermal power (OCMB+DRAM) - uint64_t l_thermal_power_limit[TT::SIZE_OF_THERMAL_LIMIT_ATTR] = {0}; - uint64_t l_thermal_power_slope[TT::SIZE_OF_THERMAL_SLOPE_ATTR] = {0}; - uint64_t l_thermal_power_intecept[TT::SIZE_OF_THERMAL_INTERCEPT_ATTR] = {0}; - // Power (PMIC) - uint64_t l_current_curve_with_limit[TT::SIZE_OF_CURRENT_CURVE_WITH_LIMIT_ATTR] = {0}; - - // Get the data from MRW - FAPI_TRY( mss::attr::get_mrw_ocmb_thermal_memory_power_limit (l_thermal_power_limit), - "Error in exp_mss_eff_config_thermal"); - FAPI_TRY( mss::attr::get_mrw_ocmb_pwr_slope (l_thermal_power_slope), "Error in exp_mss_eff_config_thermal"); - FAPI_TRY( mss::attr::get_mrw_ocmb_pwr_intercept (l_thermal_power_intecept), "Error in exp_mss_eff_config_thermal"); - FAPI_TRY( mss::attr::get_mrw_ocmb_current_curve_with_limit (l_current_curve_with_limit), - "Error in exp_mss_eff_config_thermal"); - - // Convert array to vector - using namespace std; - vector l_thermal_power_limit_v ( begin(l_thermal_power_limit), end(l_thermal_power_limit) ); - vector l_thermal_power_slope_v ( begin(l_thermal_power_slope), end(l_thermal_power_slope) ); - vector l_thermal_power_intecept_v ( begin(l_thermal_power_intecept), end(l_thermal_power_intecept) ); - vector l_current_curve_with_limit_v( begin(l_current_curve_with_limit), end(l_current_curve_with_limit) ); - - - uint16_t l_slope [TT::DIMMS_PER_PORT] = {0}; - uint16_t l_intercept[TT::DIMMS_PER_PORT] = {0}; - uint32_t l_limit [TT::DIMMS_PER_PORT] = {0}; + //Not doing any work if there are no dimms installed + if (mss::count_dimm(l_ocmb) == 0) + { + FAPI_INF("Skipping eff_config thermal because no dimms for %s", mss::c_str(l_ocmb)); + continue; + } - const std::vector throttle_types{ mss::throttle_type::POWER, mss::throttle_type::THERMAL}; + // Thermal power (OCMB+DRAM) + uint64_t l_thermal_power_limit[TT::SIZE_OF_THERMAL_LIMIT_ATTR] = {0}; + uint64_t l_thermal_power_slope[TT::SIZE_OF_THERMAL_SLOPE_ATTR] = {0}; + uint64_t l_thermal_power_intecept[TT::SIZE_OF_THERMAL_INTERCEPT_ATTR] = {0}; + // Power (PMIC) + uint64_t l_current_curve_with_limit[TT::SIZE_OF_CURRENT_CURVE_WITH_LIMIT_ATTR] = {0}; + + // Get the data from MRW + FAPI_TRY( mss::attr::get_mrw_ocmb_thermal_memory_power_limit (l_thermal_power_limit), + "Error in exp_mss_eff_config_thermal"); + FAPI_TRY( mss::attr::get_mrw_ocmb_pwr_slope (l_thermal_power_slope), "Error in exp_mss_eff_config_thermal"); + FAPI_TRY( mss::attr::get_mrw_ocmb_pwr_intercept (l_thermal_power_intecept), "Error in exp_mss_eff_config_thermal"); + FAPI_TRY( mss::attr::get_mrw_ocmb_current_curve_with_limit (l_current_curve_with_limit), + "Error in exp_mss_eff_config_thermal"); + + // Convert array to vector + std::vector l_thermal_power_limit_v ( std::begin(l_thermal_power_limit), + std::end(l_thermal_power_limit) ); + std::vector l_thermal_power_slope_v ( std::begin(l_thermal_power_slope), + std::end(l_thermal_power_slope) ); + std::vector l_thermal_power_intecept_v ( std::begin(l_thermal_power_intecept), + std::end(l_thermal_power_intecept) ); + std::vector l_current_curve_with_limit_v( std::begin(l_current_curve_with_limit), + std::end(l_current_curve_with_limit) ); + + + uint16_t l_slope [TT::DIMMS_PER_PORT] = {0}; + uint16_t l_intercept[TT::DIMMS_PER_PORT] = {0}; + uint32_t l_limit [TT::DIMMS_PER_PORT] = {0}; - for (const auto& l_throttle_type : throttle_types ) - { for (const auto& l_port : mss::find_targets(l_ocmb)) { //Don't run if there are no dimms on the port @@ -144,28 +154,33 @@ extern "C" FAPI_TRY(mss::attr::set_dimm_thermal_limit(l_port, l_limit)); FAPI_TRY(mss::attr::set_mem_watt_target(l_port, l_limit)); - FAPI_INF( "PMIC current curve slope is %d, intercept is %d, limit is %d for %s", l_slope[0], l_intercept[0], - l_limit[0], mss::c_str(l_port)); - - FAPI_INF("Starting pwr_throttles(%s)", mss::throttle_type::POWER == l_throttle_type ? "POWER" : "THERMAL"); - //get the power limits, done per dimm and set to worst case for the slot and port throttles - FAPI_TRY(mss::power_thermal::pwr_throttles(l_ocmb, mss::throttle_type::POWER)); - FAPI_TRY(l_rc, "Failed running exp_mss_eff_config_thermal with %s throttling", - mss::throttle_type::POWER == l_throttle_type ? "POWER" : "THERMAL"); - - //Set runtime throttles to worst case between ATTR_EXP_MEM_THROTTLED_N_COMMANDS_PER_SLOT - //and ATTR_EXP_MEM_RUNTIME_THROTTLED_N_COMMANDS_PER_SLOT and the _PORT equivalents also - FAPI_INF("Starting update"); - FAPI_TRY( mss::power_thermal::update_runtime_throttle(l_ocmb), "Error in exp_mss_eff_config_thermal for %d", - mss::c_str(l_port)); - FAPI_INF("finished update"); + for ( const auto& l_dimm : mss::find_targets(l_port) ) + { + const uint8_t l_dimm_pos = mss::index(l_dimm); + FAPI_INF( "DIMM (%d) slope is %d, intercept is %d, limit is %d for %s", + l_dimm_pos, l_slope[l_dimm_pos], l_intercept[l_dimm_pos], + l_limit[l_dimm_pos], mss::c_str(l_port)); + } } + + FAPI_INF("Starting pwr_throttles(%s)", mss::throttle_type::POWER == l_throttle_type ? "POWER" : "THERMAL"); + //get the power limits, done per dimm and set to worst case for the slot and port throttles + FAPI_TRY(mss::power_thermal::pwr_throttles(l_ocmb, l_throttle_type)); } - } - // Equalizes the throttles to the lowest of runtime and the lowest slot-throttle value - FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, mss::throttle_type::POWER)); - FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, mss::throttle_type::THERMAL)); + // Equalizes the throttles to the lowest of runtime and the lowest slot-throttle value + FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, l_throttle_type)); + + for ( const auto& l_ocmb : i_targets) + { + //Set runtime throttles to worst case between ATTR_EXP_MEM_THROTTLED_N_COMMANDS_PER_SLOT + //and ATTR_EXP_MEM_RUNTIME_THROTTLED_N_COMMANDS_PER_SLOT and the _PORT equivalents also + FAPI_INF("Starting update"); + FAPI_TRY( mss::power_thermal::update_runtime_throttle(l_ocmb), "Error in exp_mss_eff_config_thermal for %d", + mss::c_str(l_ocmb)); + FAPI_INF("finished update"); + } + } //Done FAPI_INF( "End exp_mss_eff_config_thermal"); diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.C index 3411bc1d3..ea703b9e7 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.C @@ -25,7 +25,7 @@ /// /// @file exp_decoder.C -/// @brief Decode MSS_MRW_PWR_CURVE_SLOPE, PWR_CURVE_INTERCEPT, and THERMAL_POWER_LIMIT +/// @brief Decode MRW attributes for DIMM power curves and power limits /// // *HWP HWP Owner: Louis Stermole // *HWP HWP Backup: Andre Marin @@ -63,9 +63,9 @@ const std::vector< std::pair > throttle_traits fapi2::ReturnCode decoder::find_slope ( @@ -74,7 +74,7 @@ fapi2::ReturnCode decoder::find_slope ( using TT = throttle_traits; // For explorer, two attribute are used to get slope (i_slope[0], i_slope[1]) - // ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_PWR_SLOPE is for thermal power slope + // ATTR_MSS_MRW_OCMB_PWR_SLOPE is for thermal power slope // ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT is for power slope FAPI_ASSERT(i_slope.size() == 2, fapi2::MSS_POWER_THERMAL_ATTR_VECTORS_INCORRECT() @@ -88,7 +88,7 @@ fapi2::ReturnCode decoder::find_slope ( // To get thermal power slope FAPI_TRY( (get_power_thermal_value( *i_slope[0], - "ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_PWR_SLOPE", + "ATTR_MSS_MRW_OCMB_PWR_SLOPE", iv_total_slope)) ); // To get power slope @@ -103,7 +103,7 @@ fapi_try_exit: /// /// @brief Finds a value for power curve intercept attributes by matching the generated hashes -/// @param[in] i_intercept vector of generated key-values for ATTR_MSS_MRW_POWER_CURVE_INTERCEPT +/// @param[in] i_intercept vector of generated key-values from MRW power curve attributes /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful /// @note populates iv_vddr_intercept, iv_total_intercept /// @@ -114,7 +114,7 @@ fapi2::ReturnCode decoder::find_intercept ( using TT = throttle_traits; // For explorer, two attribute are used to get slope (i_slope[0], i_slope[1]) - // ATTR_MSS_MRW_OCMB_POWER_INTERCEPT is for thermal power intercept + // ATTR_MSS_MRW_OCMB_PWR_INTERCEPT is for thermal power intercept // ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT is for power intercept FAPI_ASSERT(i_intercept.size() == 2, fapi2::MSS_POWER_THERMAL_ATTR_VECTORS_INCORRECT() @@ -128,7 +128,7 @@ fapi2::ReturnCode decoder::find_intercept ( // To get thermal power intercept FAPI_TRY( (get_power_thermal_value( *i_intercept[0], - "ATTR_MSS_MRW_OCMB_POWER_INTERCEPT", + "ATTR_MSS_MRW_OCMB_PWR_INTERCEPT", iv_total_intercept)) ); // To get power intercept @@ -143,10 +143,10 @@ fapi_try_exit: /// -/// @brief Finds a value from ATTR_MSS_MRW_THERMAL_MEMORY_POWER_LIMIT and stores in iv variable -/// @param[in] i_thermal_limits is a vector of the generated values from ATTR_MSS_MRW_THERMAL_POWER_LIMIT +/// @brief Finds a value for the power limit attributes by matching the generated hashes +/// @param[in] i_thermal_limits is a vector of the generated values from MRW power limit attributes /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful -/// @note populates thermal_power_limit. +/// @note populates iv_thermal_power_limit, iv_power_limit /// template<> fapi2::ReturnCode decoder::find_thermal_power_limit ( @@ -172,7 +172,7 @@ fapi2::ReturnCode decoder::find_thermal_power_limit ( "ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_POWER_LIMIT", iv_thermal_power_limit)) ); - // To get power intercept + // To get regulator power or current limit FAPI_TRY( (get_power_thermal_value( *i_thermal_limits[1], "ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT", @@ -184,19 +184,19 @@ fapi_try_exit: /// -/// @brief find the power curve attributes for each dimm on an MCS target -/// @param[in] i_targets vector of MCS targets on which dimm attrs will be set -/// @param[in] i_slope vector of generated hashes for encoding and values for MSS_MRW_POWER_SLOPE -/// @param[in] i_intercept vector of generated hashes for encoding and values for MSS_MRW_POWER_INTERCEPT -/// @param[in] i_thermal_power_limit vector of generated hashes for encoding and values for MSS_MRW_THERMAL_MEMORY_POWER_LIMIT -/// @param[out] o_vddr_slope the VDDR power curve slope for each dimm -/// @param[out] o_vddr_int the VDDR power curve intercept for each dimm -/// @param[out] o_total_slope the VDDR+VPP power curve slope for each dimm -/// @param[out] o_total_int the VDDR+VPP power curve intercept for each dimm -/// @param[out] o_thermal_power the thermal power limit for the dimm +/// @brief find the power curve attributes for each dimm on an MEM_PORT target +/// @param[in] i_throttle_type specifies whether this is for power or thermal throttling +/// @param[in] i_port vector of MEM_PORT targets on which dimm attrs will be set +/// @param[in] i_slope vector of generated hashes for encoding the values for memory power curve slopes +/// @param[in] i_intercept vector of generated hashes for encoding the values for memory power curve intercepts +/// @param[in] i_thermal_power_limit vector of generated hashes for encoding the values for memory power limits +/// @param[in] i_current_curve_with_limit vector of generated hashes for encoding the values for regulator power curves and limits +/// @param[out] o_slope the power curve slope for each dimm +/// @param[out] o_intercept the power curve intercept for each dimm +/// @param[out] o_limit the power limit for the dimm /// @return FAPI2_RC_SUCCESS iff ok /// @note used to set power curve attributes in calling function -/// @note decodes the attribute "encoding" to get the vddr and vddr/vpp power curves for a dimm +/// @note decodes the attribute "encoding" to get the power curves and power limits for a dimm /// fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type, const fapi2::Target& i_port, @@ -217,6 +217,13 @@ fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type, mss::power_thermal::decoder<> l_decoder(l_kind); fapi2::buffer l_attr_value; + // DDIMMs mrw slope/intercept/limit attribute values are for whole DDIMM, so divide these by total number of virtual DIMMs + // to get it to a DIMM level. This will get the DIMM count to use in later calculations. + // ISDIMMs use a value of 1 since mrw attribute values are at the DIMM level + uint8_t l_number_dimm_for_attr_value = (l_kind.iv_dimm_type == fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_DDIMM) ? + mss::count_dimm(mss::find_target(l_dimm)) : + 1; + FAPI_TRY( l_decoder.generate_encoding(), "%s Error in get_power_attrs", mss::c_str(l_dimm) ); // The first entry into these arrays must be valid @@ -228,7 +235,8 @@ fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type, FAPI_INF("%s ATTR_MSS_MRW_OCMB_PWR_SLOPE not found or has zero values", mss::c_str(l_dimm)); o_slope[l_dimm_pos] = - (i_throttle_type == mss::throttle_type::POWER) ? TT::POWER_SLOPE : TT::TOTAL_SLOPE; + ((i_throttle_type == mss::throttle_type::POWER) ? TT::POWER_SLOPE : TT::TOTAL_SLOPE) / + l_number_dimm_for_attr_value; } else { @@ -237,7 +245,8 @@ fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type, FAPI_TRY( l_decoder.find_slope(l_slope), "%s Error in get_power_attrs", mss::c_str(l_dimm) ); o_slope[l_dimm_pos] = - (i_throttle_type == mss::throttle_type::POWER) ? l_decoder.iv_vddr_slope : l_decoder.iv_total_slope; + ((i_throttle_type == mss::throttle_type::POWER) ? l_decoder.iv_vddr_slope : l_decoder.iv_total_slope) / + l_number_dimm_for_attr_value; } l_attr_value = i_intercept[0]; @@ -247,7 +256,8 @@ fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type, FAPI_INF("%s ATTR_MSS_MRW_OCMB_PWR_INTERCEPT not found or has zero values", mss::c_str(l_dimm)); o_intercept[l_dimm_pos] = - (i_throttle_type == mss::throttle_type::POWER) ? TT::POWER_INT : TT::TOTAL_INT; + ((i_throttle_type == mss::throttle_type::POWER) ? TT::POWER_INT : TT::TOTAL_INT) / + l_number_dimm_for_attr_value; } else { @@ -256,7 +266,8 @@ fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type, FAPI_TRY( l_decoder.find_intercept(l_intercept), "%s Error in get_power_attrs", mss::c_str(l_dimm) ); o_intercept[l_dimm_pos] = - (i_throttle_type == mss::throttle_type::POWER) ? l_decoder.iv_vddr_intercept : l_decoder.iv_total_intercept; + ((i_throttle_type == mss::throttle_type::POWER) ? l_decoder.iv_vddr_intercept : l_decoder.iv_total_intercept) / + l_number_dimm_for_attr_value; } l_attr_value = i_thermal_power_limit[0]; @@ -268,7 +279,8 @@ fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type, // The unit of limit and intercept is cA but limit is dA in mss::throttle_type::POWER // So we need to transfer them to the same unit o_limit[l_dimm_pos] = - (i_throttle_type == mss::throttle_type::POWER) ? TT::POWER_LIMIT * DECI_TO_CENTI : TT::THERMAL_LIMIT; + ((i_throttle_type == mss::throttle_type::POWER) ? TT::POWER_LIMIT* DECI_TO_CENTI : TT::THERMAL_LIMIT) / + l_number_dimm_for_attr_value; } else { @@ -279,8 +291,10 @@ fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type, // The unit of limit and intercept is cA but limit is dA in mss::throttle_type::POWER // So we need to transfer them to the same unit o_limit[l_dimm_pos] = - (i_throttle_type == mss::throttle_type::POWER) ? l_decoder.iv_power_limit * DECI_TO_CENTI : - l_decoder.iv_thermal_power_limit; + ((i_throttle_type == mss::throttle_type::POWER) ? + l_decoder.iv_power_limit* DECI_TO_CENTI : l_decoder.iv_thermal_power_limit + ) / + l_number_dimm_for_attr_value; } } diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.C index 0e95aebb7..dbed7a8c0 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.C @@ -61,7 +61,7 @@ namespace power_thermal fapi2::ReturnCode pwr_throttles( const fapi2::Target& i_target, const mss::throttle_type i_throttle_type) { - FAPI_INF("Start exp_bulk_pwr_throttle for %s type throttling for %s", + FAPI_INF("Start pwr_throttles for %s type throttling for %s", (( i_throttle_type == mss::throttle_type::THERMAL) ? "THERMAL" : "POWER"), mss::c_str(i_target)); if (mss::count_dimm (i_target) == 0) @@ -109,11 +109,11 @@ fapi2::ReturnCode pwr_throttles( const fapi2::Target #include #include +#include #include namespace mss diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle_traits.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle_traits.H index 21e003434..0b0d06572 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle_traits.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle_traits.H @@ -85,17 +85,16 @@ class throttle_traits //They are the default/ catch-all values from the power curve attributes //Shouldn't be used if system is set up correctly and attributes are available //This will throttle the DIMMs to ~76% dram data bus utilization - //(using the mrw regulator power limit of 1700 cW and thermal power limit here of 1940 cW). - // TODO: Need to fill the right value. The current value is from Nimbus + //(using the mrw regulator current limit of 100 dA cW and thermal power limit here of 2175 cW). // Thermal power (OCMB+DRAM) - TOTAL_SLOPE = 0x44C, - TOTAL_INT = 0x44C, - THERMAL_LIMIT = 0x794, + TOTAL_SLOPE = 0x462, + TOTAL_INT = 0x526, + THERMAL_LIMIT = 0x87F, // Power (PMIC) - POWER_SLOPE = 0x41A, - POWER_INT = 0x384, - POWER_LIMIT = 0x794, + POWER_SLOPE = 0x152, + POWER_INT = 0x94, + POWER_LIMIT = 0x64, }; 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 8b94c3460..709d3af1b 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 @@ -21532,12 +21532,13 @@ fapi_try_exit: /// @note Generated by gen_accessors.pl generateParameters (SYSTEM A) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Machine Readable Workbook Thermal Memory Power Limit Used to calculate throttles -/// to be at or under the power limit Per DIMM basis KEY (0-21): In order DIMM_SIZE -/// = bits 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, DIMM_WIDTH = 9-11, DIMM_DENSITY = -/// 12-14, DIMM_STACK_TYPE = 15-16, DRAM_MFGID = 17-19, DIMM_HEIGHT = 20-21, Bits -/// 22-32: Not used VALUE (bits 32-47) in cW: OCMB+DRAM thermal power limit per DIMM -/// = -/// 32-47 +/// to meet the thermal power per DIMM limit Per DIMM basis, uses first matching KEY +/// entry KEY (0-21): In order DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, DIMM_TYPE = +/// 6-8, DIMM_WIDTH = 9-11, DIMM_DENSITY = 12-14, DIMM_STACK_TYPE = 15-16, +/// DRAM_MFGID = 17-19, DIMM_HEIGHT = 20-21, Bits 22-32: Not used VALUE (bits 32-47) +/// in cW: thermal power limit DDIMM: Total OCMB+DRAM power limit per DDIMM +/// non-DDIMM: VMEM+VPP power limit per +/// DIMM /// inline fapi2::ReturnCode mrw_ocmb_thermal_memory_power_limit(uint64_t* o_array) { @@ -21559,13 +21560,14 @@ fapi_try_exit: /// @param[out] uint64_t* memory to store the value /// @note Generated by gen_accessors.pl generateParameters (SYSTEM A) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK -/// @note Machine Readable Workbook Power Curve Slope for DIMM Used to get the OCMB+DRAM -/// power curve for each DIMM Per DIMM basis KEY (0-21): In order DIMM_SIZE = bits -/// 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, DIMM_WIDTH = 9-11, DIMM_DENSITY = 12-14, -/// DIMM_STACK_TYPE = 15-16, DRAM_MFGID = 17-19, DIMM_HEIGHT = 20-21, Bits 22-32: -/// Not used VALUE (bits 32-47) in cW/utilization: OCMB+DRAM thermal power limit per -/// DIMM = -/// 32-47 +/// @note Machine Readable Workbook Power Curve Slope for DIMM Used to calculate thermal +/// throttles and port power Per DIMM basis, uses first matching KEY entry KEY +/// (0-21): In order DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, +/// DIMM_WIDTH = 9-11, DIMM_DENSITY = 12-14, DIMM_STACK_TYPE = 15-16, DRAM_MFGID = +/// 17-19, DIMM_HEIGHT = 20-21, Bits 22-32: Not used VALUE (bits 32-47) in +/// cW/utilization: DIMM power slope DDIMM: Total OCMB+DRAM power slope per DDIMM +/// non-DDIMM: VMEM+VPP power slope per +/// DIMM /// inline fapi2::ReturnCode mrw_ocmb_pwr_slope(uint64_t* o_array) { @@ -21586,13 +21588,14 @@ fapi_try_exit: /// @param[out] uint64_t* memory to store the value /// @note Generated by gen_accessors.pl generateParameters (SYSTEM A) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK -/// @note Machine Readable Workbook Power Curve Intercept for DIMM Used to get the -/// OCMB+DRAM power curve for each DIMM Per DIMM basis KEY (0-21): In order -/// DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, DIMM_WIDTH = 9-11, -/// DIMM_DENSITY = 12-14, DIMM_STACK_TYPE = 15-16, DRAM_MFGID = 17-19, DIMM_HEIGHT = -/// 20-21, Bits 22-32: Not used VALUE (bits 32-47) in cW/utilization: OCMB+DRAM -/// thermal power limit per DIMM = -/// 32-47 +/// @note Machine Readable Workbook Power Curve Intercept for DIMM Used to calculate +/// thermal throttles and port power Per DIMM basis, uses first matching KEY entry +/// KEY (0-21): In order DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, +/// DIMM_WIDTH = 9-11, DIMM_DENSITY = 12-14, DIMM_STACK_TYPE = 15-16, DRAM_MFGID = +/// 17-19, DIMM_HEIGHT = 20-21, Bits 22-32: Not used VALUE (bits 32-47) in +/// cW/utilization: DIMM power intercept DDIMM: Total OCMB+DRAM power intercept per +/// DDIMM non-DDIMM: VMEM+VPP power intercept per +/// DIMM /// inline fapi2::ReturnCode mrw_ocmb_pwr_intercept(uint64_t* o_array) { @@ -21613,13 +21616,19 @@ fapi_try_exit: /// @param[out] uint64_t* memory to store the value /// @note Generated by gen_accessors.pl generateParameters (SYSTEM A) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK -/// @note Machine Readable Workbook Power Curve Intercept and limit for DIMM Used to get -/// the PMIC power curve and limit for each DIMM Per DIMM basis KEY (0-21): In order -/// DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, DIMM_WIDTH = 9-11, -/// DIMM_DENSITY = 12-14, DIMM_STACK_TYPE = 15-16, DRAM_MFGID = 17-19, DIMM_HEIGHT = -/// 20-21, Bits 22-32: Not used VALUE (bits 32-39): Current limit (dA) VALUE (bits -/// 40-51): Current slope (cA/utilization) VALUE (bits 52-63): Current intercept -/// (cA) +/// @note Machine Readable Workbook Current Curve Intercept and limit for DIMM Used to +/// calculate throttles to meet regulator current per DIMM limit Per DIMM basis, +/// uses first matching KEY entry For DDIMM, use PMIC SW output that provides worst +/// case throttling KEY (0-21): In order DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, +/// DIMM_TYPE = 6-8, DIMM_WIDTH = 9-11, DIMM_DENSITY = 12-14, DIMM_STACK_TYPE = +/// 15-16, DRAM_MFGID = 17-19, DIMM_HEIGHT = 20-21, Bits 22-32: Not used VALUE (bits +/// 32-39): Current limit (dA) DDIMM: PMIC output current limit per DDIMM non-DDIMM: +/// VMEM regulator current limit per DIMM VALUE (bits 40-51): Current slope +/// (cA/utilization) DDIMM: PMIC output current slope per DDIMM non-DDIMM: VMEM +/// regulator current slope per DIMM VALUE (bits 52-63): Current intercept (cA) +/// DDIMM: PMIC output current intercept per DDIMM non-DDIMM: VMEM regulator current +/// intercept per +/// DIMM /// inline fapi2::ReturnCode mrw_ocmb_current_curve_with_limit(uint64_t* o_array) { 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 20152398e..bfc978492 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 @@ -41,6 +41,7 @@ #include #include #include +#include #include namespace mss 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 378643e4e..e8b4f0f61 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 @@ -133,7 +133,7 @@ fapi2::ReturnCode calc_util_from_throttles(const uint16_t i_n_throttles, o_calc_util = TT::MIN_UTIL; } - FAPI_INF("In calc_util_from_throttles, calculated %f for output utilization from throttles:%d, dram_clocks%d", + FAPI_INF("In calc_util_from_throttles, calculated %f for output utilization from throttles:%d, dram_clocks %d", o_calc_util, i_n_throttles, i_num_dram_clocks); fapi_try_exit: @@ -655,6 +655,7 @@ fapi2::ReturnCode throttle::thermal_throttles () uint32_t l_dimm_power_int [TT::DIMMS_PER_PORT] = {}; double l_calc_util [TT::DIMMS_PER_PORT] = {}; const auto l_count = count_dimm (iv_target); + uint8_t l_found_ddimm = 0; //Calculate the dimm power range for each dimm at max utilization for each FAPI_TRY( calc_dimm_power(TT::IDLE_UTIL, @@ -667,6 +668,8 @@ fapi2::ReturnCode throttle::thermal_throttles () { uint16_t l_temp_n_slot = 0; const uint8_t l_pos = mss::index(l_dimm); + mss::dimm::kind l_kind (l_dimm); + l_found_ddimm = (l_kind.iv_dimm_type == fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_DDIMM) ? 1 : l_found_ddimm; //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], @@ -699,9 +702,12 @@ fapi2::ReturnCode throttle::thermal_throttles () //Set to lowest value between calculated and runtime FAPI_INF("THERMAL throttles: runtime slot is %d, calc n slot is %d for %s", iv_runtime_n_slot, iv_n_slot, mss::c_str(iv_target)); - //Taking the min of the SLOT * (# of dimms on the port) and the iv_runtime_port throttle value + //DDDIMMs: Taking the min of the SLOT and the iv_runtime_port throttle value + //ISDIMMs: Taking the min of the SLOT * (# of dimms on the port) and the iv_runtime_port throttle value //Thermal throttling happens after the POWER calculations. the iv_runtime_n_port value shouldn't be set to 0 - iv_n_port = std::min(iv_runtime_n_port, static_cast(iv_n_slot * l_count)); + iv_n_port = (l_found_ddimm) ? + std::min(iv_runtime_n_port, static_cast(iv_n_slot)) : + std::min(iv_runtime_n_port, static_cast(iv_n_slot * l_count)); iv_n_port = (iv_n_port == 0) ? TT::MIN_THROTTLE : iv_n_port; iv_n_slot = std::min(iv_n_slot, iv_runtime_n_slot); @@ -808,10 +814,9 @@ fapi2::ReturnCode throttle::calc_dimm_power(const double i_databus_idle, 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 for %s", + FAPI_INF("Calc_dimm_power: dimm (%d) power max is %f, dimm slope %d, intercept %d for %s", l_pos, o_dimm_power_max[l_pos], - o_dimm_power_max[l_pos], iv_pwr_slope[l_pos], iv_pwr_int[l_pos], mss::c_str(l_dimm)); @@ -972,7 +977,13 @@ fapi2::ReturnCode throttle::calc_databus (const double i_databus_port_ma for (const auto& l_dimm : mss::find_targets(iv_target)) { //Left early if count_dimms == 0 - o_databus_dimm_max[mss::index(l_dimm)] = i_databus_port_max / l_count_dimms; + // For DDIMM, set each virtual DIMM to the same utilization value since mrw slope/intercept/limit attributes + // are equally divided by number of virtual dimms (ie. mrw values are for whole DDIMM, not individual virtual DIMMs) + // For ISDIMM, divide utilization by number of DIMMs on the port + mss::dimm::kind l_kind (l_dimm); + o_databus_dimm_max[mss::index(l_dimm)] = (l_kind.iv_dimm_type == fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_DDIMM) ? + i_databus_port_max : + i_databus_port_max / l_count_dimms; } //If the power slopes aren't equal, set the dimm with the highest power slope @@ -1012,6 +1023,7 @@ fapi2::ReturnCode throttle::calc_split_util( double o_util_dimm_max [TT::DIMMS_PER_PORT]) const { fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + uint8_t l_found_ddimm = 0; const uint8_t l_count_dimms = count_dimm (iv_target); //The total utilization to be used is limited by either what the port can allow or what the dimms can use FAPI_ASSERT( (i_util_slot <= i_util_port), @@ -1028,6 +1040,12 @@ fapi2::ReturnCode throttle::calc_split_util( return fapi2::FAPI2_RC_SUCCESS; } + for ( const auto& l_dimm : mss::find_targets(iv_target) ) + { + mss::dimm::kind l_kind (l_dimm); + l_found_ddimm = (l_kind.iv_dimm_type == fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_DDIMM) ? 1 : l_found_ddimm; + } + //assumptions slot <= port, l_count_dimms <=2 if (i_util_slot * l_count_dimms > i_util_port) { @@ -1040,9 +1058,13 @@ fapi2::ReturnCode throttle::calc_split_util( //Highest power_slope gets the higher utilization o_util_dimm_max[l_high_pos] = std::min(i_util_slot, i_util_port); - //Set the other dimm to the left over utilization (i_util_port - i_util_slot) - o_util_dimm_max[(!l_high_pos)] = (l_count_dimms == TT::DIMMS_PER_PORT) ? (i_util_port - o_util_dimm_max[l_high_pos]) : - 0; + //Set the other dimm to the left over utilization (i_util_port - i_util_slot) if not a DDIMM, otherwise set to same value as above + o_util_dimm_max[(!l_high_pos)] = (l_found_ddimm) ? + o_util_dimm_max[l_high_pos] : + ((l_count_dimms == TT::DIMMS_PER_PORT) ? + (i_util_port - o_util_dimm_max[l_high_pos]) : + 0 + ); FAPI_INF("Split utilization for target %s, DIMM in %d gets %f, DIMM in %d gets %f", mss::c_str(iv_target), @@ -1184,7 +1206,7 @@ fapi2::ReturnCode equalize_throttles (const std::vector< fapi2::Target >& i_t uint64_t l_fail = mss::fapi_pos(l_port); //Set the failing port. OCC just needs one failing port, doesn't need all of them - FAPI_TRY( attr::set_port_pos_of_fail_throttle(l_fail) ); + FAPI_TRY( mss::attr::set_port_pos_of_fail_throttle(l_fail) ); FAPI_ASSERT_NOEXIT( false, fapi2::MSS_CALC_PORT_POWER_EXCEEDS_MAX() @@ -1202,8 +1224,8 @@ fapi2::ReturnCode equalize_throttles (const std::vector< fapi2::Target >& i_t FAPI_INF("%s Final throttles values for slot %d, for port %d, power value %d", mss::c_str(l_port), - l_fin_port, l_fin_slot, + l_fin_port, l_fin_power); //Even if there's an error, still calculate and set the throttles. diff --git a/src/import/generic/procedures/xml/attribute_info/generic_memory_mrw_attributes.xml b/src/import/generic/procedures/xml/attribute_info/generic_memory_mrw_attributes.xml index e27e60de1..49d4a17ed 100644 --- a/src/import/generic/procedures/xml/attribute_info/generic_memory_mrw_attributes.xml +++ b/src/import/generic/procedures/xml/attribute_info/generic_memory_mrw_attributes.xml @@ -611,8 +611,8 @@ TARGET_TYPE_SYSTEM Machine Readable Workbook Thermal Memory Power Limit - Used to calculate throttles to be at or under the power limit - Per DIMM basis + Used to calculate throttles to meet the thermal power per DIMM limit + Per DIMM basis, uses first matching KEY entry KEY (0-21): In order DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, @@ -623,8 +623,9 @@ DRAM_MFGID = 17-19, DIMM_HEIGHT = 20-21, Bits 22-32: Not used - VALUE (bits 32-47) in cW: - OCMB+DRAM thermal power limit per DIMM = 32-47 + VALUE (bits 32-47) in cW: thermal power limit + DDIMM: Total OCMB+DRAM power limit per DDIMM + non-DDIMM: VMEM+VPP power limit per DIMM uint64 cW @@ -639,8 +640,8 @@ TARGET_TYPE_SYSTEM Machine Readable Workbook Power Curve Slope for DIMM - Used to get the OCMB+DRAM power curve for each DIMM - Per DIMM basis + Used to calculate thermal throttles and port power + Per DIMM basis, uses first matching KEY entry KEY (0-21): In order DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, @@ -651,8 +652,9 @@ DRAM_MFGID = 17-19, DIMM_HEIGHT = 20-21, Bits 22-32: Not used - VALUE (bits 32-47) in cW/utilization: - OCMB+DRAM thermal power limit per DIMM = 32-47 + VALUE (bits 32-47) in cW/utilization: DIMM power slope + DDIMM: Total OCMB+DRAM power slope per DDIMM + non-DDIMM: VMEM+VPP power slope per DIMM uint64 cW @@ -667,8 +669,8 @@ TARGET_TYPE_SYSTEM Machine Readable Workbook Power Curve Intercept for DIMM - Used to get the OCMB+DRAM power curve for each DIMM - Per DIMM basis + Used to calculate thermal throttles and port power + Per DIMM basis, uses first matching KEY entry KEY (0-21): In order DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, @@ -679,8 +681,9 @@ DRAM_MFGID = 17-19, DIMM_HEIGHT = 20-21, Bits 22-32: Not used - VALUE (bits 32-47) in cW/utilization: - OCMB+DRAM thermal power limit per DIMM = 32-47 + VALUE (bits 32-47) in cW/utilization: DIMM power intercept + DDIMM: Total OCMB+DRAM power intercept per DDIMM + non-DDIMM: VMEM+VPP power intercept per DIMM uint64 cW/utilization @@ -694,9 +697,10 @@ ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT TARGET_TYPE_SYSTEM - Machine Readable Workbook Power Curve Intercept and limit for DIMM - Used to get the PMIC power curve and limit for each DIMM - Per DIMM basis + Machine Readable Workbook Current Curve Intercept and limit for DIMM + Used to calculate throttles to meet regulator current per DIMM limit + Per DIMM basis, uses first matching KEY entry + For DDIMM, use PMIC SW output that provides worst case throttling KEY (0-21): In order DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, @@ -708,8 +712,14 @@ DIMM_HEIGHT = 20-21, Bits 22-32: Not used VALUE (bits 32-39): Current limit (dA) + DDIMM: PMIC output current limit per DDIMM + non-DDIMM: VMEM regulator current limit per DIMM VALUE (bits 40-51): Current slope (cA/utilization) + DDIMM: PMIC output current slope per DDIMM + non-DDIMM: VMEM regulator current slope per DIMM VALUE (bits 52-63): Current intercept (cA) + DDIMM: PMIC output current intercept per DDIMM + non-DDIMM: VMEM regulator current intercept per DIMM uint64 dA, cA/utilization, cA -- cgit v1.2.1