From 1061da0271bf85fe29fedff6f242181b3dc6d5ed Mon Sep 17 00:00:00 2001 From: Andre Marin Date: Thu, 11 Jul 2019 13:01:31 -0400 Subject: Add missing attributes needed to be set for generic mss_kind Setting DRAM_MFG_ID, RCD_MFG_ID, and MODULE_HEIGHT to eff_config and editing SPD timing values to use common API for calculations that come with values from the EEPROM Change-Id: If33f2f2a49a62f114575ef36d6325fc537d1dc27 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/79921 Tested-by: FSP CI Jenkins Tested-by: Jenkins Server Tested-by: Hostboot CI Tested-by: HWSV CI Reviewed-by: Louis Stermole Reviewed-by: STEPHEN GLANCY Reviewed-by: Jennifer A Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/79936 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Daniel M Crowell --- .../memory/lib/data_engine/attr_engine_traits.H | 842 ++++++++------------- .../generic/memory/lib/data_engine/data_engine.H | 153 ++-- .../lib/data_engine/data_engine_traits_def.H | 5 +- .../memory/lib/data_engine/data_engine_utils.H | 178 ++--- .../memory/lib/mss_generic_attribute_getters.H | 6 +- .../memory/lib/spd/common/dimm_module_decoder.H | 11 + .../memory/lib/spd/common/spd_decoder_base.H | 62 +- .../memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H | 28 +- src/import/generic/memory/lib/spd/spd_facade.H | 89 ++- .../generic/memory/lib/spd/spd_fields_ddr4.H | 9 + .../generic/memory/lib/spd/spd_traits_ddr4.H | 38 + src/import/generic/memory/lib/utils/mss_field.H | 7 +- .../memory/lib/utils/shared/mss_generic_consts.H | 28 +- .../generic_memory_eff_attributes.xml | 3 +- 14 files changed, 761 insertions(+), 698 deletions(-) (limited to 'src/import/generic') diff --git a/src/import/generic/memory/lib/data_engine/attr_engine_traits.H b/src/import/generic/memory/lib/data_engine/attr_engine_traits.H index 4a89e13ec..f498dd8a0 100644 --- a/src/import/generic/memory/lib/data_engine/attr_engine_traits.H +++ b/src/import/generic/memory/lib/data_engine/attr_engine_traits.H @@ -37,13 +37,13 @@ #define _MSS_ATTR_ENGINE_TRAITS_H_ #include +#include #include -#include +#include #include #include #include #include -#include #include #include #include @@ -51,6 +51,146 @@ namespace mss { +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TCCD_L +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TCCD_L > +{ + static constexpr const char* TIMING_NAME = "TCCD_L"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_tccd_l; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_tccd_l; +}; + +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TWTR_L +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TWTR_L > +{ + static constexpr const char* TIMING_NAME = "tWTR_L"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_twtr_l; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_twtr_l; +}; + +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TWTR_S +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TWTR_S > +{ + static constexpr const char* TIMING_NAME = "tWTR_S"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_twtr_s; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_twtr_s; +}; + +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TFAW +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TFAW > +{ + static constexpr const char* TIMING_NAME = "tFAW"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_tfaw; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_tfaw; +}; + +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TRCD +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRCD > +{ + static constexpr const char* TIMING_NAME = "trcd"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_trcd; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_trcd; +}; + +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TRP +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRP > +{ + static constexpr const char* TIMING_NAME = "tRP"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_trp; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_trp; +}; + +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TRAS +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRAS > +{ + static constexpr const char* TIMING_NAME = "tRAS"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_tras; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_tras; +}; + +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TWR +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TWR > +{ + static constexpr const char* TIMING_NAME = "tWR"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_twr; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_twr; +}; + +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TRRD_S +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRRD_S > +{ + static constexpr const char* TIMING_NAME = "tRRD_S"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_trrd_s; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_trrd_s; +}; + +/// +/// @brief Forward declartion of traits for setTimingTraits +/// @class setTimingTraits +/// @note attr_eff_engine_fields, DRAM_TRRD_L +/// +template< > +struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRRD_L > +{ + static constexpr const char* TIMING_NAME = "tRRD_L"; + + static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_trrd_l; + static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_trrd_l; +}; + /// /// @brief Traits for attr_engine /// @class attrEngineTraits - partial specialization @@ -2009,7 +2149,7 @@ struct attrEngineTraits +struct attrEngineTraits +{ + using attr_type = fapi2::ATTR_MEM_EFF_DRAM_MFG_ID_Type; + using attr_integral_type = std::remove_all_extents::type; + static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_MFG_ID_TargetType; + static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_MFG_ID; + + /// + /// @brief attribute getter + /// @param[in] i_target the fapi2 target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target& i_target, + attr_type& o_setting) + { + return mss::attr::get_dram_mfg_id(i_target, o_setting); + } + + /// + /// @brief attribute setter + /// @param[in] i_target the attr target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target& i_target, + attr_type& i_setting) + { + return mss::attr::set_dram_mfg_id(i_target, i_setting); + } + + /// + /// @brief Computes setting for attribute + /// @param[in] i_efd_data EFD data + /// @param[out] o_setting value we want to set attr with + /// @return FAPI2_RC_SUCCESS iff okay + /// + static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data, + attr_integral_type& o_setting) + { + fapi2::buffer l_temp; + FAPI_TRY(i_spd_data.dram_manufacturer_id_code(l_temp)); + fapi2::endian_swap(l_temp); + o_setting = l_temp; + + fapi_try_exit: + return fapi2::current_err; + } +}; + /// /// @brief Traits for attrEngineTraits /// @class attrEngineTraits - partial specialization @@ -2275,57 +2471,8 @@ struct attrEngineTraits(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Get the tCCD_L timing values - // tCCD_L is speed bin independent and is - // the same for all bins at a DRAM frequency. - // It is safe to read this from SPD because the correct nck - // value will be calulated based on our dimm speed. - - { - int64_t l_ftb = 0; - int64_t l_mtb = 0; - int64_t l_tccd_mtb = 0; - int64_t l_tccd_ftb = 0; - - FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) ); - FAPI_TRY( i_spd_data.min_tccd_l(l_tccd_mtb), - "%s Failed min_tccd_l()", spd::c_str(l_dimm) ); - FAPI_TRY( i_spd_data.fine_offset_min_tccd_l(l_tccd_ftb), - "%s Failed fine_offset_min_tccd_l()", spd::c_str(l_dimm) ); - - FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tCCD_L (MTB): %ld, tCCD_L(FTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, l_tccd_mtb, l_tccd_ftb ); - - l_tccd_in_ps = spd::calc_timing_from_timebase(l_tccd_mtb, l_mtb, l_tccd_ftb, l_ftb); - } - - { - // Calculate refresh cycle time in nCK & set attribute - uint8_t l_tccd_in_nck = 0; - - // Calculate nck - FAPI_TRY( spd::calc_nck(l_tccd_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_tccd_in_nck), - "%s Error in calculating tccd, with value of l_tccd_in_ps: %d", - spd::c_str(l_dimm), l_tccd_in_ps); - - FAPI_INF("%s tCK (ps): %d, tCCD_L (ps): %d, tCCD_L (nck): %d", - spd::c_str(l_dimm), l_tck_in_ps, l_tccd_in_ps, l_tccd_in_nck); - - o_setting = l_tccd_in_nck; - FAPI_DBG("%s DRAM TCCD_L %d", spd::c_str(l_dimm), o_setting); - } - - fapi_try_exit: - return fapi2::current_err; + return mss::calc_spd_time_in_nck(i_spd_data, o_setting); } }; @@ -2376,48 +2523,8 @@ struct attrEngineTraits(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Calculate twtr_l (in ps) - { - int64_t l_ftb = 0; - int64_t l_mtb = 0; - constexpr int64_t l_twtr_l_ftb = 0; - int64_t l_twtr_l_mtb = 0; - - FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) ); - FAPI_TRY( i_spd_data.min_twtr_l(l_twtr_l_mtb) ); - - FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_L (MTB): %ld, tWTR_L (FTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, l_twtr_l_mtb, l_twtr_l_ftb ); - - l_twtr_l_in_ps = spd::calc_timing_from_timebase(l_twtr_l_mtb, l_mtb, l_twtr_l_ftb, l_ftb); - } - - { - uint8_t l_twtr_l_in_nck = 0; - - // Calculate nck - FAPI_TRY( spd::calc_nck(l_twtr_l_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_l_in_nck), - "%s Error in calculating tWTR_L, with value of l_twtr_in_ps: %d", - spd::c_str(l_dimm), l_twtr_l_in_ps ); - - FAPI_INF( "%s tCK (ps): %d, tWTR_L (ps): %d, tWTR_L (nck): %d", - spd::c_str(l_dimm), l_tck_in_ps, l_twtr_l_in_ps, l_twtr_l_in_nck ); - - o_setting = l_twtr_l_in_nck; - FAPI_DBG("%s DRAM TWTR_L %d", spd::c_str(l_dimm), o_setting); - } - - fapi_try_exit: - return fapi2::current_err; + return mss::calc_spd_time_in_nck(i_spd_data, o_setting); } }; @@ -2468,48 +2575,8 @@ struct attrEngineTraits(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Calculate twtr_s (in ps) - { - int64_t l_ftb = 0; - int64_t l_mtb = 0; - constexpr int64_t l_twtr_s_ftb = 0; - int64_t l_twtr_s_mtb = 0; - - FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) ); - FAPI_TRY( i_spd_data.min_twtr_s(l_twtr_s_mtb) ); - - FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, l_twtr_s_mtb, l_twtr_s_ftb ); - - l_twtr_s_in_ps = spd::calc_timing_from_timebase(l_twtr_s_mtb, l_mtb, l_twtr_s_ftb, l_ftb); - } - - { - int8_t l_twtr_s_in_nck = 0; - - // Calculate nck - FAPI_TRY( spd::calc_nck(l_twtr_s_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_s_in_nck), - "%s Error in calculating tWTR_S, with value of l_twtr_in_ps: %d", - spd::c_str(l_dimm), l_twtr_s_in_ps ); - - FAPI_INF( "%s tCK (ps): %d, tWTR_S (ps): %d, tWTR_S (nck): %d", - spd::c_str(l_dimm), l_tck_in_ps, l_twtr_s_in_ps, l_twtr_s_in_nck ); - - o_setting = l_twtr_s_in_nck; - FAPI_DBG("%s DRAM TWTR_S %d", spd::c_str(l_dimm), o_setting); - } - - fapi_try_exit: - return fapi2::current_err; + return mss::calc_spd_time_in_nck(i_spd_data, o_setting); } }; @@ -2560,74 +2627,8 @@ struct attrEngineTraits(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Calculate tFAW - { - int64_t l_ftb = 0; - int64_t l_mtb = 0; - int64_t l_tfaw_mtb = 0; - - FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) ); - FAPI_TRY( i_spd_data.min_tfaw(l_tfaw_mtb), - "%s Failed min_tfaw()", spd::c_str(l_dimm) ); - - FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tfaw (MTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, l_tfaw_mtb); - - l_tfaw_in_ps = spd::calc_timing_from_timebase(l_tfaw_mtb, l_mtb, l_tfaw_ftb, l_ftb); - - FAPI_ASSERT( l_tfaw_in_ps >= 0, - fapi2::MSS_INVALID_TIMING_VALUE() - .set_VALUE(l_tfaw_in_ps) - .set_DIMM_TARGET(l_dimm) - .set_FUNCTION(TFAW), - "%s Error calculating tFAW (%d). Less than or equal to 0", - spd::c_str(l_dimm), - l_tfaw_in_ps); - - FAPI_DBG("%s TFAW in ps is %d", spd::c_str(l_dimm), l_tfaw_in_ps); - - FAPI_TRY( spd::calc_nck(l_tfaw_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_tfaw_in_nck), - "%s Error in calculating l_tFAW, with value of l_tfaw_in_ps: %d", - spd::c_str(l_dimm), - l_tfaw_in_nck); - } - - FAPI_TRY( attr::get_dram_width(l_dimm, l_dram_width) ); - FAPI_TRY( mss::tfaw(l_dimm, l_dram_width, l_freq, l_jedec_tfaw_in_nck), "Failed tfaw()" ); - - // Taking the worst case between the required minimum JEDEC value and the proposed value from SPD - if (l_jedec_tfaw_in_nck != l_tfaw_in_nck) - { - FAPI_INF("%s TFAW from JEDEC (%d) and from SPD (%d) don't match. Choosing worst case. dram width %d, freq %d", - spd::c_str(l_dimm), - l_jedec_tfaw_in_nck, - l_tfaw_in_nck, - l_dram_width, - l_freq); - - l_tfaw_in_nck = std::max(l_jedec_tfaw_in_nck, l_tfaw_in_nck); - } - - FAPI_INF("%s SDRAM width: %d, tFAW (nck): %d", - spd::c_str(l_dimm), l_dram_width, l_tfaw_in_nck); - o_setting = l_tfaw_in_nck; - FAPI_DBG("%s DRAM TFAW %d", spd::c_str(l_dimm), o_setting); - - fapi_try_exit: - return fapi2::current_err; + return mss::calc_spd_time_in_nck(i_spd_data, o_setting); } }; @@ -2678,56 +2679,8 @@ struct attrEngineTraits(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Calculate tRCD (in ps) - // Get the tRCD timing values - // tRCD is speed bin dependent and has a unique - // value for each speed bin so it is safe to - // read from SPD because the correct nck - // value will be calulated based on our dimm speed. - { - int64_t l_ftb = 0; - int64_t l_mtb = 0; - int64_t l_trcd_mtb = 0; - int64_t l_trcd_ftb = 0; - - FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) ); - FAPI_TRY( i_spd_data.min_trcd(l_trcd_mtb), - "%s Failed min_trcd()", spd::c_str(l_dimm) ); - FAPI_TRY( i_spd_data.fine_offset_min_trcd(l_trcd_ftb), - "%s Failed fine_offset_min_trcd()", spd::c_str(l_dimm) ); - - FAPI_INF("%s medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCD (MTB): %ld, tRCD (FTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, l_trcd_mtb, l_trcd_ftb); - - l_trcd_in_ps = spd::calc_timing_from_timebase(l_trcd_mtb, l_mtb, l_trcd_ftb, l_ftb); - } - - { - uint8_t l_trcd_in_nck = 0; - - // Calculate nck - FAPI_TRY( spd::calc_nck(l_trcd_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trcd_in_nck), - "%s Error in calculating trcd, with value of l_trcd_in_ps: %d", - spd::c_str(l_dimm), l_trcd_in_ps); - - FAPI_INF("%s tCK (ps): %d, tRCD (ps): %d, tRCD (nck): %d", - spd::c_str(l_dimm), l_tck_in_ps, l_trcd_in_ps, l_trcd_in_nck); - - o_setting = l_trcd_in_nck; - FAPI_DBG("%s DRAM TRCD %d", spd::c_str(l_dimm), o_setting); - } - - fapi_try_exit: - return fapi2::current_err; + return mss::calc_spd_time_in_nck(i_spd_data, o_setting); } }; @@ -2778,59 +2731,8 @@ struct attrEngineTraits(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Calculate tRP (in ps) - { - int64_t l_ftb = 0; - int64_t l_mtb = 0; - int64_t l_trp_mtb = 0; - int64_t l_trp_ftb = 0; - - FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) ); - FAPI_TRY( i_spd_data.min_trp(l_trp_mtb), - "%s Failed min_trp()", spd::c_str(l_dimm) ); - - FAPI_TRY( i_spd_data.fine_offset_min_trp(l_trp_ftb), - "%s Failed fine_offset_min_trp()", spd::c_str(l_dimm) ); - - FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tRP (MTB): %ld, tRP(FTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, l_trp_mtb, l_trp_ftb); - - l_trp_in_ps = spd::calc_timing_from_timebase(l_trp_mtb, l_mtb, l_trp_ftb, l_ftb); - } - - // SPD spec gives us the minimum... compute our worstcase (maximum) from JEDEC - { - // Declaring as int64_t to fix std::max compile - const int64_t l_trp = mss::ps_to_cycles(l_tck_in_ps, mss::trtp()); - l_trp_in_ps = std::max(l_trp_in_ps, l_trp); - } - - { - uint8_t l_trp_in_nck = 0; - - // Calculate nck - FAPI_TRY( spd::calc_nck(l_trp_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trp_in_nck), - "%s Error in calculating dram_tRP nck, with value of l_trp_in_ps: %d", - spd::c_str(l_dimm), l_trp_in_ps); - - FAPI_INF( "%s tCK (ps): %d, tRP (ps): %d, tRP (nck): %d", - spd::c_str(l_dimm), l_tck_in_ps, l_trp_in_ps, l_trp_in_nck ); - - o_setting = l_trp_in_nck; - FAPI_DBG("%s DRAM TRP %d", spd::c_str(l_dimm), o_setting); - } - - fapi_try_exit: - return fapi2::current_err; + return mss::calc_spd_time_in_nck(i_spd_data, o_setting); } }; @@ -2881,41 +2783,8 @@ struct attrEngineTraits(l_dimm), l_freq) ); - l_tras_in_ps = mss::tras(l_dimm, l_freq); - - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Cast needed for calculations to be done on the same integral type - // as required by template deduction. We have l_tck_in_ps as a signed - // integer because we have other timing values that calculations do - // addition with negative integers. - FAPI_TRY( spd::calc_nck(l_tras_in_ps, - static_cast(l_tck_in_ps), - spd::INVERSE_DDR4_CORRECTION_FACTOR, - l_tras_in_nck), - "%s Error in calculating tras_l, with value of l_twtr_in_ps: %d", - spd::c_str(l_dimm), l_tras_in_ps); - - FAPI_INF("%s tCK (ps): %d, tRAS (ps): %d, tRAS (nck): %d", - spd::c_str(l_dimm), l_tck_in_ps, l_tras_in_ps, l_tras_in_nck); - - o_setting = l_tras_in_nck; - FAPI_DBG("%s DRAM TRAS %d", spd::c_str(l_dimm), o_setting); - - fapi_try_exit: - return fapi2::current_err; + return mss::calc_spd_time_in_nck(i_spd_data, o_setting); } }; @@ -2966,54 +2835,8 @@ struct attrEngineTraits(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Get the tWR timing values - // tWR is speed bin independent and is - // the same for all bins within a speed grade. - // It is safe to read this from SPD because the correct nck - // value will be calulated based on our dimm speed. - { - constexpr int64_t l_twr_ftb = 0; - int64_t l_twr_mtb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) ); - - FAPI_TRY( i_spd_data.min_twr(l_twr_mtb), - "%s Failed min_twr()", spd::c_str(l_dimm) ); - - FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tWR (MTB): %ld, tWR(FTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, l_twr_mtb, l_twr_ftb); - - // Calculate twr (in ps) - l_twr_in_ps = spd::calc_timing_from_timebase(l_twr_mtb, l_mtb, l_twr_ftb, l_ftb); - } - - { - uint8_t l_twr_in_nck = 0; - - // Calculate tNCK - FAPI_TRY( spd::calc_nck(l_twr_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_twr_in_nck), - "%s Error in calculating l_twr_in_nck, with value of l_twr_in_ps: %d", spd::c_str(l_dimm), l_twr_in_ps); - - FAPI_INF( "%s tCK (ps): %d, tWR (ps): %d, tWR (nck): %d", - spd::c_str(l_dimm), l_tck_in_ps, l_twr_in_ps, l_twr_in_nck ); - - o_setting = l_twr_in_nck; - FAPI_DBG("%s DRAM TWR %d", spd::c_str(l_dimm), o_setting); - } - - fapi_try_exit: - return fapi2::current_err; + return mss::calc_spd_time_in_nck(i_spd_data, o_setting); } }; @@ -3142,69 +2965,16 @@ struct attrEngineTraits(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Calculate tRRD_S - { - int64_t l_trrd_s_mtb = 0; - int64_t l_trrd_s_ftb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) ); - - FAPI_TRY( i_spd_data.min_trrd_s(l_trrd_s_mtb), - "%s Failed min_trrd_s()", spd::c_str(l_dimm) ); - - FAPI_TRY( i_spd_data.fine_offset_min_trrd_s(l_trrd_s_ftb), - "%s Failed fine_offset_min_trrd_s()", spd::c_str(l_dimm) ); - - FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, trrd_s (MTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, l_trrd_s_mtb); - - l_trrd_s_in_ps = spd::calc_timing_from_timebase(l_trrd_s_mtb, l_mtb, l_trrd_s_ftb, l_ftb); - - FAPI_ASSERT( l_trrd_s_in_ps >= 0, - fapi2::MSS_INVALID_TIMING_VALUE() - .set_VALUE(l_trrd_s_in_ps) - .set_DIMM_TARGET(l_dimm) - .set_FUNCTION(TRRD_S), - "%s Error calculating tRRD_S (%d). Less than or equal to 0", - spd::c_str(l_dimm), - l_trrd_s_in_ps); - - FAPI_DBG("%s TRRD_S in ps is %d", spd::c_str(l_dimm), l_trrd_s_in_ps); - - FAPI_TRY( spd::calc_nck(l_trrd_s_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_s_in_nck), - "%s Error in calculating l_tRRD_S, with value of l_trrd_s_in_ps: %d", - spd::c_str(l_dimm), - l_trrd_s_in_nck); - } - FAPI_TRY( attr::get_dram_width(l_dimm, l_dram_width) ); - FAPI_TRY( trrd_s( l_dimm, l_dram_width, l_freq, l_jedec_trrd) ); - - // Taking the worst case between the required minimum JEDEC value and the proposed value from SPD - if (l_jedec_trrd != l_trrd_s_in_nck) - { - FAPI_INF("%s TRRD_S from JEDEC (%d) and from SPD (%d) don't match. Choosing worst case. dram width %d, freq %d", - spd::c_str(l_dimm), - l_jedec_trrd, - l_trrd_s_in_nck, - l_dram_width, - l_freq); - - l_trrd_s_in_nck = std::max( l_jedec_trrd, l_trrd_s_in_nck); - } + FAPI_TRY( attr::get_freq(mss::find_target(l_dimm), l_freq) ); + FAPI_TRY( trrd_s( l_dimm, l_dram_width, l_freq, l_trrd_s_in_nck) ); FAPI_INF("%s SDRAM width: %d, tRRD_S (nck): %d", spd::c_str(l_dimm), l_dram_width, l_trrd_s_in_nck); @@ -3265,69 +3035,17 @@ struct attrEngineTraits(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) ); - - // Calculate tRRD_L - { - int64_t l_trrd_l_mtb = 0; - int64_t l_trrd_l_ftb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) ); - - FAPI_TRY( i_spd_data.min_trrd_l(l_trrd_l_mtb), - "%s Failed min_trrd_l()", spd::c_str(l_dimm) ); - - FAPI_TRY( i_spd_data.fine_offset_min_trrd_l(l_trrd_l_ftb), - "%s Failed fine_offset_min_trrd_l()", spd::c_str(l_dimm) ); - - FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, trrd_l (MTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, l_trrd_l_mtb); - - l_trrd_l_in_ps = spd::calc_timing_from_timebase(l_trrd_l_mtb, l_mtb, l_trrd_l_ftb, l_ftb); - - FAPI_ASSERT( l_trrd_l_in_ps >= 0, - fapi2::MSS_INVALID_TIMING_VALUE() - .set_VALUE(l_trrd_l_in_ps) - .set_DIMM_TARGET(l_dimm) - .set_FUNCTION(TRRD_L), - "%s Error calculating tRRD_L (%d). Less than or equal to 0", - spd::c_str(l_dimm), - l_trrd_l_in_ps); - - FAPI_DBG("%s TRRD_L in ps is %d", spd::c_str(l_dimm), l_trrd_l_in_ps); - - FAPI_TRY( spd::calc_nck(l_trrd_l_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_l_in_nck), - "%s Error in calculating l_tRRD_L, with value of l_trrd_l_in_ps: %d", - spd::c_str(l_dimm), - l_trrd_l_in_nck); - } - FAPI_TRY( attr::get_dram_width(l_dimm, l_dram_width) ); - FAPI_TRY( trrd_l( l_dimm, l_dram_width, l_freq, l_jedec_trrd) ); - - // Taking the worst case between the required minimum JEDEC value and the proposed value from SPD - if (l_jedec_trrd != l_trrd_l_in_nck) - { - FAPI_INF("%s TRRD_L from JEDEC (%d) and from SPD (%d) don't match. Choosing worst case. dram width %d, freq %d", - spd::c_str(l_dimm), - l_jedec_trrd, - l_trrd_l_in_nck, - l_dram_width, - l_freq); - - l_trrd_l_in_nck = std::max( l_jedec_trrd, l_trrd_l_in_nck); - } + FAPI_TRY( trrd_l( l_dimm, l_dram_width, l_freq, l_trrd_l_in_nck) ); FAPI_INF("%s SDRAM width: %d, tRRD_L (nck): %d", spd::c_str(l_dimm), l_dram_width, l_trrd_l_in_nck); @@ -3549,6 +3267,106 @@ struct attrEngineTraits +struct attrEngineTraits +{ + using attr_type = fapi2::ATTR_MEM_EFF_RCD_MFG_ID_Type; + using attr_integral_type = std::remove_all_extents::type; + static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_RCD_MFG_ID_TargetType; + static constexpr generic_ffdc_codes FFDC_CODE = SET_RCD_MFG_ID; + + /// + /// @brief attribute getter + /// @param[in] i_target the fapi2 target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target& i_target, + attr_type& o_setting) + { + return mss::attr::get_rcd_mfg_id(i_target, o_setting); + } + + /// + /// @brief attribute setter + /// @param[in] i_target the attr target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target& i_target, + attr_type& i_setting) + { + return mss::attr::set_rcd_mfg_id(i_target, i_setting); + } + + /// + /// @brief Computes setting for attribute + /// @param[in] i_efd_data EFD data + /// @param[out] o_setting value we want to set attr with + /// @return FAPI2_RC_SUCCESS iff okay + /// + static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data, + attr_integral_type& o_setting) + { + return i_spd_data.reg_manufacturer_id_code(o_setting); + } +}; + +/// +/// @brief Traits for attr_engine +/// @class attrEngineTraits +/// @note attr_engine_derived_fields, DRAM_MODULE_HEIGHT specialization +/// +template < proc_type P > +struct attrEngineTraits +{ + using attr_type = fapi2::ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_Type; + using attr_integral_type = std::remove_all_extents::type; + static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_TargetType; + static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_MODULE_HEIGHT; + + /// + /// @brief attribute getter + /// @param[in] i_target the fapi2 target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target& i_target, + attr_type& o_setting) + { + return mss::attr::get_dram_module_height(i_target, o_setting); + } + + /// + /// @brief attribute setter + /// @param[in] i_target the attr target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target& i_target, + attr_type& i_setting) + { + return mss::attr::set_dram_module_height(i_target, i_setting); + } + + /// + /// @brief Computes setting for attribute + /// @param[in] i_efd_data EFD data + /// @param[out] o_setting value we want to set attr with + /// @return FAPI2_RC_SUCCESS iff okay + /// + static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data, + attr_integral_type& o_setting) + { + return i_spd_data.module_base_height(o_setting); + } +}; + }//mss #endif diff --git a/src/import/generic/memory/lib/data_engine/data_engine.H b/src/import/generic/memory/lib/data_engine/data_engine.H index a4dfbf8ae..6e206292b 100644 --- a/src/import/generic/memory/lib/data_engine/data_engine.H +++ b/src/import/generic/memory/lib/data_engine/data_engine.H @@ -38,103 +38,100 @@ #include #include #include -#include #include -#include -#include -#include namespace mss { +namespace gen +{ /// -/// @brief Alias for function pointer to spd_facade timing methods -/// -using spd_facade_fptr = fapi2::ReturnCode (spd::facade::*)(int64_t& o_timing_in_mtb) const; - -/// -/// @brief Algorithm to calculate SPD timings in nCK -/// @tparam ET SPD fields enumeration (e.g. attr_eff_engine_fields) -/// @tparam F SPD field -/// @tparam OT output type -/// @tparam TT defaulted to setTimingTraits -/// @param[in] i_spd the SPD data -/// @param[out] o_timing_in_ps SPD timing value in picoseconds -/// @return FAPI2_RC_SUCCESS iff okay +/// @brief Template recursive algorithm for setting attrs +/// @class attr_engine - partial specialization when F != 0 +/// @tparam P processor type +/// @tparam ET enum type - conceptually a list of attrs to set +/// @tparam F enum value - the specific attr value from ET to set +/// @tparam TT associated traits for attr_engine /// -template < typename ET, - ET F, - typename OT, - typename TT = setTimingTraits > -inline fapi2::ReturnCode calc_spd_time_in_ps(const spd::facade& i_spd, - OT& o_timing_in_ps) +template < proc_type P, typename ET, ET F, typename TT > +struct attr_engine { - const auto l_dimm = i_spd.get_dimm_target(); - int64_t l_timing_mtb = 0; - int64_t l_timing_ftb = 0; - int64_t l_mtb = 0; - int64_t l_ftb = 0; - - FAPI_TRY( spd::get_timebases(i_spd, l_mtb, l_ftb) ); + /// + /// @brief Sets attributes fields F in ET + /// @tparam IT the input type + /// @param[in] i_input input (efd_decoder, spd_facade, fapi2 target) + /// @return FAPI2_RC_SUCCESS iff ok + /// + template < typename IT > + static fapi2::ReturnCode single_set(const IT& i_input) + { + typename TT::attr_integral_type l_value = 0; - FAPI_TRY( (i_spd.*TT::get_timing_in_mtb)(l_timing_mtb), - "Failed to get % (in MTB) for %s", TT::TIMING_NAME, spd::c_str(l_dimm) ); - FAPI_TRY( (i_spd.*TT::get_timing_in_ftb)(l_timing_ftb), - "Failed to get %s (in FTB) for %s", TT::TIMING_NAME, spd::c_str(l_dimm) ); + FAPI_TRY( TT::get_value_to_set(i_input, l_value), + "Failed get_value_to_set() for proc_type: %d and enum val: %d", P, F); - FAPI_DBG("%s medium timebase (ps): %ld, fine timebase (ps): %ld, %s (MTB): %ld, (FTB): %ld", - spd::c_str(l_dimm), l_mtb, l_ftb, TT::TIMING_NAME, l_timing_mtb, l_timing_ftb ); + FAPI_TRY( set_field(i_input, l_value), + "Failed set_field() for proc_type: %d and enum val: %d", P, F); - o_timing_in_ps = spd::calc_timing_from_timebase(l_timing_mtb, l_mtb, l_timing_ftb, l_ftb); + fapi_try_exit: + return fapi2::current_err; + } -fapi_try_exit: - return fapi2::current_err; -} + /// + /// @brief Sets attributes fields F in ET + /// @tparam IT the input type + /// @param[in] i_input input (efd_decoder, spd_facade, fapi2 target) + /// @return FAPI2_RC_SUCCESS iff ok + /// + template < typename IT > + static fapi2::ReturnCode set(const IT& i_input) + { + FAPI_TRY( (attr_engine(F) == 0u>::single_set(i_input)), + "Failed attr_engine::single_set() for proc_type: %d and enum val: %d", P, F); + + // Compiler isn't smart enough to deduce F - 1u (decrementing the enum values by 1) + // Cast needed to help the compiler deduce this value is an ET type + // This does the recursive call to unroll a compile-time looping of a enum list of attrs to set + // The recursion stops at the base case where NEXT_FLD == 0u + { + constexpr ET NEXT_FLD = static_cast( static_cast(F) - 1u ); + using T = mss::attrEngineTraits; + + FAPI_TRY( (attr_engine (NEXT_FLD)>::set(i_input)), + "Failed (attr_engine ::set() for proc_type: %d and enum val: %d", P, F); + } + + fapi_try_exit: + return fapi2::current_err; + } +}; /// -/// @brief Algorithm to calculate SPD timings in nCK -/// @tparam ET SPD fields enumeration (e.g. attr_eff_engine_fields) -/// @tparam F SPD field -/// @tparam OT output type -/// @tparam TT defaulted to setTimingTraits -/// @param[in] i_spd the SPD data -/// @param[out] o_timing_in_ps SPD timing value in number of clocks (nCK) -/// @return FAPI2_RC_SUCCESS iff okay +/// @brief Template recursive algorithm for setting attrs +/// @class attr_engine - partial specialization where F == 0u +/// @tparam P processor type +/// @tparam ET attr fields enum type (conceptually a list of attrs to set) +/// @tparam F enum value - the specific attr value from ET to set +/// @tparam TT associated traits for attr_engine /// -template < typename ET, - ET F, - typename OT, - typename TT = setTimingTraits > -inline fapi2::ReturnCode calc_spd_time_in_nck(const spd::facade& i_spd, - OT& o_timing_in_nck) +template < proc_type P, typename ET, ET F, typename TT > +struct attr_engine< P, ET, F, TT, true > { - const auto l_dimm = i_spd.get_dimm_target(); - - // Calculate the DIMM speed in picoseconds (a.k.a tCK == clock period) - int64_t l_tck_in_ps = 0; - uint64_t l_freq = 0; - FAPI_TRY( attr::get_freq(mss::find_target(l_dimm), l_freq) ); - FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), - "Failed to calculate clock period (tCK) for %s", spd::c_str(l_dimm) ); - + /// + /// @brief Sets attributes fields F in ET + /// @tparam IT the input type + /// @param[in] i_input input (efd_decoder, spd_facade, fapi2 target) + /// @return FAPI2_RC_SUCCESS iff ok + /// + template < typename IT > + static fapi2::ReturnCode set(const IT& i_input) { - // Calculate the desired timing in ps - int64_t l_timing_in_ps = 0; - FAPI_TRY( (calc_spd_time_in_ps(i_spd, l_tck_in_ps)) ); - - // Calculate nck - FAPI_TRY( spd::calc_nck(l_timing_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, o_timing_in_nck), - "Error in calculating %s (nCK) for target %s, with value of %d", - TT::TIMING_NAME, spd::c_str(l_dimm), l_timing_in_ps ); - - FAPI_INF("tCK (ps): %d, %s (ps): %d, %s (nck): %d", - l_tck_in_ps, TT::TIMING_NAME, l_timing_in_ps, TT::TIMING_NAME, o_timing_in_nck); + FAPI_DBG("NO-OP: Reached base case (0) of recursive template for proc_type: %d and enum value: %d", P, F); + return fapi2::FAPI2_RC_SUCCESS; } +}; -fapi_try_exit: - return fapi2::current_err; -} - +}// gen }// mss #endif diff --git a/src/import/generic/memory/lib/data_engine/data_engine_traits_def.H b/src/import/generic/memory/lib/data_engine/data_engine_traits_def.H index 14c6bc518..bdc16dc6a 100644 --- a/src/import/generic/memory/lib/data_engine/data_engine_traits_def.H +++ b/src/import/generic/memory/lib/data_engine/data_engine_traits_def.H @@ -115,9 +115,12 @@ enum class attr_eff_engine_fields PRIM_STACK_TYPE = 20, COLUMN_ADDR_BITS = 21, ROW_ADDR_BITS = 22, + DRAM_MFG_ID = 23, + RCD_MFG_ID = 24, + DRAM_MODULE_HEIGHT = 25, // Dispatcher set to last enum value - DISPATCHER = ROW_ADDR_BITS, + DISPATCHER = DRAM_MODULE_HEIGHT, }; /// diff --git a/src/import/generic/memory/lib/data_engine/data_engine_utils.H b/src/import/generic/memory/lib/data_engine/data_engine_utils.H index d43286d44..85a5ac48b 100644 --- a/src/import/generic/memory/lib/data_engine/data_engine_utils.H +++ b/src/import/generic/memory/lib/data_engine/data_engine_utils.H @@ -37,15 +37,107 @@ #define _MSS_DATA_ENGINE_UTILS_H_ #include +#include #include #include #include #include +#include #include +#include +#include namespace mss { +/// +/// @brief Alias for function pointer to spd_facade timing methods +/// +using spd_facade_fptr = fapi2::ReturnCode (spd::facade::*)(int64_t& o_timing_in_mtb) const; + +/// +/// @brief Algorithm to calculate SPD timings in nCK +/// @tparam ET SPD fields enumeration (e.g. attr_eff_engine_fields) +/// @tparam F SPD field +/// @tparam OT output type +/// @tparam TT defaulted to setTimingTraits +/// @param[in] i_spd the SPD data +/// @param[out] o_timing_in_ps SPD timing value in picoseconds +/// @return FAPI2_RC_SUCCESS iff okay +/// +template < typename ET, + ET F, + typename OT, + typename TT = setTimingTraits > +inline fapi2::ReturnCode calc_spd_time_in_ps(const spd::facade& i_spd, + OT& o_timing_in_ps) +{ + const auto l_dimm = i_spd.get_dimm_target(); + int64_t l_timing_mtb = 0; + int64_t l_timing_ftb = 0; + int64_t l_mtb = 0; + int64_t l_ftb = 0; + + FAPI_TRY( spd::get_timebases(i_spd, l_mtb, l_ftb) ); + + FAPI_TRY( (i_spd.*TT::get_timing_in_mtb)(l_timing_mtb), + "Failed to get % (in MTB) for %s", TT::TIMING_NAME, spd::c_str(l_dimm) ); + FAPI_TRY( (i_spd.*TT::get_timing_in_ftb)(l_timing_ftb), + "Failed to get %s (in FTB) for %s", TT::TIMING_NAME, spd::c_str(l_dimm) ); + + FAPI_DBG("%s medium timebase (ps): %ld, fine timebase (ps): %ld, %s (MTB): %ld, (FTB): %ld", + spd::c_str(l_dimm), l_mtb, l_ftb, TT::TIMING_NAME, l_timing_mtb, l_timing_ftb ); + + o_timing_in_ps = spd::calc_timing_from_timebase(l_timing_mtb, l_mtb, l_timing_ftb, l_ftb); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Algorithm to calculate SPD timings in nCK +/// @tparam ET SPD fields enumeration (e.g. attr_eff_engine_fields) +/// @tparam F SPD field +/// @tparam OT output type +/// @tparam TT defaulted to setTimingTraits +/// @param[in] i_spd the SPD data +/// @param[out] o_timing_in_ps SPD timing value in number of clocks (nCK) +/// @return FAPI2_RC_SUCCESS iff okay +/// +template < typename ET, + ET F, + typename OT, + typename TT = setTimingTraits > +inline fapi2::ReturnCode calc_spd_time_in_nck(const spd::facade& i_spd, + OT& o_timing_in_nck) +{ + const auto l_dimm = i_spd.get_dimm_target(); + + // Calculate the DIMM speed in picoseconds (a.k.a tCK == clock period) + int64_t l_tck_in_ps = 0; + uint64_t l_freq = 0; + FAPI_TRY( attr::get_freq(mss::find_target(l_dimm), l_freq) ); + FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), + "Failed to calculate clock period (tCK) for %s", spd::c_str(l_dimm) ); + + { + // Calculate the desired timing in ps + int64_t l_timing_in_ps = 0; + FAPI_TRY( (calc_spd_time_in_ps(i_spd, l_timing_in_ps)) ); + + // Calculate nck + FAPI_TRY( spd::calc_nck(l_timing_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, o_timing_in_nck), + "Error in calculating %s (nCK) for target %s, with value of %d", + TT::TIMING_NAME, spd::c_str(l_dimm), l_timing_in_ps ); + + FAPI_INF("tCK (ps): %d, %s (ps): %d, %s (nck): %d", + l_tck_in_ps, TT::TIMING_NAME, l_timing_in_ps, TT::TIMING_NAME, o_timing_in_nck); + } + +fapi_try_exit: + return fapi2::current_err; +} + // Controller agnostic functions namespace gen @@ -362,92 +454,6 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief Template recursive algorithm for setting attrs -/// @class attr_engine - partial specialization when F != 0 -/// @tparam P processor type -/// @tparam ET enum type - conceptually a list of attrs to set -/// @tparam F enum value - the specific attr value from ET to set -/// @tparam TT associated traits for attr_engine -/// -template < proc_type P, typename ET, ET F, typename TT > -struct attr_engine -{ - /// - /// @brief Sets attributes fields F in ET - /// @tparam IT the input type - /// @param[in] i_input input (efd_decoder, spd_facade, fapi2 target) - /// @return FAPI2_RC_SUCCESS iff ok - /// - template < typename IT > - static fapi2::ReturnCode single_set(const IT& i_input) - { - typename TT::attr_integral_type l_value = 0; - - FAPI_TRY( TT::get_value_to_set(i_input, l_value), - "Failed get_value_to_set() for proc_type: %d and enum val: %d", P, F); - - FAPI_TRY( set_field(i_input, l_value), - "Failed set_field() for proc_type: %d and enum val: %d", P, F); - - fapi_try_exit: - return fapi2::current_err; - } - - /// - /// @brief Sets attributes fields F in ET - /// @tparam IT the input type - /// @param[in] i_input input (efd_decoder, spd_facade, fapi2 target) - /// @return FAPI2_RC_SUCCESS iff ok - /// - template < typename IT > - static fapi2::ReturnCode set(const IT& i_input) - { - FAPI_TRY( (attr_engine(F) == 0u>::single_set(i_input)), - "Failed attr_engine::single_set() for proc_type: %d and enum val: %d", P, F); - - // Compiler isn't smart enough to deduce F - 1u (decrementing the enum values by 1) - // Cast needed to help the compiler deduce this value is an ET type - // This does the recursive call to unroll a compile-time looping of a enum list of attrs to set - // The recursion stops at the base case where NEXT_FLD == 0u - { - constexpr ET NEXT_FLD = static_cast( static_cast(F) - 1u ); - using T = mss::attrEngineTraits; - - FAPI_TRY( (attr_engine (NEXT_FLD)>::set(i_input)), - "Failed (attr_engine ::set() for proc_type: %d and enum val: %d", P, F); - } - - fapi_try_exit: - return fapi2::current_err; - } -}; - -/// -/// @brief Template recursive algorithm for setting attrs -/// @class attr_engine - partial specialization where F == 0u -/// @tparam P processor type -/// @tparam ET attr fields enum type (conceptually a list of attrs to set) -/// @tparam F enum value - the specific attr value from ET to set -/// @tparam TT associated traits for attr_engine -/// -template < proc_type P, typename ET, ET F, typename TT > -struct attr_engine< P, ET, F, TT, true > -{ - /// - /// @brief Sets attributes fields F in ET - /// @tparam IT the input type - /// @param[in] i_input input (efd_decoder, spd_facade, fapi2 target) - /// @return FAPI2_RC_SUCCESS iff ok - /// - template < typename IT > - static fapi2::ReturnCode set(const IT& i_input) - { - FAPI_DBG("NO-OP: Reached base case (0) of recursive template for proc_type: %d and enum value: %d", P, F); - return fapi2::FAPI2_RC_SUCCESS; - } -}; - /// /// @brief Return a DIMM's position from a fapi2 target /// @tparam TT Traits associated with DIMM position (e.g. dimmPosTraits) diff --git a/src/import/generic/memory/lib/mss_generic_attribute_getters.H b/src/import/generic/memory/lib/mss_generic_attribute_getters.H index 6051f7d39..aeb26ef75 100644 --- a/src/import/generic/memory/lib/mss_generic_attribute_getters.H +++ b/src/import/generic/memory/lib/mss_generic_attribute_getters.H @@ -2235,7 +2235,8 @@ fapi_try_exit: /// @param[out] uint16_t& reference to store the value /// @note Generated by gen_accessors.pl generate_mc_port_params /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK -/// @note ARRAY[DIMM] DRAM Manufacturer ID Code Decodes SPD Byte 350 and 351 +/// @note ARRAY[DIMM] DRAM Manufacturer ID Code Decodes SPD Byte 350 and 351 for ISDIMMs Decodes +/// SPD Byte 552 and 553 for DDIMMs /// inline fapi2::ReturnCode get_dram_mfg_id(const fapi2::Target& i_target, uint16_t& o_value) { @@ -2258,7 +2259,8 @@ fapi_try_exit: /// @param[out] uint16_t&[] array reference to store the value /// @note Generated by gen_accessors.pl generate_mc_port_params /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK -/// @note ARRAY[DIMM] DRAM Manufacturer ID Code Decodes SPD Byte 350 and 351 +/// @note ARRAY[DIMM] DRAM Manufacturer ID Code Decodes SPD Byte 350 and 351 for ISDIMMs Decodes +/// SPD Byte 552 and 553 for DDIMMs /// inline fapi2::ReturnCode get_dram_mfg_id(const fapi2::Target& i_target, uint16_t (&o_array)[2]) diff --git a/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H b/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H index 8ff2e30fa..c8ab503ec 100644 --- a/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H +++ b/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H @@ -1490,6 +1490,17 @@ class dimm_module_decoder o_output = 0; return fapi2::FAPI2_RC_SUCCESS; } + + /// + /// @brief Decodes DRAM Manufacturer ID code + /// @param[out] o_value dram manufacturing id code + /// @return FAPI2_RC_SUCCESS iff okay + /// + virtual fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_value ) const + { + o_value = 0; + return fapi2::FAPI2_RC_SUCCESS; + } }; }// spd diff --git a/src/import/generic/memory/lib/spd/common/spd_decoder_base.H b/src/import/generic/memory/lib/spd/common/spd_decoder_base.H index 878d2f27e..d69d216b5 100644 --- a/src/import/generic/memory/lib/spd/common/spd_decoder_base.H +++ b/src/import/generic/memory/lib/spd/common/spd_decoder_base.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017,2018 */ +/* Contributors Listed Below - COPYRIGHT 2017,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -787,6 +787,66 @@ class base_cnfg_decoder return fapi2::FAPI2_RC_SUCCESS; } + /// + /// @brief Decodes Fine Offset for tWTR_L + /// @param[out] o_value tWTR_L offset in FTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// @warning not an actual SPD field, defaulted to zero to simplify calculations + /// + virtual fapi2::ReturnCode fine_offset_min_twtr_l( int64_t& o_value ) const + { + o_value = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes Fine Offset for twtr_s + /// @param[out] o_value twtr_s offset in FTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// @warning not an actual SPD field, defaulted to zero to simplify calculations + /// + virtual fapi2::ReturnCode fine_offset_min_twtr_s( int64_t& o_value ) const + { + o_value = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes Fine Offset for tfaw + /// @param[out] o_value tfaw offset in FTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// @warning not an actual SPD field, defaulted to zero to simplify calculations + /// + virtual fapi2::ReturnCode fine_offset_min_tfaw( int64_t& o_value ) const + { + o_value = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes Fine Offset for tras + /// @param[out] o_value tras offset in FTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// @warning not an actual SPD field, defaulted to zero to simplify calculations + /// + virtual fapi2::ReturnCode fine_offset_min_tras( int64_t& o_value ) const + { + o_value = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes Fine Offset for twr + /// @param[out] o_value twr offset in FTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// @warning not an actual SPD field, defaulted to zero to simplify calculations + /// + virtual fapi2::ReturnCode fine_offset_min_twr( int64_t& o_value ) const + { + o_value = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + /// /// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section /// @param[out] o_value crc value from SPD diff --git a/src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H b/src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H index 00f893a39..7c1b4f5c9 100644 --- a/src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H +++ b/src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H @@ -54,7 +54,7 @@ namespace spd /// @brief DDIMM module SPD DRAM decoder /// template < rev R > -class decoder : public dimm_module_decoder +class decoder< DDR4, DDIMM_MODULE, R > : public dimm_module_decoder { private: @@ -1399,6 +1399,32 @@ class decoder : public dimm_module_decoder return fapi2::current_err; } + /// + /// @brief Decodes DRAM manufacturing ID Code + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dram_manufacturer_id_code(uint16_t& o_output) const override + { + uint8_t l_byte0 = 0; + uint8_t l_byte1 = 0; + + FAPI_TRY( (mss::spd::reader(iv_target, iv_data, l_byte0)) ); + FAPI_TRY( (mss::spd::reader(iv_target, iv_data, l_byte1)) ); + + { + fapi2::buffer l_buffer; + right_aligned_insert(l_buffer, l_byte1, l_byte0); + o_output = l_buffer; + FAPI_INF("%s. Register Manufacturer ID Code: 0x%04x", + spd::c_str(iv_target), + o_output); + } + + fapi_try_exit: + return fapi2::current_err; + } + };// decoder }// spd diff --git a/src/import/generic/memory/lib/spd/spd_facade.H b/src/import/generic/memory/lib/spd/spd_facade.H index 81689604f..009059c09 100644 --- a/src/import/generic/memory/lib/spd/spd_facade.H +++ b/src/import/generic/memory/lib/spd/spd_facade.H @@ -48,6 +48,8 @@ inline fapi2::ReturnCode get_raw_data(const fapi2::Target iv_data; std::shared_ptr iv_dimm_module_decoder; std::shared_ptr iv_base_cnfg_decoder; + uint8_t iv_dimm_type; public: @@ -95,6 +98,11 @@ class facade final FAPI_TRY(l_factories.create_decoder(iv_dimm_module_decoder)); FAPI_TRY(l_factories.create_decoder(iv_base_cnfg_decoder)); + // Variable to deal with dimm modules (e.g. DDIMM) that has + // fields that are not disjoint between the + // general and dimm module section of the SPD (i.e. a hack variable) + FAPI_TRY( iv_base_cnfg_decoder->base_module(iv_dimm_type) ); + o_rc = fapi2::FAPI2_RC_SUCCESS; return; @@ -853,6 +861,75 @@ class facade final return fapi2::current_err; } + /// + /// @brief Decodes Fine Offset for Minimum Write to Read Time - Same Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// @warning not an actual SPD field, defaulted to zero to simplify calculations + /// + fapi2::ReturnCode fine_offset_min_twtr_l( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_twtr_l(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for Minimum Write to Read Time - Different Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// @warning not an actual SPD field, defaulted to zero to simplify calculations + /// + fapi2::ReturnCode fine_offset_min_twtr_s( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_twtr_s(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for SDRAM Minimum Four Activate Window Delay Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// @warning not an actual SPD field, defaulted to zero to simplify calculations + /// + fapi2::ReturnCode fine_offset_min_tfaw( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_tfaw(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for SDRAM Minimum Active to Precharge Delay Time in MTB + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// @warning not an actual SPD field, defaulted to zero to simplify calculations + /// + fapi2::ReturnCode fine_offset_min_tras( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_tras(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for Minimum Write Recovery Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_min_twr( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_twr(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + /// /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group /// @param[out] o_value SPD encoded value @@ -1041,7 +1118,17 @@ class facade final /// fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_value ) const { - FAPI_TRY( iv_base_cnfg_decoder->dram_manufacturer_id_code(o_value) ); + // Some module fields are duplicated in the general section and + // dimm module sections of the SPD. For DDIMMs, we want get it + // from the dimm module section instead of the general section. + if( iv_dimm_type == spd::DDIMM ) + { + FAPI_TRY( iv_dimm_module_decoder->dram_manufacturer_id_code(o_value) ); + } + else + { + FAPI_TRY( iv_base_cnfg_decoder->dram_manufacturer_id_code(o_value) ); + } fapi_try_exit: return fapi2::current_err; diff --git a/src/import/generic/memory/lib/spd/spd_fields_ddr4.H b/src/import/generic/memory/lib/spd/spd_fields_ddr4.H index 6739276cb..194eba510 100644 --- a/src/import/generic/memory/lib/spd/spd_fields_ddr4.H +++ b/src/import/generic/memory/lib/spd/spd_fields_ddr4.H @@ -1176,6 +1176,12 @@ class fields PMIC1_PHASE_COMBIN_BYTE = 259, PMIC1_PHASE_COMBIN_START = 4, PMIC1_PHASE_COMBIN_LEN = 4, + + // Byte 552-553 + DRAM_MFR_ID_CODE_LSB_BYTE = 552, + DRAM_MFR_ID_CODE_MSB_BYTE = 553, + DRAM_MFR_ID_CODE_START = 0, + DRAM_MFR_ID_CODE_LEN = 8, }; public: @@ -1408,6 +1414,9 @@ class fields // Byte 259: PMIC1 Phase Combination static constexpr field_t PMIC1_PHASE_COMBIN{PMIC1_PHASE_COMBIN_BYTE, PMIC1_PHASE_COMBIN_START, PMIC1_PHASE_COMBIN_LEN}; + // Byte 552 and 553: DRAM manufacturing ID for DDIMMs + static constexpr field_t DRAM_MFR_ID_CODE_LSB{DRAM_MFR_ID_CODE_LSB_BYTE, DRAM_MFR_ID_CODE_START, DRAM_MFR_ID_CODE_LEN}; + static constexpr field_t DRAM_MFR_ID_CODE_MSB{DRAM_MFR_ID_CODE_MSB_BYTE, DRAM_MFR_ID_CODE_START, DRAM_MFR_ID_CODE_LEN}; }; }// spd diff --git a/src/import/generic/memory/lib/spd/spd_traits_ddr4.H b/src/import/generic/memory/lib/spd/spd_traits_ddr4.H index ecdaec291..eb0fde595 100644 --- a/src/import/generic/memory/lib/spd/spd_traits_ddr4.H +++ b/src/import/generic/memory/lib/spd/spd_traits_ddr4.H @@ -5551,6 +5551,44 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_PHASE_COMBIN, R > using COMPARISON_OP = std::less_equal; }; +/// +/// @class readerTraits +/// @brief trait structure to hold static SPD information +/// @tparam R the revision of the SPD field +/// @note DRAM_MFR_ID_CODE_LSB field specialization +/// @note valid for all revisions +/// +template< rev R > +class readerTraits < fields::DRAM_MFR_ID_CODE_LSB, R > +{ + public: + + static constexpr size_t COMPARISON_VAL = 0x00; + static constexpr const char* FIELD_STR = "DRAM manufacturer ID code, LSB"; + + template + using COMPARISON_OP = std::greater_equal; +}; + +/// +/// @class readerTraits +/// @brief trait structure to hold static SPD information +/// @tparam R the revision of the SPD field +/// @note DRAM_MFR_ID_CODE_MSB field specialization +/// @note valid for all revisions +/// +template< rev R > +class readerTraits < fields::DRAM_MFR_ID_CODE_MSB, R > +{ + public: + + static constexpr size_t COMPARISON_VAL = 0x00; + static constexpr const char* FIELD_STR = "DRAM manufacturer ID code, MSB"; + + template + using COMPARISON_OP = std::greater_equal; +}; + }// spd }// mss diff --git a/src/import/generic/memory/lib/utils/mss_field.H b/src/import/generic/memory/lib/utils/mss_field.H index d6bdeaaed..c69bde04f 100644 --- a/src/import/generic/memory/lib/utils/mss_field.H +++ b/src/import/generic/memory/lib/utils/mss_field.H @@ -327,9 +327,10 @@ inline fapi2::ReturnCode get_field( const fapi2::Target& i_target, typename TT::template COMPARISON_OP() ), F.get_byte(i_data), l_temp, - i_ffdc_codes), - "Failed fail_for_invalid_value() for " TARGIDFORMAT, TARGTID ); - + i_ffdc_codes, + TT::FIELD_STR), + "%s failed check::invalid_value() for %s", + TT::FIELD_STR, spd::c_str(i_target) ); // Output should only change if data check passes o_value = static_cast(l_temp); diff --git a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H index 72970ae63..1d95e82d5 100644 --- a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H +++ b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H @@ -217,6 +217,12 @@ enum generic_ffdc_codes SET_PRIM_BUS_WIDTH = 0x1069, SET_PRIM_DIE_COUNT = 0x1070, SET_DRAM_DENSITY = 0x1071, + + // Power thermal functions + POWER_LIMIT = 0x1072, + SLOPE = 0x1073, + INTERCEPT = 0x1074, + SET_SI_RD_VREF_DQ = 0x1075, SET_CAC_DELAY_A = 0x1076, SET_CAC_DELAY_B = 0x1077, @@ -240,24 +246,22 @@ enum generic_ffdc_codes SET_DRAM_TRRD_L = 0x1091, SET_DRAM_TRFC = 0x1092, SET_DRAM_TRFC_DLR = 0x1093, - - - // Power thermal functions - POWER_LIMIT = 0x1072, - SLOPE = 0x1073, - INTERCEPT = 0x1074, + SET_DRAM_MFG_ID = 0x1094, // Used in fw_mark_store.H for MSS_INVALID_RANK_PASSED - FWMS_READ = 30, - FWMS_WRITE = 31, + FWMS_READ = 0x1095, + FWMS_WRITE = 0x1096, // Used in hw_mark_store.H for MSS_INVALID_RANK_PASSED - HWMS_READ = 40, - HWMS_WRITE = 41, + HWMS_READ = 0x1097, + HWMS_WRITE = 0x1098, // MSS_INVALID_INDEX_PASSED - SYMBOL_COUNT_READ = 50, - SYMBOL_COUNT_WRITE = 51, + SYMBOL_COUNT_READ = 0x1099, + SYMBOL_COUNT_WRITE = 0x109A, + + SET_RCD_MFG_ID = 0x109B, + SET_DRAM_MODULE_HEIGHT = 0x109C, }; /// diff --git a/src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml b/src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml index 3167e018a..850f449d7 100644 --- a/src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml +++ b/src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml @@ -625,7 +625,8 @@ ARRAY[DIMM] DRAM Manufacturer ID Code - Decodes SPD Byte 350 and 351 + Decodes SPD Byte 350 and 351 for ISDIMMs + Decodes SPD Byte 552 and 553 for DDIMMs MICRON = 0x802C, SAMSUNG = 0x80CE, HYNIX = 0x80AD -- cgit v1.2.1