Skip to content

Commit

Permalink
Add p9a_mss_utils_to_throttle
Browse files Browse the repository at this point in the history
Also move some shared code into gen_throttle.H

Change-Id: I74ada8a0ee99db511813e04a58f434d779a90930
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/88093
Reviewed-by: Mark Pizzutillo <mark.pizzutillo@ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Michael D Pardeik <pardeik@us.ibm.com>
Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/88121
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com>
  • Loading branch information
stermole authored and dcrowell77 committed Jan 29, 2020
1 parent 5318cf7 commit a69715d
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 62 deletions.
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* Contributors Listed Below - COPYRIGHT 2015,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -72,6 +72,8 @@ extern "C"
///
fapi2::ReturnCode p9_mss_utils_to_throttle( const std::vector< fapi2::Target<TARGET_TYPE_MCS> >& i_targets )
{
constexpr uint64_t l_min_util = mss::power_thermal::throttle_traits<mss::mc_type::NIMBUS>::MIN_UTIL;

FAPI_INF("Entering p9_mss_utils_to_throttle");

std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCA> > l_exceeded_power;
Expand All @@ -88,20 +90,24 @@ extern "C"
uint32_t l_max_databus_util = {};
uint32_t l_dram_clocks = 0;
uint16_t l_safemode_throttle_per_port = 0;
double l_calc_util_safemode = 0;
uint32_t l_calc_util = 0;

uint16_t l_n_port[mss::PORTS_PER_MCS] = {};
uint16_t l_n_slot[mss::PORTS_PER_MCS] = {};
uint32_t l_max_power[mss::PORTS_PER_MCS] = {};

FAPI_TRY( mss::mrw_mem_m_dram_clocks(l_dram_clocks) );
FAPI_TRY(mss::mrw_mem_m_dram_clocks(l_dram_clocks) );

//Util attribute set by OCC
FAPI_TRY( mss::databus_util(l_mcs, l_input_databus_util) );
FAPI_TRY( mss::mrw_max_dram_databus_util(l_max_databus_util));
FAPI_TRY(mss::databus_util(l_mcs, l_input_databus_util) );
FAPI_TRY(mss::mrw_max_dram_databus_util(l_max_databus_util));
FAPI_TRY(mss::mrw_safemode_mem_throttled_n_commands_per_port(l_safemode_throttle_per_port));

for( const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs) )
{
fapi2::ReturnCode l_rc;
bool l_safemode = false;

FAPI_INF("Input databus utilization for %s is %d",
mss::c_str(l_mca),
l_input_databus_util[mss::index(l_mca)]);
Expand All @@ -114,58 +120,31 @@ extern "C"
}

// If input utilization is zero, use mrw safemode throttle values for utilization
bool l_safemode = false;

if (l_input_databus_util[l_port_num] == 0)
{
FAPI_TRY(mss::mrw_safemode_mem_throttled_n_commands_per_port(l_safemode_throttle_per_port),
"Error in getting safemode throttles" );
FAPI_TRY( mss::power_thermal::calc_util_from_throttles(l_safemode_throttle_per_port, l_dram_clocks,
l_calc_util_safemode),
"%s Error calculating utilization from safemode throttle %d and mem clocks %d",
mss::c_str(l_mca),
l_safemode_throttle_per_port,
l_dram_clocks);
FAPI_INF( "%s Safemode throttles being used since input util is zero: Using N=%d, Utilization %f",
mss::c_str(l_mca),
l_safemode_throttle_per_port,
l_calc_util_safemode);
l_safemode = true;
l_input_databus_util[l_port_num] = l_calc_util_safemode;
}

using TT = mss::power_thermal::throttle_traits<>;
const uint64_t l_min_util = TT::MIN_UTIL;
//Make sure MIN_UTIL <= input_utilization <= max_utilization
const uint32_t l_databus_util = ( l_input_databus_util[l_port_num] >= l_min_util) ?
std::min(l_input_databus_util[l_port_num], l_max_databus_util)
: l_min_util;
// else make sure we're within our maximum utilization limit
FAPI_TRY(mss::power_thermal::calc_utilization<mss::mc_type::NIMBUS>(l_mca,
l_input_databus_util[l_port_num],
l_dram_clocks,
l_safemode_throttle_per_port,
l_max_databus_util,
l_calc_util,
l_util_error,
l_safemode));

