summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/utils/mss_math.H
blob: 65fc0f898ea17936cbe2f2b556f540464bff9504 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/mss_math.H $              */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] 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                                                     */
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#ifndef _MSS_MATH_H_
#define _MSS_MATH_H_

#include <fapi2.H>
#include <cstdint>

namespace mss
{
///
/// @brief Calculates inclusive range
/// @tparam T input and output type
/// @param[in] i_start starting point
/// @param[in] i_end ending point
/// @return inclusive range calculation
///
// TODO RTC:174277 - create unit test structure for generic/memory
template<typename T >
inline constexpr T inclusive_range( const T i_start, const T i_end )
{
    return (i_end - i_start) + 1;
}

///
/// @brief Poor man's round half away from 0
/// @param[in] i_input starting point
/// @return rounded int64_t value
/// @note HB doesn't have std::round, referenced from:
/// https://stackoverflow.com/questions/4572556/concise-way-to-implement-round-in-c
///
inline int64_t round_half_away_from_zero( const double i_input )
{
    // Casting to avoid comparison of diff data types
    // Explicitly casting INT64_MAX to avoid truncation of casting
    // floating point to integer
    if( i_input > static_cast<double>(INT64_MAX) )
    {
        FAPI_ERR("Invalid input greater than %d", INT64_MAX);
        fapi2::Assert(false);
    }

    return ( i_input < 0.0 ? static_cast<int64_t>(i_input - 0.5) :  static_cast<int64_t>(i_input + 0.5) );
}

///
/// @brief Divide and round unsigned values
/// @tparam T input and output types
/// @param[in] i_divisor the divisor (number to be divided)
/// @param[in] i_dividend the dividend (number to divide by)
/// @param[out] o_quotient the quotient
/// @return FAPI2_RC_SUCCESS iff successful
///
template<typename T>
inline fapi2::ReturnCode divide_and_round( const T i_divisor,
        const T i_dividend,
        T& o_quotient )
{
    o_quotient = 0;

    // Zero dividend would cause a divide-by-zero, so prevent that
    FAPI_ASSERT( (i_dividend != 0),
                 fapi2::MSS_DIVIDE_BY_ZERO()
                 .set_DIVISOR(i_divisor)
                 .set_DIVIDEND(i_dividend),
                 "Caught an attempt to divide by zero (%d / %d)",
                 i_divisor, i_dividend );

    {
        const auto l_quotient_unrounded = i_divisor / i_dividend;
        const auto l_remainder = i_divisor % i_dividend;

        // Round the quotient up or down depending on the remainder
        o_quotient = l_quotient_unrounded + ((l_remainder >= i_dividend / 2) ? 1 : 0);
    }
    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] 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
///
inline uint32_t round_up(const double i_val)
{
    //convert to uint to truncate decimals and convert back to double for comparison
    uint32_t temp = uint32_t (i_val);

    //if not equal, lost something from truncating, so add 1
    temp += (temp == i_val) ? 0 : 1;

    //Truncate final value
    return temp;
}

}// mss

#endif
OpenPOWER on IntegriCloud