<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file throttle.C
/// @brief Determine throttle settings for memory
///
// *HWP HWP Owner: <NAME> <<EMAIL>>
// *HWP HWP Backup: <NAME> <<EMAIL>>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB
//std lib
#include<algorithm>
// fapi2
#include <fapi2.H>

// mss lib
#include <lib/power_thermal/throttle.H>
#include <lib/utils/count_dimm.H>
#include <mss.H>
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_DIMM;
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<fapi2::TARGET_TYPE_MCA>& 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_calc_port_maxpower(0)
{
    //holder for watt_target to add up for port
    uint32_t l_dimm_power_limits [MAX_DIMM_PER_PORT] = {};

    FAPI_TRY( 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( dimm_thermal_limit( iv_target, iv_dimm_thermal_limit) );
    FAPI_TRY( total_pwr_intercept( iv_target, iv_pwr_int));
    FAPI_TRY( total_pwr_slope( iv_target, iv_pwr_slope));
    FAPI_TRY( runtime_mem_throttled_n_commands_per_slot(iv_target, iv_runtime_n_slot ) );
    FAPI_TRY( runtime_mem_throttled_n_commands_per_port(iv_target, iv_runtime_n_port ) );
    FAPI_TRY( mem_watt_target( iv_target, l_dimm_power_limits) );
    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<TARGET_TYPE_DIMM>(iv_target) )
    {
        iv_port_power_limit += l_dimm_power_limits[mss::index(l_dimm)];
    }

    FAPI_INF("Setting up throttle for target %s, Values are: max databus is %d, uplifts are %d %d, runtime throttles are %d %d",
             mss::c_str(iv_target),
             iv_databus_port_max,
             iv_power_uplift,
             iv_power_uplift_idle,
             iv_runtime_n_slot,
             iv_runtime_n_port);

    FAPI_INF("The dimm power limit for dimm0 is %d, dimm1 is %d,  port power limit is %d, dram clocks are %d, dimm power curve slopes are %d %d,",
             l_dimm_power_limits[0],
             l_dimm_power_limits[1],
             iv_port_power_limit,
             iv_m_clocks,
             iv_pwr_slope[0],
             iv_pwr_slope[1]);

    FAPI_INF("DIMM power curve intercepts are %d %d, DIMM power thermal limits are %d %d",
             iv_pwr_int[0],
             iv_pwr_int[1],
             iv_dimm_thermal_limit[0],
             iv_dimm_thermal_limit[1]);

    FAPI_ASSERT( (iv_databus_port_max != 0),
                 fapi2::MSS_NO_DATABUS_UTILIZATION()
                 .set_PORT_DATABUS_UTIL(iv_databus_port_max)
                 .set_DIMM_COUNT(mss::count_dimm(iv_target)),
                 "Failed to get max databus utilization for target %s",
                 mss::c_str(iv_target));

    FAPI_ASSERT( (iv_port_power_limit != 0),
                 fapi2::MSS_NO_PORT_POWER_LIMIT()
                 .set_COUNT_DIMMS( mss::count_dimm(iv_target))
                 .set_PORT_POWER_LIMIT( iv_port_power_limit),
                 "Error calculating port_power_limit on target %s with %d DIMMs installed",
                 mss::c_str(iv_target),
                 iv_port_power_limit);

    //Checking to make sure all of the attributes are valid
    for ( const auto& l_dimm : mss::find_targets<TARGET_TYPE_DIMM>(iv_target) )
    {
        const auto l_pos = mss::index(l_dimm);
        FAPI_ASSERT( (iv_pwr_int[l_pos] != 0),
                     fapi2::MSS_POWER_INTERCEPT_NOT_SET(),
                     "The attribute ATTR_MSS_TOTAL_PWR_INTERCEPT equals 0 for %s",
                     mss::c_str(l_dimm));

        FAPI_ASSERT( (iv_pwr_slope[l_pos] != 0),
                     fapi2::MSS_POWER_SLOPE_NOT_SET(),
                     "The attribute ATTR_MSS_TOTAL_PWR_SLOPE equals 0 for %s",
                     mss::c_str(l_dimm));
    }

fapi_try_exit:
    o_rc = fapi2::current_err;
    return;
}