// Error if utilization is less than MIN_UTIL
// Don't exit, let HWP finish and return error at end
if (l_input_databus_util[l_port_num] < l_min_util)
{
FAPI_ASSERT_NOEXIT( false,
fapi2::MSS_MIN_UTILIZATION_ERROR()
.set_INPUT_UTIL_VALUE(l_input_databus_util[l_port_num])
.set_MIN_UTIL_VALUE(l_min_util),
"%s Input utilization (%d) less than minimum utilization allowed (%d)",
mss::c_str(l_mca), l_input_databus_util[l_port_num], l_min_util);
l_util_error = true;
}

//Make a throttle object in order to calculate the port power
fapi2::ReturnCode l_rc;

mss::power_thermal::throttle<> l_throttle (l_mca, l_rc);
FAPI_TRY(l_rc, "Error calculating mss::power_thermal::throttle constructor in p9_mss_utils_to_throttles");
FAPI_ASSERT_NOEXIT(!l_util_error,
fapi2::MSS_MIN_UTILIZATION_ERROR()
.set_INPUT_UTIL_VALUE(l_input_databus_util[l_port_num])
.set_MIN_UTIL_VALUE(l_min_util),
"%s Input utilization (%d) less than minimum utilization allowed (%d)",
mss::c_str(l_mca), l_input_databus_util[l_port_num], l_min_util);

FAPI_INF( "%s MRW dram clock window: %d, databus utilization: %d",
mss::c_str(l_mca),
l_dram_clocks,
l_databus_util);
// Make a throttle object in order to calculate the port power
mss::power_thermal::throttle<mss::mc_type::NIMBUS> l_throttle (l_mca, l_rc);
FAPI_TRY(l_rc, "%s Error calculating mss::power_thermal::throttle constructor in p9_mss_utils_to_throttles",
mss::c_str(l_mca));

FAPI_TRY( l_throttle.calc_slots_and_power(l_databus_util));
FAPI_TRY( l_throttle.calc_slots_and_power(l_calc_util));

