Skip to content

Commit

Permalink
Cleaning up and implementing L3 eff_config_thermal
Browse files Browse the repository at this point in the history
Change-Id: Id780f75931e4522726e95191a3e56760edcc3af5
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35166
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: Michael D. Pardeik <pardeik@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Reviewed-by: Matt K. Light <mklight@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35173
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
  • Loading branch information
JacobHarvey authored and dcrowell77 committed Feb 27, 2017
1 parent e151de1 commit b3f26ce
Show file tree
Hide file tree
Showing 9 changed files with 508 additions and 287 deletions.
Expand Up @@ -157,8 +157,7 @@ fapi2::ReturnCode decoder::find_slope (const std::vector<fapi2::buffer<uint64_t>
//The last value should always be the default value
FAPI_ASSERT(l_value_iterator != i_slope.end(),
fapi2::MSS_NO_POWER_THERMAL_ATTR_FOUND()
.set_GENERATED_KEY(iv_gen_key)
.set_DIMM_TARGET(iv_kind.iv_target),
.set_GENERATED_KEY(iv_gen_key),
"Couldn't find %s value for generated key:%08lx, for target %s. "
"DIMM values for generated key are "
"size is %d, gen is %d, type is %d, width is %d, density %d, stack %d, mfgid %d, dimms %d",
Expand Down Expand Up @@ -198,8 +197,7 @@ fapi2::ReturnCode decoder::find_intercept (const std::vector<fapi2::buffer<uint6
//The last value should always be the default value
FAPI_ASSERT(l_value_iterator != i_intercept.end(),
fapi2::MSS_NO_POWER_THERMAL_ATTR_FOUND()
.set_GENERATED_KEY(iv_gen_key)
.set_DIMM_TARGET(iv_kind.iv_target),
.set_GENERATED_KEY(iv_gen_key),
"Couldn't find %s value for generated key:%08lx, for target %s. "
"DIMM values for generated key are "
"size is %d, gen is %d, type is %d, width is %d, density %d, stack %d, mfgid %d, dimms %d",
Expand Down Expand Up @@ -239,8 +237,7 @@ fapi2::ReturnCode decoder::find_thermal_power_limit (const std::vector<fapi2::bu
//The last value should always be the default value
FAPI_ASSERT(l_value_iterator != i_thermal_limits.end(),
fapi2::MSS_NO_POWER_THERMAL_ATTR_FOUND()
.set_GENERATED_KEY(iv_gen_key)
.set_DIMM_TARGET(iv_kind.iv_target),
.set_GENERATED_KEY(iv_gen_key),
"Couldn't find %s value for generated key:%8lx, for target %s. "
"DIMM values for generated key are "
"size is %d, gen is %d, type is %d, width is %d, density %d, stack %d, mfgid %d, dimms %d",
Expand Down
321 changes: 229 additions & 92 deletions src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C

Large diffs are not rendered by default.

Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2016 */
/* Contributors Listed Below - COPYRIGHT 2016,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand All @@ -30,7 +30,7 @@
// *HWP HWP Owner: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#ifndef _MSS_POWER_THROTTLE_
Expand Down Expand Up @@ -82,7 +82,7 @@ class throttle
///
inline void calc_power_uplift (const uint8_t i_uplift, double& o_value)
{
o_value *= (1 + (double(i_uplift) / PERCENT_CONVERSION));
o_value *= (1 + (static_cast<double>(i_uplift) / PERCENT_CONVERSION));
}

public:
Expand Down Expand Up @@ -113,7 +113,7 @@ class throttle
/// @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<fapi2::TARGET_TYPE_MCA>& i_mca, fapi2::ReturnCode o_rc);
throttle( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_mca, fapi2::ReturnCode& o_rc);

//
// @brief Destructor
Expand All @@ -126,12 +126,13 @@ class throttle
/// @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
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
/// @note Called twice in p9_mss_bulk_pwr_throttles
///
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);
fapi2::ReturnCode calc_port_power( const double i_idle_util [MAX_DIMM_PER_PORT],
const double i_max_util [MAX_DIMM_PER_PORT],
double& o_port_power_idle,
double& o_port_power_max);
///
/// @brief Calculates max and min power usages based off of DIMM power curves
/// @param[in] i_databus_port_max max databus utilization for the port (either calculated or mrw)
Expand All @@ -152,6 +153,7 @@ class throttle
/// @param[in] i_power_max double of the port's power consumption at max utilization
/// @param[out] o_power_slope
/// @param[out] o_power_int
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
/// @note Called in p9_mss_bulk_pwr_throttles
/// @note Power curve needed to calculate the utilization
///
Expand All @@ -175,16 +177,18 @@ class throttle
///
/// @brief set iv_n_port, iv_n_slot, iv_calc_port_maxpower
/// @param[in] i_util_port pass in the calculated port databus utilization
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
///
void calc_slots_and_power (const double i_util_port);
fapi2::ReturnCode calc_slots_and_power (const double i_util_port);

///
///@brief calculated the output power estimate from the calculated N throttle
///@param[in] i_n_slot the N throttle per slot
///@param[in] i_n_port the N throttle per port
///@return the power calculated from the uint
/// @brief calculated the output power estimate from the calculated N throttle
/// @param[in] i_n_slot the N throttle per slot
/// @param[in] i_n_port the N throttle per port
/// @param[out] o_power the calculated power
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
///
uint32_t calc_power_from_n (const uint16_t i_n_slot, const uint16_t i_n_port);
fapi2::ReturnCode calc_power_from_n (const uint16_t i_n_slot, const uint16_t i_n_port, uint32_t& o_power);

///
/// @brief Converts the port maximum databus util to a dimm level based on powerslopes and dimms installed
Expand Down Expand Up @@ -252,21 +256,47 @@ inline uint32_t throttled_cmds(const uint32_t i_databus_util, const uint32_t i_n
/// @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
/// @param[out] o_calc_util
/// @return FAPI2_RC_SUCCESS iff method was a success
/// @note Uses N/M Throttling.
/// @note DRAM databus utilization = N * 4 * 10000 / M
///
inline double calc_util_from_throttles(const uint16_t i_n_throttles, const uint32_t i_num_dram_clocks)
template<typename T>
fapi2::ReturnCode calc_util_from_throttles(const uint16_t i_n_throttles,
const uint32_t i_num_dram_clocks,
T& o_calc_util)
{
constexpr uint32_t l_multiplier = DRAM_BUS_UTILS * UTIL_CONVERSION;
const auto l_temp = (double(i_n_throttles) * l_multiplier) / i_num_dram_clocks;
return ( (l_temp == 0) ? MIN_THROTTLE : l_temp);
FAPI_ASSERT( (i_num_dram_clocks != 0),
fapi2::MSS_M_DRAM_CLOCKS_EQUALS_ZERO(),
"ATTR_MSS_MRW_MEM_M_DRAM_CLOCKS was not set and equals zero");

o_calc_util = (static_cast<double>(i_n_throttles) * l_multiplier) / i_num_dram_clocks;

// Best way to check for overflow if o_calc_util can be a double?
// If o_calc_util overflows, the value inside will be below the expected outcome
// So compare o_calc_util with the calculated value, but store calculated value in largest storage
// Compare ">=" because o_calc_util can be a double, and so we can't compare just equality due to truncation
FAPI_ASSERT( o_calc_util >= static_cast<uint64_t>((static_cast<double>(i_n_throttles) * l_multiplier) /
i_num_dram_clocks),
fapi2::MSS_OUTPUT_OVERFLOW_CALC_UTIL()
.set_RESULT((static_cast<double>(i_n_throttles) * l_multiplier) / i_num_dram_clocks),
"Overflow of output variable in calc_util_from_throttles throttles: %d, multiplier %d, dram_clocks %d",
i_n_throttles,
l_multiplier,
i_num_dram_clocks);

o_calc_util = ( (o_calc_util == 0) ? MIN_UTIL : o_calc_util);

FAPI_INF("In calc_util_from_throttles, calculated %f for output utilization", o_calc_util);
return fapi2::FAPI2_RC_SUCCESS;
fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Determines if the double has decimal digits and adds 1 and rounds if true
/// @param[in] io_val the double to be rounded up if trialing digits
/// @param[in] i_val the double to be rounded up if trialing digits
/// @return the input value rounded up to the next whole digit
/// @note Called in p9_mss_bulk_pwr_throttles
///
Expand Down
132 changes: 50 additions & 82 deletions src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2015,2016 */
/* Contributors Listed Below - COPYRIGHT 2015,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand All @@ -28,9 +28,9 @@
/// @brief Set the throttle attributes based on a power limit for the dimms on the channel pair
///
// *HWP HWP Owner: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre A. Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Level: 3
// *HWP Consumed by: FSP:HB
#include <vector>

Expand All @@ -46,99 +46,65 @@ using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_DIMM;
extern "C"
{

///
/// @brief Set ATTR_MSS_PORT_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT
/// @param[in] i_targets vector of MCS's on the same VDDR domain
/// @param[in] thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Called in p9_mss_bulk_pwr_throttles
/// @note determines the throttle levels based off of the port's power curve,
/// sets the slot throttles to the same
/// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles
/// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
///

///
/// @brief Set ATTR_MSS_PORT_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT
/// @param[in] i_targets vector of MCS's on the same VDDR domain
/// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Called in p9_mss_bulk_pwr_throttles
/// @note determines the throttle levels based off of the port's power curve,
/// sets the slot throttles to the same
/// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles
/// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
///
fapi2::ReturnCode p9_mss_bulk_pwr_throttles( const std::vector< fapi2::Target<TARGET_TYPE_MCS> >& i_targets,
throttle_type t)
const throttle_type i_throttle_type)
{
FAPI_INF("Start bulk_pwr_throttles");
fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;
FAPI_INF("Start p9_mss_bulk_pwr_throttles for %s type throttling",
(( i_throttle_type == THERMAL) ? "THERMAL" : "POWER"));
fapi2::ReturnCode l_rc;

//Check for THERMAL
if (t == THERMAL)
for ( const auto& l_mcs : i_targets)
{
for ( const auto& l_mcs : i_targets)
{
uint16_t l_slot [mss::PORTS_PER_MCS] = {};
uint16_t l_port [mss::PORTS_PER_MCS] = {};
uint32_t l_power [mss::PORTS_PER_MCS] = {};
uint16_t l_slot [mss::PORTS_PER_MCS] = {};
uint16_t l_port [mss::PORTS_PER_MCS] = {};
uint32_t l_power [mss::PORTS_PER_MCS] = {};

for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs))
for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs))
{
//Don't run if there are no dimms on the port
if (mss::count_dimm(l_mca) == 0)
{
//Don't run if there are no dimms on the port
if (mss::count_dimm(l_mca) == 0)
{
continue;
}

const uint8_t l_pos = mss::index(l_mca);
fapi2::ReturnCode l_rc;
mss::power_thermal::throttle l_pwr_struct(l_mca, l_rc);
FAPI_TRY(l_rc, "Error constructing mss:power_thermal::throttle object for target %s",
mss::c_str(l_mca));
FAPI_TRY (l_pwr_struct.thermal_throttles());

l_slot[l_pos] = l_pwr_struct.iv_n_slot;
l_port[l_pos] = l_pwr_struct.iv_n_port;
l_power[l_pos] = l_pwr_struct.iv_calc_port_maxpower;
continue;
}

FAPI_INF("Port maxpower is %d, %d slot is %d, %d, port is %d %d",
l_power[0], l_power[1], l_slot[0], l_slot[1], l_port[0], l_port[1]);
const uint8_t l_pos = mss::index(l_mca);

FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_PORT_MAXPOWER, l_mcs, l_power));
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_slot));
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_port));
}
}
//else do POWER
else
{
for ( const auto& l_mcs : i_targets)
{
uint16_t l_slot [mss::PORTS_PER_MCS] = {};
uint16_t l_port [mss::PORTS_PER_MCS] = {};
uint32_t l_power [mss::PORTS_PER_MCS] = {};
mss::power_thermal::throttle l_pwr_struct(l_mca, l_rc);
FAPI_TRY(l_rc, "Error constructing mss:power_thermal::throttle object for target %s",
mss::c_str(l_mca));

for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs))
//Let's do the actual work now
if ( i_throttle_type == THERMAL)
{
FAPI_TRY (l_pwr_struct.thermal_throttles());
}
else
{
//Don't run if there are no dimms on the port
if (mss::count_dimm(l_mca) == 0)
{
continue;
}

uint8_t l_pos = mss::index(l_mca);
fapi2::ReturnCode l_rc;
mss::power_thermal::throttle l_pwr_struct(l_mca, l_rc);
FAPI_TRY(l_rc, "Error constructing mss:power_thermal::throttle object for target %s",
mss::c_str(l_mca));

FAPI_TRY (l_pwr_struct.power_regulator_throttles());

l_slot[l_pos] = l_pwr_struct.iv_n_slot;
l_port[l_pos] = l_pwr_struct.iv_n_port;
l_power[l_pos] = l_pwr_struct.iv_calc_port_maxpower;
}

FAPI_INF("Port maxpower is %d, %d slot is %d, %d, port is %d %d",
l_power[0], l_power[1], l_slot[0], l_slot[1], l_port[0], l_port[1]);
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_PORT_MAXPOWER, l_mcs, l_power));
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_slot));
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_port));
l_slot[l_pos] = l_pwr_struct.iv_n_slot;
l_port[l_pos] = l_pwr_struct.iv_n_port;
l_power[l_pos] = l_pwr_struct.iv_calc_port_maxpower;

FAPI_INF("For target %s Calculated power is %d, throttle per slot is %d, throttle per port is %d",
mss::c_str(l_mca), l_power[l_pos], l_slot[l_pos], l_port[l_pos]);
}

FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_PORT_MAXPOWER, l_mcs, l_power));
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_slot));
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_port));
}

//Set all of the throttles to the lowest value per port for performance reasons
Expand All @@ -147,7 +113,9 @@ extern "C"
return l_rc;

fapi_try_exit:
FAPI_ERR("Error calculating bulk_pwr_throttles");
return fapi2::current_err;
FAPI_ERR("Error calculating bulk_pwr_throttles using %s throttling",
((i_throttle_type == POWER) ? "power" : "thermal"));
return l_rc;
}
} //extern C

0 comments on commit b3f26ce

Please sign in to comment.