///
/// @brief Set ATTR_MSS_CHANNEL_PAIR_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT and _PER_PORT
/// @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 throttle::power_regulator_throttles ()
{
    double l_port_power_calc_idle = 0;
    double l_port_power_calc_max = 0;
    uint32_t l_port_power_slope = 0;
    uint32_t l_port_power_int = 0;
    double l_calc_util_port = 0;
    double  l_databus_dimm_max[MAX_DIMM_PER_PORT] = {};
    double  l_calc_databus_port_idle[MAX_DIMM_PER_PORT] = {IDLE_UTIL, IDLE_UTIL};

    FAPI_INF("Starting power regulator throttles");

    //Decide utilization for each dimm based off of dimm count and power slopes
    FAPI_TRY( calc_databus(iv_databus_port_max, l_databus_dimm_max),
              "Failed to calculate each DIMMs' percentage of dram databus utilization for target %s, max port databus is %s",
              mss::c_str(iv_target),
              iv_databus_port_max);

    //Use the dimm utilizations and dimm power slopes to calculate port min and max power
    FAPI_TRY( calc_port_power(l_calc_databus_port_idle,
                              l_databus_dimm_max,
                              l_port_power_calc_idle,
                              l_port_power_calc_max),
              "Failed to calculate the max and idle power for port %s",
              mss::c_str(iv_target));

    FAPI_INF("POWER throttles: %s max port power is %f", l_port_power_calc_max);

    //Calculate the power curve slope and intercept using the port's min and max power values
    FAPI_TRY(calc_power_curve(l_port_power_calc_idle,
                              l_port_power_calc_max,
                              l_port_power_slope,
                              l_port_power_int),
             "Failed to calculate the power curve for port %s, calculated port power max is %d, idle is %d",
             mss::c_str(iv_target),
             l_port_power_calc_max,
             l_port_power_calc_idle);

    FAPI_INF("POWER Port power limit is %d", iv_port_power_limit);
    //Calculate the port's utilization to get under watt target using the port's calculated slopes
    calc_util_usage(l_port_power_slope,
                    l_port_power_int,
                    iv_port_power_limit,<commit_msg>Fix missing c_str printour in eff_config_thermal<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file throttle.C
/// @brief Determine throttle settings for memory
///
// *HWP HWP Owner: <NAME> <<EMAIL>>
// *HWP HWP Backup: <NAME> <<EMAIL>>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB
//std lib
#include<algorithm>
// fapi2
#include <fapi2.H>

// mss lib
#include <lib/power_thermal/throttle.H>
#include <lib/utils/count_dimm.H>
#include <mss.H>
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_DIMM;
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<fapi2::TARGET_TYPE_MCA>& 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_calc_port_maxpower(0)
{
    //holder for watt_target to add up for port
    uint32_t l_dimm_power_limits [MAX_DIMM_PER_PORT] = {};

    FAPI_TRY( 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( dimm_thermal_limit( iv_target, iv_dimm_thermal_limit) );
    FAPI_TRY( total_pwr_intercept( iv_target, iv_pwr_int));
    FAPI_TRY( total_pwr_slope( iv_target, iv_pwr_slope));
    FAPI_TRY( runtime_mem_throttled_n_commands_per_slot(iv_target, iv_runtime_n_slot ) );
    FAPI_TRY( runtime_mem_throttled_n_commands_per_port(iv_target, iv_runtime_n_port ) );
    FAPI_TRY( mem_watt_target( iv_target, l_dimm_power_limits) );
    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<TARGET_TYPE_DIMM>(iv_target) )
    {
        iv_port_power_limit += l_dimm_power_limits[mss::index(l_dimm)];
    }

    FAPI_INF("Setting up throttle for target %s, Values are: max databus is %d, uplifts are %d %d, runtime throttles are %d %d",
             mss::c_str(iv_target),
             iv_databus_port_max,
             iv_power_uplift,
             iv_power_uplift_idle,
             iv_runtime_n_slot,
             iv_runtime_n_port);

    FAPI_INF("The dimm power limit for dimm0 is %d, dimm1 is %d,  port power limit is %d, dram clocks are %d, dimm power curve slopes are %d %d,",
             l_dimm_power_limits[0],
             l_dimm_power_limits[1],
             iv_port_power_limit,
             iv_m_clocks,
             iv_pwr_slope[0],
             iv_pwr_slope[1]);

    FAPI_INF("DIMM power curve intercepts are %d %d, DIMM power thermal limits are %d %d",
             iv_pwr_int[0],
             iv_pwr_int[1],
             iv_dimm_thermal_limit[0],
             iv_dimm_thermal_limit[1]);

    FAPI_ASSERT( (iv_databus_port_max != 0),
                 fapi2::MSS_NO_DATABUS_UTILIZATION()
                 .set_PORT_DATABUS_UTIL(iv_databus_port_max)
                 .set_DIMM_COUNT(mss::count_dimm(iv_target)),
                 "Failed to get max databus utilization for target %s",
                 mss::c_str(iv_target));

    FAPI_ASSERT( (iv_port_power_limit != 0),
                 fapi2::MSS_NO_PORT_POWER_LIMIT()
                 .set_COUNT_DIMMS( mss::count_dimm(iv_target))
                 .set_PORT_POWER_LIMIT( iv_port_power_limit),
                 "Error calculating port_power_limit on target %s with %d DIMMs installed",
                 mss::c_str(iv_target),
                 iv_port_power_limit);

    //Checking to make sure all of the attributes are valid
    for ( const auto& l_dimm : mss::find_targets<TARGET_TYPE_DIMM>(iv_target) )
    {
        const auto l_pos = mss::index(l_dimm);
        FAPI_ASSERT( (iv_pwr_int[l_pos] != 0),
                     fapi2::MSS_POWER_INTERCEPT_NOT_SET(),
                     "The attribute ATTR_MSS_TOTAL_PWR_INTERCEPT equals 0 for %s",
                     mss::c_str(l_dimm));

        FAPI_ASSERT( (iv_pwr_slope[l_pos] != 0),
                     fapi2::MSS_POWER_SLOPE_NOT_SET(),
                     "The attribute ATTR_MSS_TOTAL_PWR_SLOPE equals 0 for %s",
                     mss::c_str(l_dimm));
    }

fapi_try_exit:
    o_rc = fapi2::current_err;
    return;
}

///
/// @brief Set ATTR_MSS_CHANNEL_PAIR_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT and _PER_PORT
/// @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 throttle::power_regulator_throttles ()
{
    double l_port_power_calc_idle = 0;
    double l_port_power_calc_max = 0;
    uint32_t l_port_power_slope = 0;
    uint32_t l_port_power_int = 0;
    double l_calc_util_port = 0;
    double  l_databus_dimm_max[MAX_DIMM_PER_PORT] = {};
    double  l_calc_databus_port_idle[MAX_DIMM_PER_PORT] = {IDLE_UTIL, IDLE_UTIL};

    FAPI_INF("Starting power regulator throttles");

    //Decide utilization for each dimm based off of dimm count and power slopes
    FAPI_TRY( calc_databus(iv_databus_port_max, l_databus_dimm_max),
              "Failed to calculate each DIMMs' percentage of dram databus utilization for target %s, max port databus is %s",
              mss::c_str(iv_target),
              iv_databus_port_max);

    //Use the dimm utilizations and dimm power slopes to calculate port min and max power
    FAPI_TRY( calc_port_power(l_calc_databus_port_idle,
                              l_databus_dimm_max,
                              l_port_power_calc_idle,
                              l_port_power_calc_max),
              "Failed to calculate the max and idle power for port %s",
              mss::c_str(iv_target));

    FAPI_INF("POWER throttles: %s max port power is %f", mss::c_str(iv_target), l_port_power_calc_max);

    //Calculate the power curve slope and intercept using the port's min and max power values
    FAPI_TRY(calc_power_curve(l_port_power_calc_idle,
                              l_port_power_calc_max,
                              l_port_power_slope,
                              l_port_power_int),
             "Failed to calculate the power curve for port %s, calculated port power max is %d, idle is %d",
             mss::c_str(iv_target),
             l_port_power_calc_max,
             l_port_power_calc_idle);

    FAPI_INF("POWER Port power limit is %d", iv_port_power_limit);
    //Calculate the port's utilization to get under watt target using the port's calculated slopes
    calc_util_usage(l_port_power_slope,
                    l_port_power_int,
                    iv_port_power_limit,
{'fraction_non_alphanumeric': 0.08639247677317018, 'fraction_numerical': 0.007477906186267845, 'mean_word_length': 1.9784039142905347, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 62, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5397270', 'n_tokens_mistral': 5709, 'n_tokens_neox': 5503, 'n_words': 1263}