FAPI_INF( "%s Calculated N commands per port %d, per slot %d, commands per dram clock window %d, maxpower is %d",
mss::c_str(l_mca),
Expand Down Expand Up @@ -197,7 +176,7 @@ extern "C"
// Return a failing RC code if we had any input utilization values less than MIN_UTIL
if (l_util_error)
{
fapi2::current_err = fapi2::FAPI2_RC_FALSE;
fapi2::current_err = fapi2::RC_MSS_MIN_UTILIZATION_ERROR;
}

fapi_try_exit:
Expand Down
117 changes: 109 additions & 8 deletions src/import/chips/p9a/procedures/hwp/memory/p9a_mss_utils_to_throttle.C
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2019 */
/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -38,22 +38,123 @@
// *HWP Consumed by: FSP:HB

#include <p9a_mss_utils_to_throttle.H>
#include <lib/shared/exp_defaults.H>
#include <lib/shared/exp_consts.H>
#include <mss_explorer_attribute_getters.H>
#include <lib/power_thermal/exp_throttle.H>

// fapi2
#include <fapi2.H>

extern "C"
{
///
/// @brief Determines throttle and power values for a given port databus utilization.
/// @param[in] i_targets vector of OCMB_CHIPs to set throttle and power attributes on
/// @return FAPI2_RC_SUCCESS iff ok
/// @note ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT will be set to worst case of all slots passed in
/// @note input ATTR_MSS_DATABUS_UTIL and ATTR_MSS_MEM_WATT_TARGET
/// @note output ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, and ATTR_MSS_PORT_MAXPOWER
/// @note Does not set runtime throttles or set registers to throttle values`
/// @note Does not set runtime throttles or set registers to throttle values
///
fapi2::ReturnCode p9a_mss_utils_to_throttle( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >&
i_targets )
{
FAPI_INF("Entering p9a_mss_utils_to_throttle");
return fapi2::FAPI2_RC_SUCCESS;
}
fapi2::ReturnCode p9a_mss_utils_to_throttle(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>>& i_targets)
{
constexpr uint64_t l_min_util = mss::power_thermal::throttle_traits<mss::mc_type::EXPLORER>::MIN_UTIL;

FAPI_INF("Entering p9a_mss_utils_to_throttle");

std::vector<fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>> l_exceeded_power;
bool l_util_error = false;

for (const auto& l_ocmb : i_targets)
{
if (mss::count_dimm(l_ocmb) == 0)
{
FAPI_INF("Skipping %s because it has no DIMM targets", mss::c_str(l_ocmb));
continue;
}

uint32_t l_max_databus_util = 0;
uint32_t l_dram_clocks = 0;
uint32_t l_safemode_util = 0;
uint32_t l_safemode_throttle_per_port = 0;
uint32_t l_calc_util = 0;

FAPI_TRY(mss::attr::get_mrw_mem_m_dram_clocks(l_dram_clocks));
FAPI_TRY(mss::attr::get_mrw_max_dram_databus_util(l_max_databus_util));
FAPI_TRY(mss::attr::get_mrw_safemode_dram_databus_util(l_safemode_util));

l_safemode_throttle_per_port = mss::power_thermal::calc_n_from_dram_util(
(l_safemode_util / mss::power_thermal::throttle_const::PERCENT_CONVERSION),
l_dram_clocks);

for(const auto& l_port : mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(l_ocmb))
{
fapi2::ReturnCode l_rc;
uint32_t l_input_databus_util = 0;
bool l_safemode = false;

// Util attribute set by OCC
FAPI_TRY( mss::attr::get_databus_util(l_port, l_input_databus_util) );

FAPI_INF("Input databus utilization for %s is %d",
mss::c_str(l_port),
l_input_databus_util);

// If input utilization is zero, use mrw safemode throttle values for utilization
// else make sure we're within our maximum utilization limit
FAPI_TRY(mss::power_thermal::calc_utilization<mss::mc_type::EXPLORER>(l_port,
l_input_databus_util,
l_dram_clocks,
l_safemode_throttle_per_port,
l_max_databus_util,
l_calc_util,
l_util_error,
l_safemode));

// Error if utilization is less than MIN_UTIL
// Don't exit, let HWP finish and return error at end
FAPI_ASSERT_NOEXIT( !l_util_error,
fapi2::MSS_MIN_UTILIZATION_ERROR()
.set_INPUT_UTIL_VALUE(l_input_databus_util)
.set_MIN_UTIL_VALUE(l_min_util),
"%s Input utilization (%d) less than minimum utilization allowed (%d)",
mss::c_str(l_port), l_input_databus_util, l_min_util);

// Make a throttle object in order to calculate the port power
mss::power_thermal::throttle<mss::mc_type::EXPLORER> l_throttle(l_port, l_rc);
FAPI_TRY(l_rc, "%s Error calculating mss::power_thermal::throttle constructor in p9a_mss_utils_to_throttles",
mss::c_str(l_port));

FAPI_TRY(l_throttle.calc_slots_and_power(l_calc_util));

FAPI_INF( "%s Calculated N commands per port %d, per slot %d, commands per dram clock window %d, maxpower is %d",
mss::c_str(l_port),
l_throttle.iv_n_port,
l_throttle.iv_n_slot,
l_dram_clocks,
l_throttle.iv_calc_port_maxpower);

FAPI_TRY(mss::attr::set_port_maxpower(l_port, l_throttle.iv_calc_port_maxpower));
FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_slot(l_port,
(l_safemode) ? l_safemode_throttle_per_port : l_throttle.iv_n_slot));
FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_port(l_port,
(l_safemode) ? l_safemode_throttle_per_port : l_throttle.iv_n_port));
} // ports
} // ocmbs

// Equalize throttles to prevent variable performance
// Note that we don't do anything with any port that exceed the power limit here, as we don't have an input power limit to go from
FAPI_TRY(mss::power_thermal::equalize_throttles<mss::mc_type::EXPLORER>(i_targets, mss::throttle_type::POWER,
l_exceeded_power));

// Return a failing RC code if we had any input utilization values less than MIN_UTIL
if (l_util_error)
{
fapi2::current_err = fapi2::RC_MSS_MIN_UTILIZATION_ERROR;
}

fapi_try_exit:
return fapi2::current_err;
}
}// extern C
85 changes: 84 additions & 1 deletion src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2019 */
/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -68,6 +68,29 @@ enum throttle_const : size_t

};

