diff options
author | Stephen Glancy <sglancy@us.ibm.com> | 2016-10-11 20:54:09 -0500 |
---|---|---|
committer | Christian R. Geddes <crgeddes@us.ibm.com> | 2016-10-31 10:36:30 -0400 |
commit | c7cf0b2d56200537be4227b246fa5c4754cc7306 (patch) | |
tree | 1d00ece50c9f5a6e582e431ebc2e1b174edbb319 /src/import/chips/p9/procedures/hwp/memory/lib/freq | |
parent | a0575efc0dae3b41ee95e55d5a5e7acb12418c90 (diff) | |
download | talos-hostboot-c7cf0b2d56200537be4227b246fa5c4754cc7306.tar.gz talos-hostboot-c7cf0b2d56200537be4227b246fa5c4754cc7306.zip |
Fixed CL and timing bugs, unit test augmentations
Fix 3DS timing params for SLR and DLR and add unit tests.
Fix CL setting for non-configured ports and add unit CL tests
Fixed SPD timing errors, CL, MR, and ddr_phy UT bugs
Change-Id: Icc7efcc6f5a01ceee168a10ca8236cb656ba013c
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31066
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Matt K. Light <mklight@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Reviewed-by: Brian R. Silver <bsilver@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31484
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/freq')
3 files changed, 297 insertions, 352 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C index 07e4ca4d2..c275c1e0d 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C @@ -44,6 +44,7 @@ #include <lib/spd/common/spd_decoder.H> #include <lib/freq/cas_latency.H> #include <lib/freq/cycle_time.H> +#include <lib/freq/sync.H> #include <lib/utils/conversions.H> #include <lib/eff_config/timing.H> #include <lib/utils/find.H> @@ -66,17 +67,19 @@ namespace mss /// @param[in] i_caches decoder caches /// cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, - const std::map<uint32_t, std::shared_ptr<spd::decoder> >& i_caches): + const std::map<uint32_t, std::shared_ptr<spd::decoder> >& i_caches, + fapi2::ReturnCode& o_rc): iv_dimm_list_empty(false), + iv_target(i_target), iv_largest_taamin(0), iv_proposed_tck(0), - iv_common_CL(UINT64_MAX) // Masks out supported CLs + iv_common_cl(UINT64_MAX) // Masks out supported CLs { - const auto l_dimm_list = find_targets<TARGET_TYPE_DIMM>(i_target); + const auto l_dimm_list = find_targets<TARGET_TYPE_DIMM>(iv_target); if(l_dimm_list.empty()) { - FAPI_INF("cas latency ctor seeing no DIMM on %s", mss::c_str(i_target)); + FAPI_INF("cas latency ctor seeing no DIMM on %s", mss::c_str(iv_target)); iv_dimm_list_empty = true; return; } @@ -86,105 +89,169 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, const auto l_dimm_pos = pos(l_dimm); // Find decoder factory for this dimm position + // Can't be const auto because HB needs to implement + // something - AAM auto l_it = i_caches.find(l_dimm_pos); FAPI_TRY( check::spd::invalid_cache(l_dimm, l_it != i_caches.end(), l_dimm_pos), - "Failed to get valid cache"); + "%s. Failed to get valid cache", mss::c_str(iv_target) ); { // Retrive timing values from the SPD - uint64_t l_tAAmin_in_ps = 0; - uint64_t l_tCKmax_in_ps = 0; - uint64_t l_tCKmin_in_ps = 0; + uint64_t l_taa_min_in_ps = 0; + uint64_t l_tckmax_in_ps = 0; + uint64_t l_tck_min_in_ps = 0; - FAPI_TRY( get_taamin(l_dimm, l_it->second, l_tAAmin_in_ps), - "Failed to get tAAmin"); - FAPI_TRY( get_tckmax(l_dimm, l_it->second, l_tCKmax_in_ps), - "Failed to get tCKmax" ); - FAPI_TRY( get_tckmin(l_dimm, l_it->second, l_tCKmin_in_ps), - "Failed to get tCKmin"); + FAPI_TRY( get_taamin(l_dimm, l_it->second, l_taa_min_in_ps), + "%s. Failed to get tAAmin", mss::c_str(iv_target) ); + FAPI_TRY( get_tckmax(l_dimm, l_it->second, l_tckmax_in_ps), + "%s. Failed to get tCKmax", mss::c_str(iv_target) ); + FAPI_TRY( get_tckmin(l_dimm, l_it->second, l_tck_min_in_ps), + "%s. Failed to get tCKmin", mss::c_str(iv_target) ); // Determine largest tAAmin value - iv_largest_taamin = std::max(iv_largest_taamin, l_tAAmin_in_ps); + iv_largest_taamin = std::max(iv_largest_taamin, l_taa_min_in_ps); // Determine a proposed tCK value that is greater than or equal tCKmin // But less than tCKmax - iv_proposed_tck = std::max(iv_proposed_tck, l_tCKmin_in_ps); - iv_proposed_tck = std::min(iv_proposed_tck, l_tCKmax_in_ps); + iv_proposed_tck = std::max(iv_proposed_tck, l_tck_min_in_ps); + iv_proposed_tck = std::min(iv_proposed_tck, l_tckmax_in_ps); + } + + // Collecting stack type + // If I have at least one 3DS DIMM connected I have + // to use 3DS tAAmax of 21.5 ps versus 18 ps for non-3DS DDR4 + if( iv_is_3ds != loading::IS_3DS) + { + uint8_t l_stack_type = 0; + FAPI_TRY( l_it->second->prim_sdram_signal_loading(l_dimm, l_stack_type) ); + + // Is there a more algorithmic efficient approach? - AAM + iv_is_3ds = (l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) ? + loading::IS_3DS : loading::NOT_3DS; } { // Retrieve dimm supported cas latencies from SPD - uint64_t l_dimm_supported_CL = 0; + uint64_t l_dimm_supported_cl = 0; FAPI_TRY( l_it->second->supported_cas_latencies(l_dimm, - l_dimm_supported_CL), - "Failed to get supported CAS latency"); + l_dimm_supported_cl), + "%s. Failed to get supported CAS latency", mss::c_str(iv_target) ); - // ANDing bitmap from all modules creates a bitmap w/a common CL - iv_common_CL &= l_dimm_supported_CL; + // Bitwise ANDING the bitmap from all modules creates a bitmap w/a common CL + iv_common_cl &= l_dimm_supported_cl; } }// dimm + // Limit tCK from the max supported dimm speed in the system + // So that this is taken into account when calculating CL + { + // Defaulting to non-zero speed + uint64_t l_freq_override = fapi2::ENUM_ATTR_MSS_FREQ_MT2666; + uint64_t l_tck_override_in_ps = 0; + + FAPI_TRY( select_supported_freq(iv_target, l_freq_override), + "%s. Failed select_supported_freq()", mss::c_str(iv_target) ); + FAPI_TRY( freq_to_ps(l_freq_override, l_tck_override_in_ps), + "%s. Failed freq_to_ps()", mss::c_str(iv_target) ); + + FAPI_INF("%s. Selected supported dimm speed %d MT/s (Clock period %d in ps)", + mss::c_str(iv_target), l_freq_override, l_tck_override_in_ps); + + iv_proposed_tck = std::max( l_tck_override_in_ps, iv_proposed_tck ); + FAPI_INF("%s. Initial proposed tCK in ps: %d", mss::c_str(iv_target), iv_proposed_tck); + } + // Why didn't I encapsulate common CL operations and checking in a function // like the timing params? Well, I want to check the "final" common CL and - // the creation of common CLs (ANDing bits) is dimm level operation - FAPI_ASSERT(iv_common_CL != 0, + // the creation of common CLs (bitwise ANDING) is at the dimm level operation + FAPI_ASSERT(iv_common_cl != 0, fapi2::MSS_NO_COMMON_SUPPORTED_CL(). - set_CL_SUPPORTED(iv_common_CL). - set_MCS_TARGET(i_target), - "No common CAS latencies (CL bitmap = 0)"); + set_CL_SUPPORTED(iv_common_cl). + set_MCS_TARGET(iv_target), + "%s. No common CAS latencies (CL bitmap = 0)", + mss::c_str(iv_target) ); - FAPI_DBG("Supported CL bitmap 0x%llX", iv_common_CL); + FAPI_INF("%s. Supported CL bitmap 0x%llX", mss::c_str(iv_target), iv_common_cl); - // If we reach here al instance vars should have successfully initialized + // If we reach here all member vars should have successfully initialized + o_rc = fapi2::FAPI2_RC_SUCCESS; return; // If we reach here something failed above. fapi_try_exit: - FAPI_ERR("Something went wrong retreiving dimm info"); + o_rc = fapi2::FAPI2_RC_FALSE; + FAPI_ERR("%s. Something went wrong retrieving DIMM info", mss::c_str(iv_target) ); }// ctor /// -/// @brief Calculates CAS latency and checks if it is supported and within JEDEC spec. +/// @brief Constructor that allows the user to set desired data in lieu of SPD /// @param[in] i_target the controller target +/// @param[in] i_taa_min largest tAAmin we want to set in picoseconds +/// @param[in] i_tck_min proposed tCKmin in picoseconds +/// @param[in] i_common_cl_mask common CAS latency mask we want to force (bitmap) +/// @param[in] i_is_3ds boolean for whether this is a 3DS SDRAM, 3DS is true, false otherwise (default) +/// +cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, + const uint64_t i_taa_min, + const uint64_t i_tck_min, + const uint64_t i_common_cl_mask, + const loading i_is_3ds): + iv_dimm_list_empty(false), + iv_target(i_target), + iv_largest_taamin(i_taa_min), + iv_proposed_tck(i_tck_min), + iv_common_cl(i_common_cl_mask), + iv_is_3ds(i_is_3ds) +{ + const auto l_dimm_list = find_targets<TARGET_TYPE_DIMM>(iv_target); + + if(l_dimm_list.empty()) + { + FAPI_INF("cas latency ctor seeing no DIMM on %s", mss::c_str(iv_target)); + iv_dimm_list_empty = true; + } +} + +/// +/// @brief Calculates CAS latency and checks if it is supported and within JEDEC spec. /// @param[out] o_cas_latency selected CAS latency -/// @param[out] o_tCK cycle time corresponding to seleted CAS latency +/// @param[out] o_tck cycle time corresponding to selected CAS latency /// @return fapi2::FAPI2_RC_SUCCESS if ok /// -fapi2::ReturnCode cas_latency::find_CL(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, - uint64_t& o_cas_latency, - uint64_t& o_tCK) +fapi2::ReturnCode cas_latency::find_cl(uint64_t& o_cas_latency, + uint64_t& o_tck) { uint64_t l_desired_cas_latency = 0; if(!iv_dimm_list_empty) { // Create a vector filled with common CLs from buffer - std::vector<uint64_t> l_supported_CLs = create_common_cl_vector(iv_common_CL); + std::vector<uint64_t> l_supported_cls = integral_bitmap_to_vector(iv_common_cl); //For a proposed tCK value between tCKmin(all) and tCKmax, determine the desired CAS Latency. - l_desired_cas_latency = calc_cas_latency(iv_largest_taamin, iv_proposed_tck); + FAPI_TRY( calc_cas_latency(iv_largest_taamin, iv_proposed_tck, l_desired_cas_latency), + "%s. Failed to calculate CAS latency", mss::c_str(iv_target) ); //Chose an actual CAS Latency (CLactual) that is greater than or equal to CLdesired //and is supported by all modules on the memory channel - FAPI_TRY( choose_actual_CL(l_supported_CLs, iv_largest_taamin, iv_proposed_tck, l_desired_cas_latency), - "Failed choose_actual_CL()"); + FAPI_TRY( is_cl_supported_in_common(l_supported_cls, l_desired_cas_latency), + "%s. Failed to find a common CAS latency supported among all modules", mss::c_str(iv_target) ); - // Once the calculation of CLactual is completed, the BIOS must also + // Once the calculation of CLactual is completed // verify that this CAS Latency value does not exceed tAAmax. - //If not, choose a lower CL value and repeat until a solution is found. - FAPI_TRY( validate_valid_CL(l_supported_CLs, iv_largest_taamin, iv_proposed_tck, l_desired_cas_latency), - "Failed validate_valid_CL()"); + FAPI_TRY( is_cl_exceeding_taa_max (l_desired_cas_latency, iv_proposed_tck), + "%s. Failed to find a CL value that doesn't exceed tAAmax", mss::c_str(iv_target) ); } // Update output values after all criteria is met // If the MCS has no dimm configured than both // l_desired_latency & iv_proposed_tck is 0 by initialization o_cas_latency = l_desired_cas_latency; - o_tCK = iv_proposed_tck; + o_tck = iv_proposed_tck; fapi_try_exit: return fapi2::current_err; @@ -207,27 +274,32 @@ fapi2::ReturnCode cas_latency::get_taamin(const fapi2::Target<TARGET_TYPE_DIMM>& int64_t l_fine_timebase = 0; // Retrieve timing parameters - FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase) ); - FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase) ); - FAPI_TRY( i_pDecoder->min_cas_latency_time(i_target, l_timing_mtb) ); - FAPI_TRY( i_pDecoder->fine_offset_min_taa(i_target, l_timing_ftb) ); + FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase), + "%s. Failed medium_timebase()", mss::c_str(iv_target) ); + FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase), + "%s. Failed fine_timebase()", mss::c_str(iv_target) ); + FAPI_TRY( i_pDecoder->min_cas_latency_time(i_target, l_timing_mtb), + "%s. Failed min_cas_latency_time()", mss::c_str(iv_target) ); + FAPI_TRY( i_pDecoder->fine_offset_min_taa(i_target, l_timing_ftb), + "%s. Failed fine_offset_min_taa()", mss::c_str(iv_target) ); // Calculate timing value - o_value = uint64_t(calc_timing_from_timebase(l_timing_mtb, - l_medium_timebase, - l_timing_ftb, - l_fine_timebase)); + o_value = spd::calc_timing_from_timebase(l_timing_mtb, + l_medium_timebase, + l_timing_ftb, + l_fine_timebase); // Sanity check FAPI_ASSERT(o_value > 0, fapi2::MSS_INVALID_TIMING_VALUE(). set_VALUE(o_value). set_DIMM_TARGET(i_target), - "tAAmin invalid (<= 0) : %d", + "%s. tAAmin invalid (<= 0) : %d", + mss::c_str(iv_target), o_value); - FAPI_DBG( "%s. tAAmin (ps): %d", - c_str(i_target), + FAPI_INF( "%s. tAAmin (ps): %d", + mss::c_str(iv_target), o_value); fapi_try_exit: @@ -252,34 +324,38 @@ fapi2::ReturnCode cas_latency::get_tckmin(const fapi2::Target<TARGET_TYPE_DIMM>& int64_t l_fine_timebase = 0; // Retrieve timing parameters - FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase) ); - FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase) ); - FAPI_TRY( i_pDecoder->min_cycle_time(i_target, l_timing_mtb) ); - FAPI_TRY( i_pDecoder->fine_offset_min_tck(i_target, l_timing_ftb) ); + FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase), + "%s. Failed medium_timebase()", mss::c_str(iv_target) ); + FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase), + "%s. Failed fine_timebase()", mss::c_str(iv_target) ); + FAPI_TRY( i_pDecoder->min_cycle_time(i_target, l_timing_mtb), + "%s. Failed min_cycle_time()", mss::c_str(iv_target) ); + FAPI_TRY( i_pDecoder->fine_offset_min_tck(i_target, l_timing_ftb), + "%s. Failed fine_offset_min_tck()", mss::c_str(iv_target) ); // Calculate timing value - o_value = uint64_t( calc_timing_from_timebase(l_timing_mtb, - l_medium_timebase, - l_timing_ftb, - l_fine_timebase) ); + o_value = spd::calc_timing_from_timebase(l_timing_mtb, + l_medium_timebase, + l_timing_ftb, + l_fine_timebase); // Sanity check FAPI_ASSERT(o_value > 0, fapi2::MSS_INVALID_TIMING_VALUE(). set_VALUE(o_value). set_DIMM_TARGET(i_target), - "tCKmin invalid (<= 0) : %d", + "%s. tCKmin invalid (<= 0) : %d", + mss::c_str(iv_target), o_value); - FAPI_DBG("%s. tCKmin (ps): %d", - c_str(i_target), + FAPI_INF("%s. tCKmin (ps): %d", + mss::c_str(iv_target), o_value ); fapi_try_exit: return fapi2::current_err; } - /// /// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD /// @param[in] i_target the dimm target @@ -297,27 +373,32 @@ fapi2::ReturnCode cas_latency::get_tckmax(const fapi2::Target<TARGET_TYPE_DIMM>& int64_t l_fine_timebase = 0; // Retrieve timing parameters - FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase) ); - FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase) ); - FAPI_TRY( i_pDecoder->max_cycle_time(i_target, l_timing_mtb) ); - FAPI_TRY( i_pDecoder->fine_offset_max_tck(i_target, l_timing_ftb) ); + FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase), + "%s. Failed medium_timebase()", mss::c_str(iv_target) ); + FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase), + "%s. Failed fine_timebase()", mss::c_str(iv_target) ); + FAPI_TRY( i_pDecoder->max_cycle_time(i_target, l_timing_mtb), + "%s. Failed max_cycle_time()", mss::c_str(iv_target) ); + FAPI_TRY( i_pDecoder->fine_offset_max_tck(i_target, l_timing_ftb), + "%s. Failed fine_offset_max_tck()", mss::c_str(iv_target) ); // Calculate timing value - o_value = uint64_t(calc_timing_from_timebase(l_timing_mtb, - l_medium_timebase, - l_timing_ftb, - l_fine_timebase) ); + o_value = spd::calc_timing_from_timebase(l_timing_mtb, + l_medium_timebase, + l_timing_ftb, + l_fine_timebase); // Sanity check FAPI_ASSERT(o_value > 0, fapi2::MSS_INVALID_TIMING_VALUE(). set_VALUE(o_value). set_DIMM_TARGET(i_target), - "tCKmax invalid (<= 0) : %d", + "%s. tCKmax invalid (<= 0) : %d", + mss::c_str(iv_target), o_value); - FAPI_DBG( "%s. tCKmax (ps): %d", - c_str(i_target), + FAPI_INF( "%s. tCKmax (ps): %d", + mss::c_str(iv_target), o_value); fapi_try_exit: @@ -326,231 +407,133 @@ fapi_try_exit: /// /// @brief Gets max CAS latency (CL) for the appropriate High/Low Range -/// @param[in] i_supported_CL +/// @param[in] i_supported_cl /// @return the maximum supported CL /// @note Depends on bit 7 of byte 23 from the DDR4 SPD /// -inline uint64_t cas_latency::get_max_CL(const fapi2::buffer<uint64_t> i_supported_CL) const +inline uint64_t cas_latency::get_max_cl(const fapi2::buffer<uint64_t> i_supported_cl) const { - constexpr uint64_t CAS_LAT_RANGE_BIT = 31; - // If the last of Byte 23 of the SPD is 1, this selects CL values // in the High CL range (23 to 52) // If the last bit of Byte 23 of the SPD is 0, this selects CL values // in the Low CL range (7 to 36) //Assuming bitmap is right aligned - return i_supported_CL.getBit<CAS_LAT_RANGE_BIT>() ? HIGH_RANGE_MAX_CL_DDR4 : LOW_RANGE_MAX_CL_DDR4; + return i_supported_cl.getBit<CAS_LAT_RANGE_BIT>() ? HIGH_RANGE_MAX_CL_DDR4 : LOW_RANGE_MAX_CL_DDR4; } /// /// @brief Gets min CAS latency (CL) for the appropriate High/Low Range -/// @param[in] i_supported_CL +/// @param[in] i_supported_cl /// @return the minimum supported CL /// @note Depends on bit 7 of byte 23 from the DDR4 SPD /// -inline uint64_t cas_latency::get_min_CL(const fapi2::buffer<uint64_t>& i_supported_CL) const +inline uint64_t cas_latency::get_min_cl(const fapi2::buffer<uint64_t>& i_supported_cl) const { // If the last of Byte 23 of the SPD is 1, this selects CL values // in the High CL range (23 to 52) // If the last bit of Byte 23 of the SPD is 0, this selects CL values // in the Low CL range (7 to 36) - constexpr uint64_t CAS_LAT_RANGE_BIT = 31; - - return i_supported_CL.getBit<CAS_LAT_RANGE_BIT>() ? HIGH_RANGE_MIN_CL_DDR4 : LOW_RANGE_MIN_CL_DDR4; + return i_supported_cl.getBit<CAS_LAT_RANGE_BIT>() ? HIGH_RANGE_MIN_CL_DDR4 : LOW_RANGE_MIN_CL_DDR4; } /// /// @brief Calculates CAS latency time from tCK and tAA -/// @param[in] i_tAA cas latency time -/// @param[in] i_tCK min cycle time -/// @return o_cas_latency calculated CAS latency +/// @param[in] i_taa cas latency time +/// @param[in] i_tck min cycle time +/// @param[out] o_cas_latency calculated CAS latency +/// @return FAPI2_RC_SUCCESS iff okay /// -inline uint64_t cas_latency::calc_cas_latency(const uint64_t i_tAA, const uint64_t i_tCK) const +inline fapi2::ReturnCode cas_latency::calc_cas_latency(const uint64_t i_taa, + const uint64_t i_tck, + uint64_t& o_cas_latency) const { - uint64_t l_quotient = i_tAA / i_tCK; - uint64_t l_remainder = i_tAA % i_tCK; - uint64_t o_cas_latency = l_quotient + (l_remainder == 0 ? 0 : 1); + FAPI_TRY( spd::calc_nck(i_taa, i_tck, INVERSE_DDR4_CORRECTION_FACTOR, o_cas_latency) ); - FAPI_DBG("Calculated CL = tAA / tCK : %d / %d = %d", - i_tAA, - i_tCK, + FAPI_INF("%s. tAA (ps): %d, tCK (ps): %d, CL (nck): %d", + mss::c_str(iv_target), + i_taa, + i_tck, o_cas_latency); - return o_cas_latency; +fapi_try_exit: + return fapi2::current_err; } /// /// @brief Helper function to create a vector of supported CAS latencies from a bitmap -/// @param[in] i_common_CL common CAS latency bitmap +/// @param[in] i_common_cl common CAS latency bitmap /// @return vector of supported CAS latencies /// -std::vector<uint64_t> cas_latency::create_common_cl_vector(const uint64_t i_common_CL) const +std::vector<uint64_t> cas_latency::integral_bitmap_to_vector(const uint64_t i_common_cl) const { std::vector<uint64_t> l_vector; - fapi2::buffer<uint64_t> l_CL_mask(i_common_CL); + fapi2::buffer<uint64_t> l_cl_mask(i_common_cl); - uint64_t min_CL = get_min_CL(l_CL_mask); - uint64_t max_CL = get_max_CL(l_CL_mask); + uint64_t min_cl = get_min_cl(l_cl_mask); + uint64_t max_cl = get_max_cl(l_cl_mask); - FAPI_DBG("min CL %lu", min_CL); - FAPI_DBG("max CL %lu", max_CL); + FAPI_INF("%s. min CL %lu", mss::c_str(iv_target), min_cl); + FAPI_INF("%s. max CL %lu", mss::c_str(iv_target), max_cl); - for(uint64_t cas_latency = min_CL; cas_latency <= max_CL; ++cas_latency) + for(uint64_t l_cas_latency = min_cl; l_cas_latency <= max_cl; ++l_cas_latency) { // 64 bit is buffer length - indexed at 0 - 63 constexpr uint64_t l_buffer_length = 64 - 1; - uint64_t l_bit_pos = l_buffer_length - (cas_latency - min_CL); + uint64_t l_bit_pos = l_buffer_length - (l_cas_latency - min_cl); // Traversing through buffer one bit at a time // 0 means unsupported CAS latency // 1 means supported CAS latency // We are pushing supported CAS latencies into a vector for direct use - if( l_CL_mask.getBit(l_bit_pos) ) + if( l_cl_mask.getBit(l_bit_pos) ) { - l_vector.push_back(cas_latency); + // I want don't this to print all the time, DBG is fine + FAPI_DBG( "%s. Supported CL (%d) from common CL mask", + mss::c_str(iv_target), l_cas_latency ); + + l_vector.push_back(l_cas_latency); } } return l_vector; } - /// /// @brief Determines if a requested CAS latency (CL) is supported in the bin of common CLs -/// @param[in] i_common_CLs vector of common CAS latencies +/// @param[in] i_common_cls vector of common CAS latencies /// @param[in] i_cas_latency CAS latency we are comparing against -/// @return true if CAS latency is supported +/// @return FAPI2_RC_SUCCESS iff ok /// -inline bool cas_latency::is_CL_supported_in_common(const std::vector<uint64_t>& i_common_CLs, +inline fapi2::ReturnCode cas_latency::is_cl_supported_in_common(const std::vector<uint64_t>& i_common_cls, const uint64_t i_cas_latency) const { - return std::binary_search(i_common_CLs.begin(), i_common_CLs.end(), i_cas_latency); + return std::binary_search(i_common_cls.begin(), i_common_cls.end(), i_cas_latency) == true ? + fapi2::FAPI2_RC_SUCCESS : fapi2::FAPI2_RC_FALSE; } /// /// @brief Checks that CAS latency doesn't exceed largest CAS latency time /// @param[in] i_cas_latency cas latency -/// @param[in] i_tCK cycle time -/// @return bool true if CAS latency exceeds the largest CAS latency time -/// false otherwise -/// -inline bool cas_latency::is_CL_exceeding_tAAmax(const uint64_t i_cas_latency, - const uint64_t i_tCK) const -{ - // JEDEC spec requirement - return (i_cas_latency * i_tCK > TAA_MAX_DDR4); -} - - -/// -/// @brief Helper function to determines next lowest CAS latency (CL) -/// @param[in] i_common_CLs vector of common CAS latencies -/// @param[in] i_desired_cas_latency current CAS latency -/// @return the next lowest CL -/// -inline uint64_t cas_latency::next_lowest_CL(const std::vector<uint64_t>& i_common_CLs, - const uint64_t i_desired_cas_latency) -{ - auto iterator = std::lower_bound(i_common_CLs.begin(), i_common_CLs.end(), i_desired_cas_latency); - return *(--iterator); -} - -/// -/// @brief Checks that CAS latency (CL) is supported among all dimms -/// and if it isn't we try to find a CL that is. -/// @param[in] i_common_CLs vector of common CAS latencies -/// @param[in] i_tAA CAS latency time -/// @param[in,out] io_tCK cycle time that corresponds to cas latency -/// @param[in,out] io_desired_cas_lat cas latency supported for all dimms -/// @return fapi2::FAPI2_RC_SUCCESS if we find a valid CL also common among all dimms -/// -fapi2::ReturnCode cas_latency::choose_actual_CL (const std::vector<uint64_t>& i_common_CLs, - const uint64_t i_tAA, - uint64_t& io_tCK, - uint64_t& io_desired_cas_lat) -{ - if( i_common_CLs.empty() ) - { - FAPI_ERR("Common CAS latency vector is empty!"); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - } - - //check if the desired CL is supported in the common CAS latency bin - bool l_is_CL_supported = is_CL_supported_in_common(i_common_CLs, io_desired_cas_lat); - - while( !l_is_CL_supported ) - { - // If CL is not supported... - // Choose a higher tCKproposed value and recalculate CL - // Check recalculated CL is supported in common CL - // Repeat until a solution is found - FAPI_TRY( select_higher_tck(io_tCK), "Failed select_higher_tck()"); - FAPI_DBG("Next higher tCK: %d", io_tCK); - - io_desired_cas_lat = calc_cas_latency(i_tAA, io_tCK); - l_is_CL_supported = is_CL_supported_in_common(i_common_CLs, io_desired_cas_lat); - } - - // If we reach here everything is okay - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Checks that CAS latency (CL) doesn't exceed max CAS latency time (tAAmax) -/// and if it does it tries to find a valid CL that doesn't exceed tAAmax. -/// @param[in] i_common_CLs vector of common CAS latencies -/// @param[in] i_tAA CAS latency time -/// @param[in,out] io_tCK cycle time that corresponds to cas latency -/// @param[in,out] io_desired_cas_lat cas latency supported for all dimms -/// @return fapi2::FAPI2_RC_SUCCESS if CL doesn't exceed tAAmax +/// @param[in] i_tck cycle time +/// @return FAPI2_RC_SUCCESS iff ok /// -fapi2::ReturnCode cas_latency::validate_valid_CL (const std::vector<uint64_t>& i_common_CLs, - const uint64_t i_tAA, - uint64_t& io_tCK, - uint64_t& io_desired_cas_lat) +inline fapi2::ReturnCode cas_latency::is_cl_exceeding_taa_max(const uint64_t i_cas_latency, + const uint64_t i_tck) const { - if( i_common_CLs.empty() ) - { - FAPI_ERR("Common CAS latency vector is empty!"); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - } + // JEDEC SPD spec requirement + const size_t l_taa_max = (iv_is_3ds == loading::NOT_3DS) ? TAA_MAX_DDR4 : TAA_MAX_DDR4_3DS; - // Check that selected CL is less than tAAmax - bool l_is_CL_violating_spec = is_CL_exceeding_tAAmax (io_desired_cas_lat, io_tCK); + FAPI_INF("%s. CL (%d) * tCK (%d) = %d > %d", + mss::c_str(iv_target), + i_cas_latency, + i_tck, + i_cas_latency * i_tck, + l_taa_max); - while(l_is_CL_violating_spec) - { - // If it is not.... - // Decrement CL to next lowest supported CL - // And try again - io_desired_cas_lat = next_lowest_CL(i_common_CLs, io_desired_cas_lat); - FAPI_DBG("Next lowest CAS latency %d", io_desired_cas_lat); - - FAPI_TRY( choose_actual_CL(i_common_CLs, i_tAA, io_tCK, io_desired_cas_lat), - "Failed choose_actual_CL()"); - - l_is_CL_violating_spec = is_CL_exceeding_tAAmax (io_desired_cas_lat, io_tCK); - } - - //If we reach this point that we are not violationg tAAmax spec anymore - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - // Since a fail here could mean a fail due to choose_actual_cl and - // due to violation of taamax specification, this error will help - // distinguish error reason - FAPI_ASSERT(false, - fapi2::MSS_EXCEED_TAA_MAX_NO_CL(). - set_CL(io_desired_cas_lat), - "Exceeded tAAmax"); - - return fapi2::current_err; + return (i_cas_latency * i_tck) > l_taa_max ? fapi2::FAPI2_RC_FALSE : fapi2::FAPI2_RC_SUCCESS; } }// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H index b52c6b16c..d1c11510c 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H @@ -50,23 +50,16 @@ namespace mss { -enum constants : std::uint64_t + +// I choose enumerations over boolean because I feel +// it makes the interface clearer than could be depicted +// by 'true' and 'false' alone. +enum class loading : size_t { - // From JEDEC Standard No. 79-4A - // Speed Bins pg. 164 - /// Time in picoseconds - TAA_MAX_DDR4 = 18000, - - // Low range CAS latency from SPD - LOW_RANGE_MIN_CL_DDR4 = 7, - LOW_RANGE_MAX_CL_DDR4 = 36, - - // High range CAS latency SPD - HIGH_RANGE_MIN_CL_DDR4 = 23, - HIGH_RANGE_MAX_CL_DDR4 = 52, + NOT_3DS, + IS_3DS, }; - /// /// @class decoder /// @brief CAS latency class that encapsulates JEDEC calculation algorithm @@ -89,23 +82,73 @@ class cas_latency /// @brief Class constructor that retrieves required SPD data held by internal state /// @param[in] i_target the controller target /// @param[in] i_caches decoder caches + /// @param[out] o_rc returns FAPI2_RC_SUCCESS if constructor initialzed successfully /// cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs, - const std::map<uint32_t, std::shared_ptr<spd::decoder> >& i_caches); + const std::map<uint32_t, std::shared_ptr<spd::decoder> >& i_caches, + fapi2::ReturnCode& o_rc); + + /// @brief Constructor that allows the user to set desired data in lieu of SPD + /// @param[in] i_target the controller target + /// @param[in] i_taa_min largest tAAmin we want to set in picoseconds + /// @param[in] i_tck_min proposed tCKmin in picoseconds + /// @param[in] i_common_cl_mask common CAS latency mask we want to use (bitmap) + /// @param[in] i_is_3ds loading::IS_3DS if this is for 3DS, + /// loading::NOT_3DS otherwise (default) + /// + cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, + const uint64_t i_taa_min, + const uint64_t i_tck_min, + const uint64_t i_common_cl_mask, + const loading i_is_3ds = loading::NOT_3DS); - // Default destructor + /// + /// @brief Default destructor + /// ~cas_latency() = default; /// /// @brief Calculates CAS latency and checks if it is supported and within JEDEC spec. - /// @param[in] i_target the controller target /// @param[out] o_cas_latency selected CAS latency - /// @param[out] o_tCK cycle time corresponding to seleted CAS latency + /// @param[out] o_tck cycle time corresponding to seleted CAS latency /// @return fapi2::FAPI2_RC_SUCCESS if ok /// - fapi2::ReturnCode find_CL(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs, - uint64_t& o_cas_latency, - uint64_t& o_tCK); + fapi2::ReturnCode find_cl(uint64_t& o_cas_latency, + uint64_t& o_tck); + + private: + + enum + { + // From JEDEC Standard No. 79-4A + // Speed Bins pg. 164 + /// Time in picoseconds + TAA_MAX_DDR4 = 18000, + + // From JEDEC Standard No. 79-4 3DS + // Speed Bins pg. 135 + /// Time in picoseconds + TAA_MAX_DDR4_3DS = 21500, + + // Low range CAS latency from SPD + LOW_RANGE_MIN_CL_DDR4 = 7, + LOW_RANGE_MAX_CL_DDR4 = 36, + + // High range CAS latency SPD + HIGH_RANGE_MIN_CL_DDR4 = 23, + HIGH_RANGE_MAX_CL_DDR4 = 52, + + CAS_LAT_RANGE_BIT = 31, + }; + + ///////////////////////// + // Private variables + ///////////////////////// + fapi2::Target<fapi2::TARGET_TYPE_MCS> iv_target; + uint64_t iv_largest_taamin;// cas latency time + uint64_t iv_proposed_tck;// cycle time + uint64_t iv_common_cl; // common cas latency + loading iv_is_3ds; /// /// @brief Retrieves SDRAM Minimum CAS Latency Time (tAAmin) from SPD @@ -141,99 +184,56 @@ class cas_latency /// /// @brief Gets max CAS latency (CL) for the appropriate High/Low Range - /// @param[in] i_supported_CL + /// @param[in] i_supported_cl /// @return the maximum supported CL /// @note Depends on bit 7 of byte 23 from the DDR4 SPD /// - inline uint64_t get_max_CL(const fapi2::buffer<uint64_t> i_supported_CL) const; + inline uint64_t get_max_cl(const fapi2::buffer<uint64_t> i_supported_cl) const; /// /// @brief Gets min CAS latency (CL) for the appropriate High/Low Range - /// @param[in] i_supported_CL + /// @param[in] i_supported_cl /// @return the minimum supported CL /// @note Depends on bit 7 of byte 23 from the DDR4 SPD /// - inline uint64_t get_min_CL(const fapi2::buffer<uint64_t>& i_supported_CL) const; + inline uint64_t get_min_cl(const fapi2::buffer<uint64_t>& i_supported_cl) const; /// /// @brief Calculates CAS latency time from tCK and tAA - /// @param[in] i_tAA cas latency time - /// @param[in] i_tCK min cycle time - /// @return o_cas_latency calculated CAS latency + /// @param[in] i_taa cas latency time + /// @param[in] i_tck min cycle time + /// @param[out] o_cas_latency calculated CAS latency + /// @return FAPI2_RC_SUCCESS iff okay /// - inline uint64_t calc_cas_latency(const uint64_t i_tAA, const uint64_t i_tCK) const; + inline fapi2::ReturnCode calc_cas_latency(const uint64_t i_taa, + const uint64_t i_tck, + uint64_t& o_cas_latency) const; /// /// @brief Helper function to create a vector of supported CAS latencies from a bitmap - /// @param[in] i_common_CL common CAS latency bitmap + /// @param[in] i_common_cl common CAS latency bitmap /// @return vector of supported CAS latencies /// - std::vector<uint64_t> create_common_cl_vector(const uint64_t i_common_CL) const; + std::vector<uint64_t> integral_bitmap_to_vector(const uint64_t i_bitmap) const; /// /// @brief Determines if a requested CAS latency (CL) is supported in the bin of common CLs - /// @param[in] i_common_CLs vector of common CAS latencies + /// @param[in] i_common_cls vector of common CAS latencies /// @param[in] i_cas_latency CAS latency we are comparing against - /// @return true if CAS latency is supported + /// @return fapi2::FAPI2_RC_SUCCESS if ok /// - inline bool is_CL_supported_in_common(const std::vector<uint64_t>& i_common_CLs, - const uint64_t i_cas_latency) const; + inline fapi2::ReturnCode is_cl_supported_in_common(const std::vector<uint64_t>& i_common_cls, + const uint64_t i_cas_latency) const; /// /// @brief Checks that CAS latency doesn't exceed largest CAS latency time /// @param[in] i_cas_latency cas latency - /// @param[in] i_tCK cycle time - /// @return bool true if CAS latency exceeds the largest CAS latency time - /// false otherwise - /// - inline bool is_CL_exceeding_tAAmax(const uint64_t i_cas_latency, - const uint64_t i_tCK) const; - - /// - /// @brief Helper function to determines next lowest CAS latency (CL) - /// @param[in] i_common_CLs vector of common CAS latencies - /// @param[in] i_desired_cas_latency current CAS latency - /// @return the next lowest CL - /// - inline uint64_t next_lowest_CL(const std::vector<uint64_t>& i_common_CLs, - const uint64_t i_desired_cas_latency); - - /// - /// @brief Checks that CAS latency (CL) is supported among all dimms - /// and if it isn't we try to find a CL that is. - /// @param[in] i_common_CLs vector of common CAS latencies - /// @param[in] i_tAA CAS latency time - /// @param[in,out] io_tCK cycle time that corresponds to cas latency - /// @param[in,out] io_desired_cas_lat cas latency supported for all dimms - /// @return fapi2::FAPI2_RC_SUCCESS if we find a valid CL also common among all dimms - /// - fapi2::ReturnCode choose_actual_CL (const std::vector<uint64_t>& i_common_CLs, - const uint64_t i_tAA, - uint64_t& io_tCK, - uint64_t& io_desired_cas_lat); - /// - /// @brief Checks that CAS latency (CL) doesn't exceed max CAS latency time (tAAmax) - /// and if it does it tries to find a valid CL that doesn't exceed tAAmax. - /// @param[in] i_common_CLs vector of common CAS latencies - /// @param[in] i_tAA CAS latency time - /// @param[in,out] io_tCK cycle time that corresponds to cas latency - /// @param[in,out] io_desired_cas_lat cas latency supported for all dimms - /// @return fapi2::FAPI2_RC_SUCCESS if CL doesn't exceed tAAmax + /// @param[in] i_tck cycle time + /// @return fapi2::FAPI2_RC_SUCCESS if ok /// - fapi2::ReturnCode validate_valid_CL (const std::vector<uint64_t>& i_common_CLs, - const uint64_t i_tAA, - uint64_t& io_tCK, - uint64_t& io_desired_cas_lat); - - private: - - ///////////////////////// - // Private variables - ///////////////////////// - uint64_t iv_largest_taamin;// cas latency time - uint64_t iv_proposed_tck;// cycle time - uint64_t iv_common_CL; // common cas latency + inline fapi2::ReturnCode is_cl_exceeding_taa_max(const uint64_t i_cas_latency, + const uint64_t i_tck) const; };// cas_latency diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cycle_time.H b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cycle_time.H index 2352d14df..39ff8d401 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cycle_time.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cycle_time.H @@ -52,22 +52,6 @@ enum FREQ_MARGIN : std::uint64_t MAX_FREQ_MARGIN = 2799, }; -// Proposed DDR4 Full spec update(79-4A) -// Item No. 1716.78C -// Page 217 -// 10.1 Item No. 1716.78C -// Speed Bin Table Note -static const std::vector<uint64_t> tckmin_avg_ddr4 -{ - - // Timing in picoseconds | Application bin speed - 750, // 2666 MT/s - 833, // 2400 MT/s - 937, // 2133 MT/s - 1071, // 1866 MT/s - /* 1250, // 1600 MT/s - don't think we support this one - AAM */ -}; - /// /// @brief Selects DIMM frequency to run based on supported system frequencies /// @tparam T the fapi2::TargetType for which the DIMM information exists. @@ -127,28 +111,6 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief Determines next highest min cycle time (tCK) -/// @param[in,out] io_tCK_in_ps min cycle time in ps -/// @return fapi2::FAPI2_RC_SUCCESS if ok -/// -inline fapi2::ReturnCode select_higher_tck(uint64_t& io_tCK) -{ - auto iterator = std::upper_bound(tckmin_avg_ddr4.begin(), - tckmin_avg_ddr4.end(), - io_tCK); - - // Did we find a greater than value? - FAPI_ASSERT(iterator != tckmin_avg_ddr4.end(), - fapi2::MSS_REACHED_HIGHEST_TCK(). - set_TCK(io_tCK), - "Reached highest valid tCK"); - -fapi_try_exit: - return fapi2::current_err; -} - - }// mss #endif |