From ee413cb5a6ae5b743582c61427ab3d9f8ec1afc7 Mon Sep 17 00:00:00 2001 From: Jacob Harvey Date: Thu, 13 Oct 2016 09:29:46 -0500 Subject: Started implementation of bulk_pwr_throttles Added calc_power and calc_databus functions for throttling Added testing for those calc functions Added a set_power_attrs which decodes power curve attributes Change-Id: I2f08f846f6b19b0200b1c1df4a095cabfa9ee840 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31163 Reviewed-by: Brian R. Silver Reviewed-by: Louis Stermole Tested-by: Jenkins Server Tested-by: Hostboot CI Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31259 Reviewed-by: Matt Derksen Tested-by: FSP CI Jenkins Reviewed-by: JACOB L. HARVEY Reviewed-by: Daniel M. Crowell --- .../hwp/memory/lib/mss_attribute_accessors.H | 464 ++------------------- .../hwp/memory/lib/power_thermal/decoder.C | 46 ++ .../hwp/memory/lib/power_thermal/decoder.H | 31 ++ .../hwp/memory/lib/power_thermal/throttle.C | 286 +++++++++++-- .../hwp/memory/lib/power_thermal/throttle.H | 179 ++++++-- .../hwp/memory/p9_mss_bulk_pwr_throttles.C | 30 +- .../hwp/memory/p9_mss_eff_config_thermal.C | 112 ++++- .../hwp/memory/p9_mss_eff_config_thermal.H | 5 +- .../hwp/memory/p9_mss_utils_to_throttle.C | 4 +- .../xml/attribute_info/memory_mcs_attributes.xml | 60 +-- .../xml/attribute_info/memory_mrw_attributes.xml | 6 +- .../xml/error_info/p9_memory_mss_eff_config.xml | 32 ++ 12 files changed, 669 insertions(+), 586 deletions(-) (limited to 'src/import/chips/p9') 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 0fc3992bc..5d99d8caf 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 @@ -5291,83 +5291,6 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief ATTR_EFF_NUM_DROPS_PER_PORT getter -/// @param[in] const ref to the fapi2::Target -/// @param[out] ref to the value uint8_t -/// @note Generated by gen_accessors.pl generateParameters (D) -/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK -/// @note Specifies the number of DIMM dimensions that are valid per -/// port. -/// -inline fapi2::ReturnCode eff_num_drops_per_port(const fapi2::Target& i_target, uint8_t& o_value) -{ - uint8_t l_value[2]; - - FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_NUM_DROPS_PER_PORT, i_target.getParent(), l_value) ); - o_value = l_value[mss::index(i_target)]; - return fapi2::current_err; - -fapi_try_exit: - FAPI_ERR("failed accessing ATTR_EFF_NUM_DROPS_PER_PORT: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_EFF_NUM_DROPS_PER_PORT getter -/// @param[in] const ref to the fapi2::Target -/// @param[out] ref to the value uint8_t -/// @note Generated by gen_accessors.pl generateParameters (D.1) -/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK -/// @note Specifies the number of DIMM dimensions that are valid per -/// port. -/// -inline fapi2::ReturnCode eff_num_drops_per_port(const fapi2::Target& i_target, - uint8_t& o_value) -{ - uint8_t l_value[2]; - auto l_mca = i_target.getParent(); - - FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_NUM_DROPS_PER_PORT, l_mca.getParent(), l_value) ); - o_value = l_value[mss::index(l_mca)]; - return fapi2::current_err; - -fapi_try_exit: - FAPI_ERR("failed accessing ATTR_EFF_NUM_DROPS_PER_PORT: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_EFF_NUM_DROPS_PER_PORT getter -/// @param[in] const ref to the fapi2::Target -/// @param[out] uint8_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 Specifies the number of DIMM dimensions that are valid per -/// port. -/// -inline fapi2::ReturnCode eff_num_drops_per_port(const fapi2::Target& i_target, uint8_t* o_array) -{ - if (o_array == nullptr) - { - FAPI_ERR("nullptr passed to attribute accessor %s", __func__); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - } - - uint8_t l_value[2]; - - FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_NUM_DROPS_PER_PORT, i_target, l_value) ); - memcpy(o_array, &l_value, 2); - return fapi2::current_err; - -fapi_try_exit: - FAPI_ERR("failed accessing ATTR_EFF_NUM_DROPS_PER_PORT: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - /// /// @brief ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM getter /// @param[in] const ref to the fapi2::Target @@ -6050,15 +5973,15 @@ fapi_try_exit: /// /// @brief ATTR_MSS_TOTAL_PWR_SLOPE 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 (F) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note VDDR+VPP Power slope value for dimm creator: mss_eff_config consumer: /// mss_bulk_pwr_throttles /// -inline fapi2::ReturnCode total_pwr_slope(const fapi2::Target& i_target, uint32_t& o_value) +inline fapi2::ReturnCode total_pwr_slope(const fapi2::Target& i_target, uint16_t& o_value) { - uint32_t l_value[2][2]; + uint16_t l_value[2][2]; auto l_mca = i_target.getParent(); auto l_mcs = l_mca.getParent(); @@ -6075,13 +5998,13 @@ fapi_try_exit: /// /// @brief ATTR_MSS_TOTAL_PWR_SLOPE 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 (G) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note VDDR+VPP Power slope value for dimm creator: mss_eff_config consumer: /// mss_bulk_pwr_throttles /// -inline fapi2::ReturnCode total_pwr_slope(const fapi2::Target& i_target, uint32_t* o_array) +inline fapi2::ReturnCode total_pwr_slope(const fapi2::Target& i_target, uint16_t* o_array) { if (o_array == nullptr) { @@ -6089,11 +6012,11 @@ inline fapi2::ReturnCode total_pwr_slope(const fapi2::Target(); FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_TOTAL_PWR_SLOPE, l_mcs, l_value) ); - memcpy(o_array, &(l_value[mss::index(i_target)][0]), 8); + memcpy(o_array, &(l_value[mss::index(i_target)][0]), 4); return fapi2::current_err; fapi_try_exit: @@ -6105,13 +6028,13 @@ fapi_try_exit: /// /// @brief ATTR_MSS_TOTAL_PWR_SLOPE 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 (H) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note VDDR+VPP Power slope value for dimm creator: mss_eff_config consumer: /// mss_bulk_pwr_throttles /// -inline fapi2::ReturnCode total_pwr_slope(const fapi2::Target& i_target, uint32_t* o_array) +inline fapi2::ReturnCode total_pwr_slope(const fapi2::Target& i_target, uint16_t* o_array) { if (o_array == nullptr) { @@ -6119,10 +6042,10 @@ inline fapi2::ReturnCode total_pwr_slope(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 (F) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note VDDR+VPP Power intercept value for dimm creator: mss_eff_config consumer: /// mss_bulk_pwr_throttles /// -inline fapi2::ReturnCode total_pwr_intercept(const fapi2::Target& i_target, uint32_t& o_value) +inline fapi2::ReturnCode total_pwr_intercept(const fapi2::Target& i_target, uint16_t& o_value) { - uint32_t l_value[2][2]; + uint16_t l_value[2][2]; auto l_mca = i_target.getParent(); auto l_mcs = l_mca.getParent(); @@ -6159,13 +6082,13 @@ fapi_try_exit: /// /// @brief ATTR_MSS_TOTAL_PWR_INTERCEPT 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 (G) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note VDDR+VPP Power intercept value for dimm creator: mss_eff_config consumer: /// mss_bulk_pwr_throttles /// -inline fapi2::ReturnCode total_pwr_intercept(const fapi2::Target& i_target, uint32_t* o_array) +inline fapi2::ReturnCode total_pwr_intercept(const fapi2::Target& i_target, uint16_t* o_array) { if (o_array == nullptr) { @@ -6173,11 +6096,11 @@ inline fapi2::ReturnCode total_pwr_intercept(const fapi2::Target(); FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_TOTAL_PWR_INTERCEPT, l_mcs, l_value) ); - memcpy(o_array, &(l_value[mss::index(i_target)][0]), 8); + memcpy(o_array, &(l_value[mss::index(i_target)][0]), 4); return fapi2::current_err; fapi_try_exit: @@ -6189,13 +6112,13 @@ fapi_try_exit: /// /// @brief ATTR_MSS_TOTAL_PWR_INTERCEPT 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 (H) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note VDDR+VPP Power intercept value for dimm creator: mss_eff_config consumer: /// mss_bulk_pwr_throttles /// -inline fapi2::ReturnCode total_pwr_intercept(const fapi2::Target& i_target, uint32_t* o_array) +inline fapi2::ReturnCode total_pwr_intercept(const fapi2::Target& i_target, uint16_t* o_array) { if (o_array == nullptr) { @@ -6203,10 +6126,10 @@ inline fapi2::ReturnCode total_pwr_intercept(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 Master Power slope value for -/// dimm -/// -inline fapi2::ReturnCode master_pwr_slope(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_MASTER_PWR_SLOPE, 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_MASTER_PWR_SLOPE: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_MASTER_PWR_SLOPE 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 Master Power slope value for -/// dimm -/// -inline fapi2::ReturnCode master_pwr_slope(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_MASTER_PWR_SLOPE, 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_MASTER_PWR_SLOPE: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_MASTER_PWR_SLOPE 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 Master Power slope value for -/// dimm -/// -inline fapi2::ReturnCode master_pwr_slope(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_MASTER_PWR_SLOPE, i_target, l_value) ); - memcpy(o_array, &l_value, 16); - return fapi2::current_err; - -fapi_try_exit: - FAPI_ERR("failed accessing ATTR_MSS_MASTER_PWR_SLOPE: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_SUPPLIER_PWR_SLOPE getter -/// @param[in] const ref to the 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 Supplier Power slope value for -/// dimm -/// -inline fapi2::ReturnCode supplier_pwr_slope(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_SUPPLIER_PWR_SLOPE, 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_SUPPLIER_PWR_SLOPE: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_SUPPLIER_PWR_SLOPE 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 Supplier Power slope value for -/// dimm -/// -inline fapi2::ReturnCode supplier_pwr_slope(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_SUPPLIER_PWR_SLOPE, 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_SUPPLIER_PWR_SLOPE: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_SUPPLIER_PWR_SLOPE 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 Supplier Power slope value for -/// dimm -/// -inline fapi2::ReturnCode supplier_pwr_slope(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_SUPPLIER_PWR_SLOPE, i_target, l_value) ); - memcpy(o_array, &l_value, 16); - return fapi2::current_err; - -fapi_try_exit: - FAPI_ERR("failed accessing ATTR_MSS_SUPPLIER_PWR_SLOPE: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_MASTER_PWR_INTERCEPT getter -/// @param[in] const ref to the 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 Master Power intercept value for -/// dimm -/// -inline fapi2::ReturnCode master_pwr_intercept(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_MASTER_PWR_INTERCEPT, 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_MASTER_PWR_INTERCEPT: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_MASTER_PWR_INTERCEPT 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 Master Power intercept value for -/// dimm -/// -inline fapi2::ReturnCode master_pwr_intercept(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_MASTER_PWR_INTERCEPT, 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_MASTER_PWR_INTERCEPT: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_MASTER_PWR_INTERCEPT 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 Master Power intercept value for -/// dimm -/// -inline fapi2::ReturnCode master_pwr_intercept(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_MASTER_PWR_INTERCEPT, i_target, l_value) ); - memcpy(o_array, &l_value, 16); - return fapi2::current_err; - -fapi_try_exit: - FAPI_ERR("failed accessing ATTR_MSS_MASTER_PWR_INTERCEPT: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_SUPPLIER_PWR_INTERCEPT getter -/// @param[in] const ref to the 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 Supplier Power intercept value for -/// dimm -/// -inline fapi2::ReturnCode supplier_pwr_intercept(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_SUPPLIER_PWR_INTERCEPT, 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_SUPPLIER_PWR_INTERCEPT: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_SUPPLIER_PWR_INTERCEPT 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 Supplier Power intercept value for -/// dimm -/// -inline fapi2::ReturnCode supplier_pwr_intercept(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_SUPPLIER_PWR_INTERCEPT, 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_SUPPLIER_PWR_INTERCEPT: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - -/// -/// @brief ATTR_MSS_SUPPLIER_PWR_INTERCEPT 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 Supplier Power intercept value for -/// dimm -/// -inline fapi2::ReturnCode supplier_pwr_intercept(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_SUPPLIER_PWR_INTERCEPT, i_target, l_value) ); - memcpy(o_array, &l_value, 16); - return fapi2::current_err; - -fapi_try_exit: - FAPI_ERR("failed accessing ATTR_MSS_SUPPLIER_PWR_INTERCEPT: 0x%lx (target: %s)", - uint64_t(fapi2::current_err), mss::c_str(i_target)); - return fapi2::current_err; -} - /// /// @brief ATTR_MSS_DIMM_MAXBANDWIDTH_GBS getter /// @param[in] const ref to the fapi2::Target @@ -19490,7 +19074,7 @@ fapi_try_exit: /// @note Generated by gen_accessors.pl generateParameters (SYSTEM) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Memory power control settings programmed during IPL Used by OCC when exiting -/// idle powersave +/// idle power-save /// mode /// inline fapi2::ReturnCode mrw_power_control_requested(uint8_t& o_value) @@ -19512,7 +19096,7 @@ fapi_try_exit: /// @note Generated by gen_accessors.pl generateParameters (SYSTEM) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Memory power control settings for IDLE powersave mode Used by OCC when entering -/// idle powersave +/// idle power-save /// mode /// inline fapi2::ReturnCode mrw_idle_power_control_requested(uint8_t& o_value) 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 1013cbbfe..a6129774a 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 @@ -259,6 +259,52 @@ fapi2::ReturnCode decoder::find_thermal_power_limit (const std::vector( iv_thermal_power_limit); +fapi_try_exit: + return fapi2::current_err; +} +/// +/// @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 +/// @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 +/// +fapi2::ReturnCode get_power_attrs (const fapi2::Target& i_mcs, + const std::vector< fapi2::buffer< uint64_t > >& i_slope, + const std::vector< fapi2::buffer< uint64_t > >& i_intercept, + const std::vector< fapi2::buffer< uint64_t > >& i_thermal_power_limit, + uint16_t o_vddr_slope [PORTS_PER_MCS][MAX_DIMM_PER_PORT], + uint16_t o_vddr_int [PORTS_PER_MCS][MAX_DIMM_PER_PORT], + 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]) +{ + for (const auto& l_dimm : find_targets (i_mcs)) + { + const auto l_mca_pos = mss::index (find_target(l_dimm)); + const auto l_dimm_pos = mss::index (l_dimm); + mss::dimm::kind l_kind (l_dimm); + mss::power_thermal::decoder l_decoder(l_kind); + FAPI_TRY( l_decoder.generate_encoding() ); + FAPI_TRY( l_decoder.find_slope(i_slope) ); + FAPI_TRY( l_decoder.find_intercept(i_intercept) ); + FAPI_TRY( l_decoder.find_thermal_power_limit(i_thermal_power_limit) ); + + o_vddr_slope [l_mca_pos][l_dimm_pos] = l_decoder.iv_vddr_slope; + o_vddr_int [l_mca_pos][l_dimm_pos] = l_decoder.iv_vddr_intercept; + o_total_slope [l_mca_pos][l_dimm_pos] = l_decoder.iv_total_slope; + o_total_int [l_mca_pos][l_dimm_pos] = l_decoder.iv_total_intercept; + o_thermal_power [l_mca_pos][l_dimm_pos] = l_decoder.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 91e24d344..d7ca5bf71 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,6 +41,12 @@ #include namespace mss { +enum size_of_attrs : size_t +{ + SIZE_OF_POWER_CURVES_ATTRS = 100, + SIZE_OF_THERMAL_ATTR = 10, +}; + namespace power_thermal { @@ -222,6 +228,31 @@ class decoder }; +/// +/// @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 +/// @return FAPI2_RC_SUCCESS iff ok +/// @note used to get power curve attributes in calling function +/// @note decodes the attribute "encoding" to get the vddr and vddr/vpp power curves for a dimm +/// +fapi2::ReturnCode get_power_attrs (const fapi2::Target& i_targets, + const std::vector< fapi2::buffer< uint64_t > >& i_slope, + const std::vector< fapi2::buffer< uint64_t > >& i_intercept, + const std::vector< fapi2::buffer< uint64_t > >& i_thermal_power_limit, + uint16_t o_vddr_slope [PORTS_PER_MCS][MAX_DIMM_PER_PORT], + uint16_t o_vddr_int [PORTS_PER_MCS][MAX_DIMM_PER_PORT], + 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 c3f2c7686..f468ec708 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 @@ -37,6 +37,7 @@ // mss lib #include +#include #include using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_MCS; @@ -45,68 +46,273 @@ using fapi2::TARGET_TYPE_MCBIST; namespace mss { +namespace power_thermal +{ + + +/// +/// @brief Constructor +/// @param[in] i_target MCS target to call power thermal stuff on +/// @param[out] o_rc, a return code which determines the success of the constructor +/// +throttle::throttle( const fapi2::Target& i_mca, fapi2::ReturnCode o_rc) : + iv_target(i_mca), + iv_databus_port_max(0), + iv_runtime_n_slot(0), + iv_runtime_n_port(0), + iv_n_slot(0), + iv_n_port(0), + iv_port_power_limit(0), + iv_port_maxpower(0), + iv_calc_port_maxpower(0) +{ + 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( 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( mrw_mem_m_dram_clocks(iv_m_clocks) ); + + //Port power limit = sum of dimm power limits + for ( const auto& l_dimm : mss::find_targets(iv_target) ) + { + iv_port_power_limit += l_dimm_power_limits[mss::index(l_dimm)]; + } + + 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"); + return; +} /// /// @brief Set ATTR_MSS_CHANNEL_PAIR_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT and _PER_PORT -/// @param[in] Vector of MCS's on the same VDDR domain /// @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, /// @note the _per_slot throttles are set to the _per_port values /// @note throttles are all equalized and set to the worst case value /// -fapi2::ReturnCode bulk_power_regulator_throttles (const std::vector>& i_targets) +fapi2::ReturnCode throttle::power_regulator_throttles () { - - for (const auto& l_mcs : i_targets) - { - uint32_t l_databus_util_max = 0; - uint8_t l_power_uplift = 0; - uint8_t l_power_uplift_idle = 0; - uint32_t l_dimm_power_limit [2][2] = {}; - uint32_t l_runtime_n_slot [2] = {}; - uint32_t l_m_clocks = 0; - uint32_t l_final_n_slot_array[2] = {}; - uint32_t l_port_maxpower[2] = {}; - - FAPI_TRY( mem_throttled_n_commands_per_slot( l_mcs, &(l_final_n_slot_array[0])) ); - FAPI_TRY( port_maxpower ( l_mcs, l_port_maxpower) ); - FAPI_TRY( mrw_max_dram_databus_util(l_databus_util_max) ); - FAPI_TRY( mrw_dimm_power_curve_percent_uplift( l_power_uplift) ); - FAPI_TRY( mrw_dimm_power_curve_percent_uplift_idle( l_power_uplift_idle) ); - FAPI_TRY( runtime_mem_throttled_n_commands_per_slot(l_mcs, &(l_runtime_n_slot[0]) ) ); - FAPI_TRY( mem_watt_target( l_mcs, &(l_dimm_power_limit[0][0])) ); - FAPI_TRY( mrw_mem_m_dram_clocks(l_m_clocks) ); - //Temp values until totally implemented - l_port_maxpower[0] = 2088; - l_port_maxpower[1] = 2088; - //same for per port and per slot - //Throttle per slot is set to per port value - l_final_n_slot_array[0] = 115; - l_final_n_slot_array[1] = 115; - FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_PORT_MAXPOWER, l_mcs, l_port_maxpower) ); - //Set the throttle for the MCS target - FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_final_n_slot_array ) ); - FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_final_n_slot_array ) ); - } // MCS - -fapi_try_exit: - FAPI_INF("End power regulator bulk throttles"); return fapi2::current_err; } /// /// @brief Set ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT and PER_PORT -/// @param[in] Vector of MCS's on the same VDDR domain /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Called in p9_mss_bulk_pwr_throttles /// @note Sets the throttle levels based off of the dimm's thermal limits /// @note both DIMM's on a port are set to the same throttle level /// -fapi2::ReturnCode bulk_thermal_throttles (const std::vector>& i_targets) +fapi2::ReturnCode throttle::thermal_throttles () { - FAPI_INF("End thermal bulk throttles"); + return fapi2::FAPI2_RC_SUCCESS; } +/// +/// @brief Calculates the min and max power usage for a port based off of power curves and utilizati +/// @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 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; + + //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]; + } + + //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)); +} + +/// +/// @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 +/// @note Called in p9_mss_bulk_pwr_throttles +/// @note Port power curve needed to calculate the port utilization +/// +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) +{ + double l_denominator = ((double(iv_databus_port_max) / UTIL_CONVERSION) - IDLE_UTIL); + + 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); + + 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); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + 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 +/// @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) +{ + 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; +} + +/// +/// @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 +/// +void throttle::calc_dimm_power( double o_dimm_power_idle [MAX_DIMM_PER_PORT], + double o_dimm_power_max [MAX_DIMM_PER_PORT]) +{ + for ( const auto& l_dimm : mss::find_targets(iv_target) ) + { + const auto l_pos = mss::index(l_dimm); + + 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]; + + + //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)); + } +} + +/// +/// @brief Converts the port maximum databus 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 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); + + //No work for no dimms + if (l_count_dimms == 0) + { + return fapi2::FAPI2_RC_SUCCESS; + } + + 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; + } + + //If not equal power slopes, set the dimm with the highest power slope + //Should be correct even if only one DIMM 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 + 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_MCA_TARGET(iv_target), + "Failed to calculated databus utilization for target %s", + mss::c_str(iv_target)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @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] = {}; + uint32_t l_max_databus = 0; + uint32_t l_throttle_m_clocks [PORTS_PER_MCS] = {}; + + FAPI_TRY( runtime_mem_m_dram_clocks(i_target, l_throttle_m_clocks) ); + FAPI_TRY( mrw_max_dram_databus_util(l_max_databus) ); + + 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]); + } + + FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, i_target, l_run_throttles) ); + +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 e22950a39..3259608ce 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 @@ -27,7 +27,7 @@ /// @brief throttle API /// -// *HWP HWP Owner: Andre Marin +// *HWP HWP Owner: Jacob Harvey // *HWP HWP Backup: Brian Silver // *HWP Team: Memory // *HWP Level: 2 @@ -36,15 +36,141 @@ #ifndef _MSS_POWER_THROTTLE_ #define _MSS_POWER_THROTTLE_ - +#include +#include namespace mss { - +namespace power_thermal +{ enum throttle_const : size_t { - // Dram data bus utilization is 4X the address bus utilization + // Dram data bus utilization is bus utilization / 4 DRAM_BUS_UTILS = 4, + UTIL_CONVERSION = 10000, PERCENT_CONVERSION = 100, + MIN_UTIL = 1, + IDLE_UTIL = 0, +}; +/// +/// @class throttle +/// @brief Determine power_thermal throttles for memory +/// +class throttle +{ + private: + + public: + const fapi2::Target& iv_target; + //dimm level + uint32_t iv_databus_port_max; + + uint8_t iv_power_uplift_idle; + uint8_t iv_power_uplift; + + uint32_t iv_runtime_n_slot; + uint32_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; + uint32_t iv_port_power_limit; + uint32_t iv_port_maxpower; + uint32_t iv_calc_port_maxpower; + + //default ctor deleted + throttle() = delete; + + /// + /// @brief Constructor + /// @param[in] i_target MCA target to call power thermal stuff on + /// @param[out] o_rc fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ctor was successful + /// + throttle( const fapi2::Target& i_mca, fapi2::ReturnCode o_rc); + + // + // @brief Destructor + // + ~throttle() = default; + + /// + /// @brief Calculates the min and max power usage for a port based off of power curves and utilizati + /// @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 + /// @note Called in p9_mss_bulk_pwr_throttles + /// @note Port power curve needed to calculate the port utilization + /// + 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); + /// + /// @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 + /// @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); + + /// + /// @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 + /// + void calc_dimm_power(double o_dimm_power_idle [MAX_DIMM_PER_PORT], + double o_dimm_power_max [MAX_DIMM_PER_PORT]); + /// + /// @brief Converts the port maximum databus 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]); + + /// + /// @brief Set 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 + /// + fapi2::ReturnCode power_regulator_throttles (); + + /// + /// @brief Set 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 Sets the throttle levels based off of the dimm's thermal limits + /// @note both DIMM's on a port are set to the same throttle level + /// + fapi2::ReturnCode thermal_throttles (); }; /// @@ -53,42 +179,41 @@ enum throttle_const : size_t /// @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 / 100 ) = ((N * 4) / M ) -/// Dram data bus utilization is 4X the address bus utilization -/// +/// Equation: (DRAM data bus utilization Percent / 10000 ) = ((N * M) / 4 ) +/// Equation: N = (DRAM data bus utilization Percent * 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 * PERCENT_CONVERSION; + 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_quotient = l_dividend / l_divisor; - const uint64_t l_remainder = l_dividend % l_divisor; + const uint64_t l_result = l_dividend / l_divisor; - return l_quotient + (l_remainder == 0 ? 0 : 1); + return l_result; } /// -/// @brief Set ATTR_MSS_CHANNEL_PAIR_MAXPOWER and ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, -/// @param[in] Vector of MCS 's on the same VDDR domain -/// @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 +/// @brief Calculate the port databus utilization based off of N throttles and M dram clocks +/// @param[in] i_n_throttles N (address operations) allowed within a window of M DRAM clocks +/// @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 /// -fapi2::ReturnCode bulk_power_regulator_throttles (const std::vector>& - i_targets); +inline double calc_util_from_throttles(const uint16_t i_n_throttles, const uint32_t i_num_dram_clocks) +{ + constexpr uint32_t l_multiplier = DRAM_BUS_UTILS * UTIL_CONVERSION; + return ( (double(i_n_throttles) * l_multiplier) / i_num_dram_clocks); + +} /// -/// @brief Set ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, -/// @param[in] Vector of MCS 's on the same VDDR domain -/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK -/// @note Called in p9_mss_bulk_pwr_throttles -/// @note Sets the throttle levels based off of the dimm's thermal limits -/// @note both DIMM's on a port are set to the same throttle level +/// @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 /// -fapi2::ReturnCode bulk_thermal_throttles (const std::vector>& i_targets); - +fapi2::ReturnCode restore_runtime_throttles( const fapi2::Target& i_target ); +}//power_thermal }// mss #endif 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 65d3bd083..77cbacf5d 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 @@ -32,7 +32,7 @@ // *HWP Team: Memory // *HWP Level: 1 // *HWP Consumed by: FSP:HB -#include +#include #include #include @@ -62,22 +62,42 @@ extern "C" throttle_type t) { FAPI_INF("Start bulk_pwr_throttles"); - - FAPI_TRY ( mss::bulk_thermal_throttles (i_targets) ); +//To be implemented in next commit +#if 0 //Check for THERMAL if (t == THERMAL) { - FAPI_TRY ( mss::bulk_thermal_throttles (i_targets) ); + for ( const auto& l_mcs : i_targets) + { + 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() ); + } + } + + //Equalize throttles } //else do POWER else { - FAPI_TRY ( mss::bulk_power_regulator_throttles (i_targets) ); + for ( const auto& l_mcs : i_targets) + { + 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() ); + } + } + + //Equalize throttles } + FAPI_INF("End bulk_pwr_throttles"); fapi_try_exit: +#endif return fapi2::current_err; } } //extern C 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 ec918049c..361c3dbe6 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 @@ -27,23 +27,117 @@ /// @file p9_mss_eff_config_thermal.C /// @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 Consumed by: FSP:HB #include +#include #include - +#include +#include +#include +#include +#include +extern "C" +{ /// /// @brief Perform thermal calculations as part of the effective configuration -/// @param[in] i_target the controller (e.g., MCS) +/// @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 fapi2::Target& i_target ) -{ - FAPI_INF("Start effective config thermal"); - FAPI_INF("End effective config thermal"); - return fapi2::FAPI2_RC_SUCCESS; -} + fapi2::ReturnCode p9_mss_eff_config_thermal( const std::vector< fapi2::Target >& i_targets ) + { + + FAPI_INF("Start effective config thermal"); + + uint16_t l_vddr_slope [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {}; + uint16_t l_vddr_int [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {}; + uint16_t l_total_slope [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {}; + uint16_t l_total_int [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {}; + uint32_t l_thermal_power [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {}; + + //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); + + 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); + + 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) + { + l_slope[i] = fapi2::buffer (l_tslope[i]); + l_intercept[i] = fapi2::buffer(l_tintercept[i]); + } + + for ( const auto& l_mcs : i_targets ) + { + FAPI_TRY (mss::power_thermal::get_power_attrs(l_mcs, + l_slope, + l_intercept, + l_thermal_power_limit, + l_vddr_slope, + l_vddr_int, + l_total_slope, + l_total_int, + l_thermal_power)); + + 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 + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_TOTAL_PWR_SLOPE, + l_mcs, + l_vddr_slope)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_TOTAL_PWR_INTERCEPT, + l_mcs, + l_vddr_int)); + } + + //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)); + + //Set VDDR+VPP + for ( const auto& l_mcs : i_targets ) + { + FAPI_TRY (mss::power_thermal::get_power_attrs(l_mcs, + l_slope, + l_intercept, + l_thermal_power_limit, + l_vddr_slope, + l_vddr_int, + l_total_slope, + l_total_int, + l_thermal_power)); + + 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 + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_TOTAL_PWR_SLOPE, + l_mcs, + l_total_slope)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_TOTAL_PWR_INTERCEPT, + l_mcs, + l_total_int)); + } + + + FAPI_INF("End effective config thermal"); + + fapi_try_exit: + return fapi2::FAPI2_RC_SUCCESS; + } +} //extern C 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 003454acb..9071f5a1c 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 @@ -37,8 +37,9 @@ #define __P9_MSS_EFF_CONFIG_THERMAL__ #include +#include -typedef fapi2::ReturnCode (*p9_mss_eff_config_thermal_FP_t) (const fapi2::Target&); +typedef fapi2::ReturnCode (*p9_mss_eff_config_thermal_FP_t) (const std::vector>&); extern "C" { @@ -48,7 +49,7 @@ extern "C" /// @param[in] i_target the controller (e.g., MCS) /// @return FAPI2_RC_SUCCESS iff ok /// - fapi2::ReturnCode p9_mss_eff_config_thermal( const fapi2::Target& i_target ); + fapi2::ReturnCode p9_mss_eff_config_thermal( const std::vector< fapi2::Target >& i_targets ); } 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 ee980cd92..8809ad0f4 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 @@ -85,8 +85,8 @@ extern "C" l_databus_util ); // Calculate programmable N address operations within M dram clock window - l_throttled_cmds_port[l_port_num] = mss::throttled_cmds( l_databus_util[l_port_num], l_dram_clocks ); - l_throttled_cmds_slot[l_port_num] = mss::throttled_cmds( l_databus_util[l_port_num], l_dram_clocks ); + 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; 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 155a02270..8d5776543 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 @@ -1127,18 +1127,6 @@ eff_ibm_type - - ATTR_EFF_NUM_DROPS_PER_PORT - TARGET_TYPE_MCS - Specifies the number of DIMM dimensions that are valid per port. - - uint8 - EMPTY = 0, SINGLE = 1, DUAL = 2 - - 2 - eff_num_drops_per_port - - ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM TARGET_TYPE_MCS @@ -1255,7 +1243,7 @@ consumer: mss_bulk_pwr_throttles - uint32 + uint16 2 2 total_pwr_slope @@ -1270,56 +1258,12 @@ consumer: mss_bulk_pwr_throttles - uint32 + uint16 2 2 total_pwr_intercept - - ATTR_MSS_MASTER_PWR_SLOPE - TARGET_TYPE_MCS - Master Power slope value for dimm - - uint32 - - 2 2 - master_pwr_slope - - - - ATTR_MSS_SUPPLIER_PWR_SLOPE - TARGET_TYPE_MCS - Supplier Power slope value for dimm - - uint32 - - 2 2 - supplier_pwr_slope - - - - ATTR_MSS_MASTER_PWR_INTERCEPT - TARGET_TYPE_MCS - Master Power intercept value for dimm - - uint32 - - 2 2 - master_pwr_intercept - - - - ATTR_MSS_SUPPLIER_PWR_INTERCEPT - TARGET_TYPE_MCS - Supplier Power intercept value for dimm - - uint32 - - 2 2 - supplier_pwr_intercept - - ATTR_MSS_DIMM_MAXBANDWIDTH_GBS TARGET_TYPE_MCS 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 6c35ef2ac..f4737af85 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 @@ -67,7 +67,7 @@ uint64 cW - ffffe0001700 + ffffe000000006A4 10 @@ -247,7 +247,7 @@ TARGET_TYPE_SYSTEM Memory power control settings programmed during IPL - Used by OCC when exiting idle powersave mode + Used by OCC when exiting idle power-save mode uint8 OFF = 0x00, POWER_DOWN = 0x01, STR = 0x02, PD_AND_STR = 0x03 @@ -263,7 +263,7 @@ TARGET_TYPE_SYSTEM Memory power control settings for IDLE powersave mode - Used by OCC when entering idle powersave mode + Used by OCC when entering idle power-save mode uint8 OFF = 0x00, POWER_DOWN = 0x01, STR = 0x02, PD_AND_STR = 0x03 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 95adb0067..12336a55b 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 @@ -145,4 +145,36 @@ + + RC_MSS_NO_DATABUS_UTILIZATION + + There are 2 DIMMS on the port but both have 0 databus utilization + + PORT_DATABUS_UTIL + + MCA_TARGET + HIGH + + + MCA_TARGET + + + + + RC_MSS_CALC_PORT_POWER_CURVE_DIVIDE_BY_ZERO + + Denominator equals 0 + + PORT_DATABUS_UTIL + UTIL_CONVERSION + IDLE_UTIL + + MCA_TARGET + HIGH + + + MCA_TARGET + + + -- cgit v1.2.1