///
/// @brief Calculate the N throttle for a given dram data bus utilization value
///
/// @tparam T1 template parameter, type of input to be processed
/// @tparam T2 template parameter, type of input to be processed
/// @param[in] i_dram_util dram data bus utilization value
/// @param[in] i_throttle_m M throttle value in N/M throttling
///
/// @return int32_t calculated N throttle value
///
template<typename T1, typename T2>
inline uint32_t calc_n_from_dram_util(const T1 i_dram_util, const T2 i_throttle_m)
{
constexpr uint64_t CONVERT_ADDR_UTIL_TO_DATA_UTIL = 4;

return (static_cast<int>(static_cast<double>(i_dram_util)
* (i_throttle_m)
/ (CONVERT_ADDR_UTIL_TO_DATA_UTIL)
/ (PERCENT_CONVERSION)
)
);
}

///
/// @brief Calculate N (address operations) allowed within a window of M DRAM clocks
/// @param[in] i_databus_util databus utilization percentage (e.g. 5% = 5)
Expand Down Expand Up @@ -1097,6 +1120,66 @@ fapi_try_exit:
}


///
/// @brief set the safemode throttle register
/// @tparam MC mss::mc_type
/// @tparam T the fapi2 target type of the target
/// @tparam TT portTraits port traits for the given MC target type
/// @param[in] i_target the port target
/// @return fapi2::FAPI2_RC_SUCCESS if ok
/// @note sets FARB4Q
/// @note used to set throttle window (N throttles / M clocks)
///
template<mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = throttle_traits<MC>>
fapi2::ReturnCode calc_utilization(const fapi2::Target<T>& i_target,
const uint32_t i_input_databus_util,
const uint32_t i_dram_clocks,
const uint16_t i_safemode_throttle_per_port,
const uint32_t i_max_databus_util,
uint32_t& o_util,
bool& o_util_error,
bool& o_safemode)
{
constexpr uint64_t l_min_util = TT::MIN_UTIL;

o_util = i_input_databus_util;
o_safemode = false;

// Use MRW safemode throttle values if input utilization is zero
if (i_input_databus_util == 0)
{
FAPI_TRY(calc_util_from_throttles<MC>(i_safemode_throttle_per_port,
i_dram_clocks,
o_util),
"%s Error calculating utilization from safemode throttle %d and mem clocks %d",
mss::c_str(i_target),
i_safemode_throttle_per_port,
i_dram_clocks);
FAPI_INF("%s Safemode throttles being used since input util is zero: Using N=%d, Utilization %f",
mss::c_str(i_target),
i_safemode_throttle_per_port,
o_util);
o_safemode = true;
}
else if (i_input_databus_util < l_min_util)
{
o_util_error = true;
}

// Make sure MIN_UTIL <= input_utilization <= max_utilization
o_util = (o_util >= l_min_util) ? std::min(o_util, i_max_databus_util) : l_min_util;

FAPI_INF("%s MRW dram clock window: %d, databus utilization: %d",
mss::c_str(i_target),
i_dram_clocks,
o_util);

return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Equalize the throttles and estimated power at those throttle levels
/// @tparam MC mss::mc_type
Expand Down

0 comments on commit a69715d

Please sign in to comment.