From 984f7f35a02e4894c8cb448223bea8d53b64f459 Mon Sep 17 00:00:00 2001 From: Andre Marin Date: Fri, 5 Aug 2016 11:40:28 -0500 Subject: Add rdimm decoder module, incorporate to base spd decoder Change-Id: I8137521ec1d2de48a389f769adda1068fe163376 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/28198 Tested-by: Jenkins Server Reviewed-by: JACOB L. HARVEY Tested-by: Hostboot CI Reviewed-by: Brian R. Silver Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/28199 Tested-by: FSP CI Jenkins Reviewed-by: William G. Hoffa --- .../hwp/memory/lib/eff_config/eff_config.C | 123 +- .../hwp/memory/lib/eff_config/eff_config.H | 44 +- .../procedures/hwp/memory/lib/freq/cas_latency.C | 7 +- .../procedures/hwp/memory/lib/freq/cas_latency.H | 7 +- .../hwp/memory/lib/spd/common/spd_decoder.C | 2858 ++++++++++++++ .../hwp/memory/lib/spd/common/spd_decoder.H | 1454 +++++++ .../hwp/memory/lib/spd/common/spd_decoder_v1_1.C | 910 +++++ .../hwp/memory/lib/spd/rdimm/rdimm_decoder.H | 796 ++++ .../hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C | 819 ++++ .../hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_1.C | 236 ++ .../p9/procedures/hwp/memory/lib/spd/spd_decoder.C | 4155 -------------------- .../p9/procedures/hwp/memory/lib/spd/spd_decoder.H | 1200 ------ .../p9/procedures/hwp/memory/lib/spd/spd_factory.C | 492 +++ .../p9/procedures/hwp/memory/lib/spd/spd_factory.H | 139 + .../p9/procedures/hwp/memory/lib/utils/checker.H | 2 +- .../p9/procedures/hwp/memory/p9_mss_eff_config.C | 14 +- .../chips/p9/procedures/hwp/memory/p9_mss_freq.C | 14 +- .../chips/p9/procedures/hwp/memory/p9_mss_volt.C | 16 +- .../chips/p9/procedures/hwp/memory/p9_mss_volt.H | 2 - .../hwp/memory/tests/mss_rdimm_decoder_ut.C | 581 +++ 20 files changed, 8344 insertions(+), 5525 deletions(-) create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder_v1_1.C create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder.H create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_1.C delete mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C delete mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.H create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H create mode 100644 src/import/chips/p9/procedures/hwp/memory/tests/mss_rdimm_decoder_ut.C diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C index e87c76b0c..dc0717e52 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C @@ -32,17 +32,18 @@ // *HWP Level: 2 // *HWP Consumed by: FSP:HB +// fapi2 #include #include -#include -#include +// mss lib #include +#include +#include +#include #include -#include #include #include - #include using fapi2::TARGET_TYPE_MCA; @@ -57,114 +58,6 @@ namespace mss // Non-member function implementations ///////////////////////// -// TK - Refactor functions to make them more -// testable with next larger change set of decoder -// and eff_config refactoring. Currently, -// goal of achieving VBU value is achieved. - AAM - -/// -/// @brief Returns Logical ranks in Primary SDRAM type -/// @param[in] i_target dimm target -/// @param[in] i_pDecoder shared pointer to the SPD decoder -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode prim_sdram_logical_ranks(const fapi2::Target& i_target, - const std::shared_ptr& i_pDecoder, - uint8_t& o_logical_ranks) -{ - uint8_t l_signal_loading = 0; - uint8_t l_ranks_per_dimm = 0; - FAPI_TRY( i_pDecoder->prim_sdram_signal_loading(i_target, l_signal_loading) ); - FAPI_TRY( i_pDecoder->num_package_ranks_per_dimm(i_target, l_ranks_per_dimm) ); - - if(l_signal_loading == spd::SINGLE_LOAD_STACK) - { - uint8_t l_die_count = 0; - FAPI_TRY( i_pDecoder->prim_sdram_die_count(i_target, l_die_count) ); - - o_logical_ranks = l_ranks_per_dimm * l_die_count; - } - else - { - // Covers case for MONOLITHIC & MULTI_LOAD_STACK - o_logical_ranks = l_ranks_per_dimm; - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Returns Logical ranks in Secondary SDRAM type -/// @param[in] i_target dimm target -/// @param[in] i_pDecoder shared pointer to the SPD decoder -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode sec_sdram_logical_ranks(const fapi2::Target& i_target, - const std::shared_ptr& i_pDecoder, - uint8_t& o_logical_ranks) -{ - uint8_t l_signal_loading = 0; - uint8_t l_ranks_per_dimm = 0; - - FAPI_TRY( i_pDecoder->sec_sdram_signal_loading(i_target, l_signal_loading) ); - FAPI_TRY( i_pDecoder->num_package_ranks_per_dimm(i_target, l_ranks_per_dimm) ); - - if(l_signal_loading == spd::SINGLE_LOAD_STACK) - { - uint8_t l_die_count = 0; - FAPI_TRY( i_pDecoder->sec_sdram_die_count(i_target, l_die_count) ); - - o_logical_ranks = l_ranks_per_dimm * l_die_count; - } - else - { - // Covers case for MONOLITHIC & MULTI_LOAD_STACK - o_logical_ranks = l_ranks_per_dimm; - } - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Returns Logical ranks per DIMM -/// @param[in] i_target dimm target -/// @param[in] i_pDecoder shared pointer to the SPD decoder -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode logical_ranks_per_dimm(const fapi2::Target& i_target, - const std::shared_ptr& i_pDecoder, - uint8_t& o_logical_rank_per_dimm) -{ - uint8_t l_rank_mix = 0; - - FAPI_TRY( i_pDecoder->rank_mix(i_target, l_rank_mix) ); - - if(l_rank_mix == spd::SYMMETRICAL) - { - FAPI_TRY( prim_sdram_logical_ranks(i_target, i_pDecoder, o_logical_rank_per_dimm) ); - } - else - { - // Rank mix is ASYMMETRICAL - uint8_t l_prim_logical_rank_per_dimm = 0; - uint8_t l_sec_logical_rank_per_dimm = 0; - - FAPI_TRY( prim_sdram_logical_ranks(i_target, i_pDecoder, l_prim_logical_rank_per_dimm) ); - FAPI_TRY( sec_sdram_logical_ranks(i_target, i_pDecoder, l_sec_logical_rank_per_dimm) ); - - o_logical_rank_per_dimm = l_prim_logical_rank_per_dimm + l_sec_logical_rank_per_dimm; - } - -fapi_try_exit: - return fapi2::current_err; -} - /// /// @brief IBT helper - maps from VPD definition of IBT to the RCD control word bit fields /// @param[in] i_ibt the IBT from VPD (e.g., 10, 15, ...) @@ -334,7 +227,7 @@ fapi2::ReturnCode eff_config::ranks_per_dimm(const fapi2::Targetlogical_ranks_per_dimm(i_target, l_ranks_per_dimm) ); l_attrs_ranks_per_dimm[l_port_num][l_dimm_num] = l_ranks_per_dimm; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_RANKS_PER_DIMM, l_mcs, l_attrs_ranks_per_dimm) ); @@ -415,7 +308,7 @@ fapi2::ReturnCode eff_config::dimm_size(const fapi2::Target& i FAPI_TRY( iv_pDecoder->device_width(i_target, l_sdram_width) ); FAPI_TRY( iv_pDecoder->prim_bus_width(i_target, l_bus_width) ); FAPI_TRY( iv_pDecoder->sdram_density(i_target, l_sdram_density) ); - FAPI_TRY( logical_ranks_per_dimm(i_target, iv_pDecoder, l_logical_rank_per_dimm) ); + FAPI_TRY( iv_pDecoder->logical_ranks_per_dimm(i_target, l_logical_rank_per_dimm) ); { // Calculate dimm size @@ -736,7 +629,7 @@ fapi2::ReturnCode eff_config::dram_bank_bits(const fapi2::Targetbanks(i_target, l_bank_bits) ); + FAPI_TRY( iv_pDecoder->bank_bits(i_target, l_bank_bits) ); l_attrs_bank_bits[l_port_num][l_dimm_num] = l_bank_bits; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_BANK_BITS, l_mcs, l_attrs_bank_bits) ); diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H index 46dbbbf5d..a2b1c79d7 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H @@ -35,9 +35,14 @@ #ifndef _MSS_EFF_CONFIG_H_ #define _MSS_EFF_CONFIG_H_ -#include +// std lib #include -#include + +// fapi2 +#include + +// mss lib +#include namespace mss { @@ -752,41 +757,6 @@ class eff_config };// eff_config - - -/// -/// @brief Returns Logical ranks in Primary SDRAM type -/// @param[in] i_target dimm target -/// @param[in] i_pDecoder shared pointer to the SPD decoder -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode prim_sdram_logical_ranks(const fapi2::Target& i_target, - const std::shared_ptr& i_pDecoder, - uint8_t& o_logical_ranks); - -/// -/// @brief Returns Logical ranks in Secondary SDRAM type -/// @param[in] i_target dimm target -/// @param[in] i_pDecoder shared pointer to the SPD decoder -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode sec_sdram_logical_ranks(const fapi2::Target& i_target, - const std::shared_ptr& i_pDecoder, - uint8_t& o_logical_ranks); - -/// -/// @brief Returns Logical ranks per DIMM -/// @param[in] i_target dimm target -/// @param[in] i_pDecoder shared pointer to the SPD decoder -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode logical_ranks_per_dimm(const fapi2::Target& i_target, - const std::shared_ptr& i_pDecoder, - uint8_t& o_logical_rank_per_dimm); - } // mss #endif // _MSS_EFF_CONFIG_H_ 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 0c230bd1b..ce92c500a 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 @@ -33,16 +33,21 @@ // *HWP Level: 2 // *HWP Consumed by: HB:FSP +// std lib #include #include +// fapi2 #include -#include + +// mss lib +#include #include #include #include #include #include +#include using fapi2::TARGET_TYPE_DIMM; using fapi2::TARGET_TYPE_MCS; 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 6b5df447a..b52c6b16c 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 @@ -36,17 +36,20 @@ #ifndef _MSS_CAS_LATENCY_H_ #define _MSS_CAS_LATENCY_H_ +// std lib #include #include #include +// fapi2 #include -#include + +// mss lib +#include namespace mss { - enum constants : std::uint64_t { // From JEDEC Standard No. 79-4A diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C new file mode 100644 index 000000000..0af1e912c --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C @@ -0,0 +1,2858 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file spd_decoder.C +/// @brief SPD decoder definitions +/// +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Brian Silver +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +// std lib +#include +#include + +// fapi2 +#include + +// mss lib +#include +#include +#include +#include +#include + +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_DIMM; + +namespace mss +{ +namespace spd +{ + +///////////////////////// +// Member Method implementation +///////////////////////// + +/// +/// @brief ctor +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data vector +/// @param[in] i_module_decoder shared_ptr to dimm module decoder +/// +decoder::decoder(const fapi2::Target& i_target, + const std::vector& i_spd_data, + const std::shared_ptr& i_module_decoder) + : iv_module_decoder(i_module_decoder), iv_spd_data(i_spd_data), iv_target(i_target) +{} + +/// +/// @brief Decodes number of used SPD bytes +/// @param[in] i_target dimm target +/// @param[out] o_value number of SPD bytes used +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 0 bits(0~3) +/// @note Item JC-45-2220.01x +/// @note Page 14 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::number_of_used_bytes(const fapi2::Target& i_target, + uint16_t& o_value) +{ + // ========================================================= + // Byte 0 maps + // Item JC-45-2220.01x + // Page 14 + // DDR4 SPD Document Release 3 + // Byte 0 (0x000): Number of Bytes Used / Number of Bytes in SPD Device + // ========================================================= + static const std::vector > BYTES_USED_MAP = + { + //{key byte, number of used bytes} + {1, 128}, + {2, 256}, + {3, 384}, + {4, 512} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 0; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, BYTES_USED_START, BYTES_USED_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(BYTES_USED_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check on SPD used bytes") ); + + FAPI_INF("%s. Bytes Used: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes total number of SPD bytes +/// @param[in] i_target dimm target +/// @param[out] o_value number of total SPD bytes +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 0 (bits 4~6) +/// @note Item JC-45-2220.01x +/// @note Page 14 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::number_of_total_bytes(const fapi2::Target& i_target, + uint16_t& o_value) +{ + + // ========================================================= + // Byte 0 maps + // Item JC-45-2220.01x + // Page 14 + // DDR4 SPD Document Release 3 + // Byte 0 (0x000): Number of Bytes Used / Number of Bytes in SPD Device + // ========================================================= + static const std::vector > BYTES_TOTAL_MAP = + { + //{key byte, number of total bytes} + {1, 256}, + {2, 512} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 0; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, BYTES_TOTAL_START, BYTES_TOTAL_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(BYTES_TOTAL_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check on SPD total bytes") ); + + FAPI_INF("%s. Total Bytes: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes hybrid media field from SPD +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing hybrid memory type +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 3 (bits 4~6) +/// @note Item JC-45-2220.01x +/// @note Page 17 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::hybrid_media(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // Decodes SPD Byte 3 (bits 4~6) were reserved + // and coded as zeros. There was no concept of hybrid media so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; + +} + +/// +/// @brief Decodes hybrid field from SPD +/// @param[in] i_target +/// @param[out] o_value enum representing if module is hybrid +/// @return fapi2::ReturnCode +/// @note Decodes SPD Byte 3 (bit 7) +/// @note Item JC-45-2220.01x +/// @note Page 17 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::hybrid(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // Decodes SPD Byte 3 (bit 7) were reserved + // and coded as zeros. There was no concept of hybrid media so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decodes SDRAM density from SPD +/// @param[in] i_target dimm target +/// @param[out] o_value SDRAM density in GBs +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 4 (bits 0~3) +/// @note Item JC-45-2220.01x +/// @note Page 18 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::sdram_density(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 4 maps + // Item JC-45-2220.01x + // Page 18 + // DDR4 SPD Document Release 3 + // Byte 4 (0x004): SDRAM Density and Banks + // ========================================================= + static const std::vector< std::pair > SDRAM_DENSITY_MAP = + { + // {key byte, capacity in GBs} + {2, 1}, + {3, 2}, + {4, 4}, + {5, 8}, + {6, 16}, + {7, 32}, + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 4; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check to assure SPD DRAM capacity (map) wont be at invalid values + bool l_is_val_found = mss::find_value_from_key(SDRAM_DENSITY_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for SPD DRAM capacity") ); + + FAPI_INF("%s. SDRAM density: %d Gb", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes number of SDRAM bank_bits from SPD +/// @param[in] i_target dimm target +/// @param[out] o_value Number of SDRAM bank bits +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 4 (bits 5~4) +/// @note Item JC-45-2220.01x +/// @note Page 18 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::bank_bits(const fapi2::Target& i_target, + uint8_t& o_value) + +{ + // ========================================================= + // Byte 4 maps + // Item JC-45-2220.01x + // Page 18 + // DDR4 SPD Document Release 3 + // Byte 4 (0x004): SDRAM Density and Banks + // ========================================================= + static const std::vector< std::pair > BANK_ADDR_BITS_MAP = + { + // {key byte, number of bank address bits} + {0, 2}, + {1, 3} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 4; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, SDRAM_BANKS_START, SDRAM_BANKS_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check to assure SPD DRAM capacity (map) wont be at invalid values + bool l_is_val_found = mss::find_value_from_key(BANK_ADDR_BITS_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for SPD DRAM banks") ); + + FAPI_INF("%s. Number of banks address bits: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes number of SDRAM bank group bits from SPD +/// @param[in] i_target dimm target +/// @param[out] o_value Number of SDRAM bank group bits +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 4 (bits 6~7) +/// @note Item JC-45-2220.01x +/// @note Page 18 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::bank_group_bits(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 4 maps + // Item JC-45-2220.01x + // Page 18 + // DDR4 SPD Document Release 3 + // Byte 4 (0x004): SDRAM Density and Banks + // ========================================================= + static const std::vector > BANK_GROUP_BITS_MAP = + { + // {key byte, number of bank groups bits} + {0, 0}, + {1, 1}, + {2, 2} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 4; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, BANK_GROUP_START, BANK_GROUP_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check to assure SPD DRAM capacity (map) wont be at invalid values + bool l_is_val_found = mss::find_value_from_key(BANK_GROUP_BITS_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for SPD DRAM bank groups") ); + + FAPI_INF("%s. Number of bank group bits: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes number of SDRAM column address bits +/// @param[in] i_target dimm target +/// @param[out] o_value number of column address bits +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 5 (bits 2~0) +/// @note Item JC-45-2220.01x +/// @note Page 18 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::column_address_bits(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 5 maps + // Item JC-45-2220.01x + // Page 18 + // DDR4 SPD Document Release 3 + // Byte 5 (0x005): SDRAM Addressing + // ========================================================= + static const std::vector > COLUMN_ADDRESS_BITS_MAP = + { + //{key byte,col address bits} + {0, 9}, + {1, 10}, + {2, 11}, + {3, 12} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 5; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, COL_ADDRESS_START, COL_ADDRESS_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check to assure SPD DRAM capacity (map) wont be at invalid values + bool l_is_val_found = mss::find_value_from_key(COLUMN_ADDRESS_BITS_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for SDRAM Column Address Bits") ); + + FAPI_INF("%s. Number of Column Address Bits: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes number of SDRAM row address bits +/// @param[in] i_target dimm target +/// @param[out] o_value number of row address bits +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 5 (bits 5~3) +/// @note Item JC-45-2220.01x +/// @note Page 18 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::row_address_bits(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 5 maps + // Item JC-45-2220.01x + // Page 18 + // DDR4 SPD Document Release 3 + // Byte 5 (0x005): SDRAM Addressing + // ========================================================= + static const std::vector > ROW_ADDRESS_BITS_MAP = + { + //{key byte,row address bits} + {0, 12}, + {1, 13}, + {2, 14}, + {3, 15}, + {4, 16}, + {5, 17}, + {6, 18} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 5; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, ROW_ADDRESS_START, ROW_ADDRESS_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check to assure SPD DRAM capacity (map) wont be at invalid values + bool l_is_val_found = mss::find_value_from_key(ROW_ADDRESS_BITS_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for SDRAM Row Address Bits") ); + + FAPI_INF("%s. Number of Row Address Bits: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes Primary SDRAM signal loading +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing signal loading type +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 6 (bits 1~0) +/// @note Item JC-45-2220.01x +/// @note Page 19 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::prim_sdram_signal_loading(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 6 maps + // Item JC-45-2220.01x + // Page 19 + // DDR4 SPD Document Release 3 + // Byte 6 (0x006): Primary SDRAM Package Type + // ========================================================= + static const std::vector > PRIM_SIGNAL_LOADING_MAP = + { + // {key byte, signal loading} + {0, fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_SDP}, + {1, fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_DDP_QDP}, + {2, fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 6; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, PRIM_SIGNAL_LOAD_START, PRIM_SIGNAL_LOAD_LEN >(i_target, + iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(PRIM_SIGNAL_LOADING_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Primary SDRAM Signal Loading") ); + + FAPI_INF("%s. Primary SDRAM Signal Loading: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Primary SDRAM die count +/// @param[in] i_target dimm target +/// @param[out] o_value die count +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 6 (bits 6~4) +/// @note Item JC-45-2220.01x +/// @note Page 19 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::prim_sdram_die_count(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 6 maps + // Item JC-45-2220.01x + // Page 19 + // DDR4 SPD Document Release 3 + // Byte 6 (0x006): Primary SDRAM Package Type + // ========================================================= + static const std::vector > PRIM_DIE_COUNT_MAP = + { + // {key byte, number of die} + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 5}, + {5, 6}, + {6, 7}, + {7, 8} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 6; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, PRIM_DIE_COUNT_START, PRIM_DIE_COUNT_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(PRIM_DIE_COUNT_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for SDRAM Row Address Bits") ); + + FAPI_INF("%s. Number of Row Address Bits: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Primary SDRAM package type +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing package type +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 6 (bit 7) +/// @note Item JC-45-2220.01x +/// @note Page 19 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::prim_sdram_package_type(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 6 maps + // Item JC-45-2220.01x + // Page 19 + // DDR4 SPD Document Release 3 + // Byte 6 (0x006): Primary SDRAM Package Type + // ========================================================= + static const std::vector > PRIM_PACKAGE_TYPE_MAP = + { + // {key byte, value} + {0, MONOLITHIC}, + {1, NON_MONOLITHIC} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 6; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, PRIM_PACKAGE_TYPE_START, PRIM_PACKAGE_TYPE_LEN >(i_target, + iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(PRIM_PACKAGE_TYPE_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Primary SDRAM package type") ); + + FAPI_INF("%s. Primary SDRAM package type: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decode SDRAM Maximum activate count +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing max activate count +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 7 (bits 3~0) +/// @note Item JC-45-2220.01x +/// @note Page 20 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::maximum_activate_count(const fapi2::Target& i_target, + uint32_t& o_value) +{ + // ========================================================= + // Byte 7 maps + // Item JC-45-2220.01x + // Page 20 + // DDR4 SPD Document Release 3 + // Byte 7 (0x007): SDRAM Optional Features + // ========================================================= + static const std::vector > MAC_MAP = + { + // {key byte, maximum activate count} + {0, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNTESTED}, + {1, fapi2::ENUM_ATTR_EFF_DRAM_MAC_700K}, + {2, fapi2::ENUM_ATTR_EFF_DRAM_MAC_600K}, + {3, fapi2::ENUM_ATTR_EFF_DRAM_MAC_500K}, + {4, fapi2::ENUM_ATTR_EFF_DRAM_MAC_400K}, + {5, fapi2::ENUM_ATTR_EFF_DRAM_MAC_300K}, + {6, fapi2::ENUM_ATTR_EFF_DRAM_MAC_200K}, + {8, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNLIMITED} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 7; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, MAC_START, MAC_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(MAC_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for SDRAM Maximum Active Count (MAC)") ); + + FAPI_INF("%s. Maximum Active Count (MAC): %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point +/// @param[in] i_target dimm target +/// @param[out] o_value max activate window multiplier +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 7 (bits 3~0) +/// @note Item JC-45-2220.01x +/// @note Page 20 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::maximum_activate_window_multiplier(const fapi2::Target& i_target, + uint32_t& o_value) +{ + // ========================================================= + // Byte 7 maps + // Item JC-45-2220.01x + // Page 20 + // DDR4 SPD Document Release 3 + // Byte 7 (0x007): SDRAM Optional Features + // ========================================================= + // Multiplier with tREFI is not taken into account here + static const std::vector > TMAW_MAP = + { + // {key byte, tMAW multiplier} + {0, 8192}, + {1, 4096}, + {2, 2048} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 7; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, TMAW_START, TMAW_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(TMAW_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Maximum Active Window (tMAW)") ); + + FAPI_INF("%s. Maximum Active Window multiplier: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decode Post package repair (PPR) +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing if (hard) PPR is supported +/// @return fapi2::ReturnCode +/// @note SPD Byte 9 (bits 7~6) +/// @note Item JC-45-2220.01x +/// @note Page 21 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::post_package_repair(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 9 maps + // Item JC-45-2220.01x + // Page 21 + // DDR4 SPD Document Release 3 + // Byte 9 (0x009): Other SDRAM Optional Features + // ========================================================= + static const std::vector > PPR_MAP = + { + // {key byte, value } + {0, fapi2::ENUM_ATTR_EFF_DRAM_PPR_NOT_SUPPORTED}, + {1, fapi2::ENUM_ATTR_EFF_DRAM_PPR_SUPPORTED} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 9; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, PPR_START, PPR_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(PPR_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for PPR") ); + + FAPI_INF("%s. Post Package Repair (PPR): %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Secondary SDRAM signal loading +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing signal loading type +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 10 (bits 1~0) +/// @note Item JC-45-2220.01x +/// @note Page 22 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::sec_sdram_signal_loading(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // SPD Byte 10 (bits 1~0) were reserved + // and coded as zeros. There was no concept of + // secondary SDRAM signal loading so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decode Soft post package repair (soft PPR) +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing if soft PPR is supported +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 9 (bit 5) +/// @note Item JC-45-2220.01x +/// @note Page 21 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::soft_post_package_repair(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // SPD Byte 9 (bit 5) was reserved + // and coded as zeros. There was no concept of soft PPR so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decodes Secondary DRAM Density Ratio +/// @param[in] i_target dimm target +/// @param[out] o_value raw bits from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 10 (bits 3~2) +/// @note Item JC-45-2220.01x +/// @note Page 22 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::sec_dram_density_ratio(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // SPD Byte 10 (bits 3~2) were reserved + // and coded as zeros. There was no concept of + // secondary SDRAM density ratio so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decodes Secondary SDRAM die count +/// @param[in] i_target dimm target +/// @param[out] o_value die count +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 10 (bits 6~4) +/// @note Item JC-45-2220.01x +/// @note Page 22 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::sec_sdram_die_count(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // SPD Byte 10 (bits 6~4) were reserved + // and coded as zeros. There was no concept of + // secondary SDRAM hybrid media so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decodes Secondary SDRAM package type +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing package type +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 10 (bit 7) +/// @note Item JC-45-2220.01x +/// @note Page 22 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::sec_sdram_package_type(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // SPD Byte 10 (bit 7) was reserved + // and coded as zeros. There was no concept of + // secondary SDRAM package type so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decode Module Nominal Voltage, VDD +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing if 1.2V is operable +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 11 (bit 0) +/// @note Item JC-45-2220.01x +/// @note Page 23 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::operable_nominal_voltage(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 11 maps + // Item JC-45-2220.01x + // Page 22-23 + // DDR4 SPD Document Release 3 + // Byte 11 (0x00B): Modle Nominal Voltage + // ========================================================= + static const std::vector > OPERABLE_MAP = + { + // {key byte, value } + {0, NOT_OPERABLE }, + {1, OPERABLE} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 11; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, OPERABLE_START, OPERABLE_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(OPERABLE_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Operable nominal voltage") ); + + FAPI_INF("%s. Operable: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decode Module Nominal Voltage, VDD +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing if 1.2V is endurant +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 11 (bit 1) +/// @note Item JC-45-2220.01x +/// @note Page 23 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::endurant_nominal_voltage(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 11 maps + // Item JC-45-2220.01x + // Page 22-23 + // DDR4 SPD Document Release 3 + // Byte 11 (0x00B): Modle Nominal Voltage + // ========================================================= + static const std::vector > ENDURANT_MAP = + { + // {key byte, value } + {0, NOT_ENDURANT}, + {1, ENDURANT} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 11; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, ENDURANT_START, ENDURANT_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(ENDURANT_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Endurant nominal voltage") ); + + FAPI_INF("%s. Endurant: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes SDRAM device width +/// @param[in] i_target dimm target +/// @param[out] o_value device width in bits +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 12 (bits 2~0) +/// @note Item JC-45-2220.01x +/// @note Page 23 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::device_width(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 12 maps + // Item JC-45-2220.01x + // Page 23 + // DDR4 SPD Document Release 3 + // Byte 12 (0x00C): Module Organization + // ========================================================= + static const std::vector > DEVICE_WIDTH_MAP = + { + // {key byte, device width (bits)} + {0, 4}, + {1, 8}, + {2, 16}, + {3, 32}, + // All others reserved + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 12; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, SDRAM_WIDTH_START, SDRAM_WIDTH_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(DEVICE_WIDTH_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Device Width") ); + + FAPI_INF("%s. Device Width: %d bits", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes number of package ranks per DIMM +/// @param[in] i_target dimm target +/// @param[out] o_value number of package ranks per DIMM +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 12 (bits 5~3) +/// @note Item JC-45-2220.01x +/// @note Page 23 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::num_package_ranks_per_dimm(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 12 maps + // Item JC-45-2220.01x + // Page 23 + // DDR4 SPD Document Release 3 + // Byte 12 (0x00C): Module Organization + // ========================================================= + static const std::vector > NUM_PACKAGE_RANKS_MAP = + { + // {key byte, num of package ranks per DIMM (package ranks)} + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 5}, + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 12; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, PACKAGE_RANKS_START, PACKAGE_RANKS_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(NUM_PACKAGE_RANKS_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Num Package Ranks Per DIMM") ); + + FAPI_INF("%s. Num Package Ranks per DIMM: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Rank Mix +/// @param[in] i_target dimm target +/// @param[out] o_value rank mix value from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 12 (bit 6) +/// @note Item JC-45-2220.01x +/// @note Page 23 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::rank_mix(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // Decodes SPD Byte 3 (bits 4~6) were reserved + // and coded as zeros. There was no concept of rank_mix so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; + +} + +/// +/// @brief Decodes primary bus width +/// @param[in] i_target dimm target +/// @param[out] o_value primary bus width in bits +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 13 (bits 2~0) +/// @note Item JC-45-2220.01x +/// @note Page 27 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::prim_bus_width(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 13 maps + // Item JC-45-2220.01x + // Page 27 + // DDR4 SPD Document Release 3 + // Byte 13 (0x00D): Module Memory Bus Width + // ========================================================= + static const std::vector > BUS_WIDTH_MAP = + { + // {key byte, bus width (in bits) + {0, 8}, + {1, 16}, + {2, 32}, + {3, 64} + // All others reserved + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 13; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, BUS_WIDTH_START, BUS_WIDTH_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(BUS_WIDTH_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Primary Bus Width") ); + + FAPI_INF("%s. Primary Bus Width: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes bus width extension +/// @param[in] i_target dimm target +/// @param[out] o_value bus width extension in bits +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 13 (bits 2~0) +/// @note Item JC-45-2220.01x +/// @note Page 28 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::bus_width_extension(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 13 maps + // Item JC-45-2220.01x + // Page 27 + // DDR4 SPD Document Release 3 + // Byte 13 (0x00D): Module Memory Bus Width + // ========================================================= + static const std::vector > BUS_WIDTH_EXT_MAP = + { + {0, 0}, + {1, 8} + // All others reserved + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 13; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, BUS_EXT_WIDTH_START, BUS_EXT_WIDTH_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(BUS_WIDTH_EXT_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Bus Width Extension") ); + + FAPI_INF("%s. Bus Width Extension (bits): %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decode Module Thermal Sensor +/// @param[in] i_target dimm target +/// @param[out] o_value thermal sensor value from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 14 (bit 7) +/// @note Item JC-45-2220.01x +/// @note Page 28 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::thermal_sensor(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 14; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, THERM_SENSOR_START, THERM_SENSOR_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check for valid value + constexpr size_t INVALID_VALUE = 2; // single bit value 0 or 1 + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_field_bits < INVALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed check for Thermal Sensor") ); + + // Update output after check passes + o_value = l_field_bits; + + FAPI_INF("%s. Thermal Sensor: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decode Extended Base Module Type +/// @param[in] i_target dimm target +/// @param[out] o_value raw data from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 15 (bits 3~0) +/// @note Item JC-45-2220.01x +/// @note Page 28 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::extended_base_module_type(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 15; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, EXT_MOD_TYPE_START, EXT_MOD_TYPE_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check for valid value + // Currently reserved to 0b000 + constexpr size_t RESERVED = 0; + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_field_bits == RESERVED, + BYTE_INDEX, + l_field_bits, + "Failed check for Extended Base Module Type") ); + + // Update output for check passes + o_value = l_field_bits; + + FAPI_INF("%s. Extended Base Module Type: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decode Fine Timebase +/// @param[in] i_target dimm target +/// @param[out] o_value fine_timebase from SPD in picoseconds +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 17 (bits 1~0) +/// @note Item JC-45-2220.01x +/// @note Page 29 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_timebase(const fapi2::Target& i_target, + int64_t& o_value) +{ + // ========================================================= + // Byte 17 maps + // Item JC-45-2220.01x + // Page 29 + // DDR4 SPD Document Release 3 + // Byte 17 (0x011): Timebases + // ========================================================= + // Created a maps of a single value in case mapping expands to more values + static const std::vector > FINE_TIMEBASE_MAP = + { + // {key byte, fine timebase (in picoseconds) + {0, 1} + // All others reserved + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 17; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, FINE_TIMEBASE_START, FINE_TIMEBASE_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(FINE_TIMEBASE_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Fine Timebase") ); + + FAPI_INF("%s. Fine Timebase: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decode Medium Timebase +/// @param[in] i_target dimm target +/// @param[out] o_value medium timebase from SPD in picoseconds +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 17 (bits 3~2) +/// @note Item JC-45-2220.01x +/// @note Page 29 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::medium_timebase(const fapi2::Target& i_target, + int64_t& o_value) +{ + // ========================================================= + // Byte 17 maps + // Item JC-45-2220.01x + // Page 29 + // DDR4 SPD Document Release 3 + // Byte 17 (0x011): Timebases + // ========================================================= + // Created a maps of a single value in case mapping expands to more values + static const std::vector > MEDIUM_TIMEBASE_MAP = + { + // {key byte, medium timebase (in picoseconds) + {0, 125} + // All others reserved + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 17; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, MED_TIMEBASE_START, MED_TIMEBASE_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(MEDIUM_TIMEBASE_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Medium Timebase") ); + + FAPI_INF("%s. Medium Timebase: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes SDRAM Minimum Cycle Time in MTB +/// @param[in] i_target dimm target +/// @param[out] o_value tCKmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 18 +/// @note Item JC-45-2220.01x +/// @note Page 31-32 +/// @note DDR4 SPD Document Release 3 +/// @warning If tCKmin cannot be divided evenly by the MTB, +/// this byte must be rounded up to the next larger +/// integer and the Fine Offset for tCKmin (SPD byte 125) +/// used for correction to get the actual value. +/// +fapi2::ReturnCode decoder::min_cycle_time(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Explicit conversion + constexpr size_t BYTE_INDEX = 18; + int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: %d.", + mss::c_str(i_target), + BYTE_INDEX, + l_timing_val); + + // Check if value is valid + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the min cycle time (tckmin) in MTB") ); + + // Update output after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Cycle Time (tCKmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes SDRAM Maximum Cycle Time in MTB +/// @param[in] i_target dimm target +/// @param[out] o_value tCKmax in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 19 +/// @note Item JC-45-2220.01x +/// @note Page 32 +/// @note DDR4 SPD Document Release 3 +/// @warning If tCKmax cannot be divided evenly by the MTB, +/// this byte must be rounded up to the next larger +/// integer and the Fine Offset for tCKmax (SPD byte 124) +/// used for correction to get the actual value. +/// +fapi2::ReturnCode decoder::max_cycle_time(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Explicit conversion + constexpr size_t BYTE_INDEX = 19; + int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: %d.", + mss::c_str(i_target), + BYTE_INDEX, + l_timing_val); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the max cycle time (tckmax) in MTB") ); + + // Update output after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Maximum Cycle Time (tCKmax) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decode CAS Latencies Supported +/// @param[in] i_target dimm target +/// @param[out] o_value bitmap of supported CAS latencies +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Bytes 20-23 +/// @note Item JC-45-2220.01x +/// @note Page 33-34 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::supported_cas_latencies(const fapi2::Target& i_target, + uint64_t& o_value) +{ + // Trace print in the front assists w/ debug + constexpr size_t FIRST_BYTE = 20; + uint8_t first_raw_byte = iv_spd_data[FIRST_BYTE]; + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + c_str(i_target), + FIRST_BYTE, + first_raw_byte); + + constexpr size_t SEC_BYTE = 21; + uint8_t sec_raw_byte = iv_spd_data[SEC_BYTE]; + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + c_str(i_target), + SEC_BYTE, + sec_raw_byte); + + constexpr size_t THIRD_BYTE = 22; + uint8_t third_raw_byte = iv_spd_data[THIRD_BYTE]; + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + c_str(i_target), + THIRD_BYTE, + third_raw_byte); + + constexpr size_t FOURTH_BYTE = 23; + uint8_t fourth_raw_byte = iv_spd_data[FOURTH_BYTE]; + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + c_str(i_target), + FOURTH_BYTE, + fourth_raw_byte); + + // Buffers used for bit manipulation + // Combine Bytes to create bitmap - right aligned + fapi2::buffer l_buffer; + + l_buffer.insertFromRight(first_raw_byte) + .insertFromRight(sec_raw_byte) + .insertFromRight(third_raw_byte) + .insertFromRight(fourth_raw_byte); + + // According to the JEDEC spec: + // Byte 22 (Bits 7~0) and Byte 23 are reserved and thus not supported + constexpr size_t MAX_VALID_VAL = 0x3FFFF; + + // Check for a valid value + uint64_t l_supported_cl = l_buffer; + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_supported_cl <= MAX_VALID_VAL, + FOURTH_BYTE, + fourth_raw_byte, + "Failed check on CAS latencies supported") ); + + // Update output value only if range check passes + o_value = l_supported_cl; + + FAPI_INF("%s. CAS latencies supported (bitmap): 0x%llX", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes SDRAM Minimum CAS Latency Time in MTB +/// @param[in] i_target dimm target +/// @param[out] o_value tAAmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 24 +/// @note Item JC-45-2220.01x +/// @note Page 34 +/// @note DDR4 SPD Document Release 3 +/// @warning If tAAmin cannot be divided evenly by the MTB, +/// this byte must be rounded up to the next larger +/// integer and the Fine Offset for tAAmin (SPD byte 123) +/// used for correction to get the actual value. +/// +fapi2::ReturnCode decoder::min_cas_latency_time(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Explicit conversion + constexpr size_t BYTE_INDEX = 24; + int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + l_timing_val); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum CAS Latency Time (tAAmin) in MTB") ); + + // Only update output if it passes check + o_value = l_timing_val; + + FAPI_INF("%s. Minimum CAS Latency Time (tAAmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB +/// @param[in] i_target dimm target +/// @param[out] o_value tRCDmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 25 +/// @note Item JC-45-2220.01x +/// @note Page 35 +/// @note DDR4 SPD Document Release 3 +/// @warning If tRCDmin cannot be divided evenly by the MTB, +/// this byte must be rounded up to the next larger +/// integer and the Fine Offset for tRCDmin (SPD byte 122) +/// used for correction to get the actual value +/// +fapi2::ReturnCode decoder::min_ras_to_cas_delay_time(const fapi2::Target& i_target, + + int64_t& o_value) +{ + // Explicit conversion + constexpr size_t BYTE_INDEX = 25; + int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + l_timing_val); + + // Find valid value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum RAS to CAS Delay Time (tRCDmin) in MTB") ); + + // Only update output if it passes check + o_value = l_timing_val; + + FAPI_INF("%s. Minimum RAS to CAS Delay Time (tRCDmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB +/// @param[in] i_target dimm target +/// @param[out] o_value tRPmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 26 +/// @note Item JC-45-2220.01x +/// @note Page 36-37 +/// @note DDR4 SPD Document Release 3 +/// @warning If tRPmin cannot be divided evenly by the MTB, +/// this byte must be rounded up to the next larger +/// integer and the Fine Offset for tRPmin (SPD byte 121) +/// used for correction to get the actual value +/// +fapi2::ReturnCode decoder::min_row_precharge_delay_time(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Explicit conversion + constexpr size_t BYTE_INDEX = 26; + int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + l_timing_val); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Row Precharge Delay Time (tRPmin) in MTB") ); + + // Only update output if it passes check + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Row Precharge Delay Time (tRPmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB +/// @param[in] i_target dimm target +/// @param[out] o_value tRASmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 27 (bits 3~0) & Byte 28 (bits 7~0) +/// @note Item JC-45-2220.01x +/// @note Page 38 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::min_active_to_precharge_delay_time(const fapi2::Target& i_target, + int64_t& o_value) +{ + constexpr size_t BYTE_INDEX_MSN = 27; + uint8_t tRASmin_MSN = extract_spd_field< BYTE_INDEX_MSN, TRASMIN_MSN_START, TRASMIN_MSN_LEN >(i_target, iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 28; + uint8_t tRASmin_LSB = extract_spd_field< BYTE_INDEX_LSB, TRASMIN_LSB_START, TRASMIN_LSB_LEN >(i_target, iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSN_START = 52; + constexpr size_t MSN_LEN = 4; + constexpr size_t LSB_START = 56; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + + l_buffer.insertFromRight( tRASmin_MSN ) + .insertFromRight( tRASmin_LSB ); + + // Extract timing value from the buffer into an integral type + int64_t l_timing_val = l_buffer; + + // JEDEC spec limits for this timing value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC + + // best we can do? + // I had to combine parts from two different bytes. + // But byte 28 of the JEDEC spec explains how to piece this together - AAM + constexpr size_t ERROR_BYTE_INDEX = 28; + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + ERROR_BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Active to Precharge Delay Time (tRASmin) in MTB") ); + + // Update output only after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Active to Precharge Delay Time (tRASmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB +/// @param[in] i_target dimm target +/// @param[out] o_value tRCmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 27 (bits 7~4) & SPD Byte 29 (bits 7~0) +/// @note Item JC-45-2220.01x +/// @note Page 38 +/// @note DDR4 SPD Document Release 3 +/// @warning If tRCmin cannot be divided evenly by the MTB, +/// this byte must be rounded up to the next larger +/// integer and the Fine Offset for tRCmin (SPD byte 120) +/// used for correction to get the actual value. +/// +fapi2::ReturnCode decoder::min_active_to_active_refresh_delay_time(const fapi2::Target& i_target, + int64_t& o_value) +{ + constexpr size_t BYTE_INDEX_MSN = 27; + uint8_t tRCmin_MSN = extract_spd_field< BYTE_INDEX_MSN, TRCMIN_MSN_START, TRCMIN_MSN_LEN >(i_target, iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 29; + uint8_t tRCmin_LSB = extract_spd_field< BYTE_INDEX_LSB, TRCMIN_LSB_START, TRCMIN_LSB_LEN >(i_target, iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSN_START = 52; + constexpr size_t MSN_LEN = 4; + constexpr size_t LSB_START = 56; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + + l_buffer.insertFromRight( tRCmin_MSN ) + .insertFromRight( tRCmin_LSB ); + + // Extract timing value from the buffer into an integral type + int64_t l_timing_val = l_buffer; + + // JEDEC spec limits for this timing value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC + + // best we can do? + // I had to combine parts from two different bytes. + // But byte 29 of the JEDEC spec explains how to piece this together - AAM + constexpr size_t ERROR_BYTE_INDEX = 29; + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + ERROR_BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB") ); + + // Update output only after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1 +/// @param[in] i_target dimm target +/// @param[out] o_value tRFC1min in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 30 & Byte 31 +/// @note Item JC-45-2220.01x +/// @note Page 39-40 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_1(const fapi2::Target& i_target, + int64_t& o_value) +{ + constexpr size_t BYTE_INDEX_MSB = 31; + uint8_t tRFC1min_MSB = extract_spd_field< BYTE_INDEX_MSB, TRFC1MIN_MSB_START, TRFC1MIN_MSB_LEN >(i_target, iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 30; + uint8_t tRFC1min_LSB = extract_spd_field< BYTE_INDEX_LSB, TRFC1MIN_LSB_START, TRFC1MIN_LSB_LEN >(i_target, iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSB_START = 48; + constexpr size_t MSB_LEN = 8; + constexpr size_t LSB_START = 56; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + + l_buffer.insertFromRight( tRFC1min_MSB ) + .insertFromRight( tRFC1min_LSB ); + + // Extract timing value from the buffer into an integral type + int64_t l_timing_val = l_buffer; + + // JEDEC spec limits for this timing value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC + + // best we can do? + // I had to combine parts from two different bytes. + // Chose one of them (byte 30) to for error printout of this decode + constexpr size_t ERROR_BYTE_INDEX = 30; + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + ERROR_BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB") ); + + // Update output only after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2 +/// @param[in] i_target dimm target +/// @param[out] o_value tRFC2min in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 32 & Byte 33 +/// @note Item JC-45-2220.01x +/// @note Page 40 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_2(const fapi2::Target& i_target, + int64_t& o_value) +{ + constexpr size_t BYTE_INDEX_MSB = 33; + uint8_t tRFC2min_MSB = extract_spd_field< BYTE_INDEX_MSB, TRFC2MIN_MSB_START, TRFC2MIN_MSB_LEN>(i_target, iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 32; + uint8_t tRFC2min_LSB = extract_spd_field< BYTE_INDEX_LSB, TRFC2MIN_LSB_START, TRFC2MIN_LSB_LEN>(i_target, iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSB_START = 48; + constexpr size_t MSB_LEN = 8; + constexpr size_t LSB_START = 56; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + + l_buffer.insertFromRight( tRFC2min_MSB ) + .insertFromRight( tRFC2min_LSB ); + + // Extract timing value from the buffer into an integral type + int64_t l_timing_val = l_buffer; + + // JEDEC spec limits for this timing value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC + + // best we can do? + // I had to combine parts from two different bytes. + // Chose one of them (byte 33) to for error printout of this decode + constexpr size_t ERROR_BYTE_INDEX = 33; + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + ERROR_BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB") ); + + // Update output only after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4 +/// @param[in] i_target dimm target +/// @param[out] o_value tRFC4min in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 34 & Byte 35 +/// @note Item JC-45-2220.01x +/// @note Page 40 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_4(const fapi2::Target& i_target, + int64_t& o_value) +{ + constexpr size_t BYTE_INDEX_MSB = 35; + uint8_t tRFC4min_MSB = extract_spd_field< BYTE_INDEX_MSB, TRFC4MIN_MSB_START, TRFC4MIN_MSB_LEN>(i_target, iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 34; + uint8_t tRFC4min_LSB = extract_spd_field< BYTE_INDEX_LSB, TRFC4MIN_LSB_START, TRFC4MIN_LSB_LEN>(i_target, iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSB_START = 48; + constexpr size_t MSB_LEN = 8; + constexpr size_t LSB_START = 56; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + + l_buffer.insertFromRight( tRFC4min_MSB ) + .insertFromRight( tRFC4min_LSB ); + + // Extract timing value from the buffer into an integral type + int64_t l_timing_val = l_buffer; + + // JEDEC spec limits for this timing value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC + + // best we can do? + // I had to combine parts from two different bytes. + // Chose one of them (byte 34) for error printout of this decode + constexpr size_t ERROR_BYTE_INDEX = 34; + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + ERROR_BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB") ); + + // Update output only after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes SDRAM Minimum Four Activate Window Delay Time +/// @param[in] i_target dimm target +/// @param[out] o_value tFAWmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 36 (bits 3~0) & Byte 37 (bits 7~0) +/// @note Item JC-45-2220.01x +/// @note Page 42 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::min_tfaw(const fapi2::Target& i_target, + int64_t& o_value) +{ + constexpr size_t BYTE_INDEX_MSN = 36; + uint8_t tFAWmin_MSN = extract_spd_field< BYTE_INDEX_MSN, TFAWMIN_MSN_START, TFAWMIN_MSN_LEN >(i_target, iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 37; + uint8_t tFAWmin_LSB = extract_spd_field< BYTE_INDEX_LSB, TFAWMIN_LSB_START, TFAWMIN_LSB_LEN >(i_target, iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSN_START = 52; + constexpr size_t MSN_LEN = 4; + constexpr size_t LSB_START = 56; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + + l_buffer.insertFromRight( tFAWmin_MSN ). + insertFromRight( tFAWmin_LSB ); + + // Extract timing value from the buffer into an integral type + int64_t l_timing_val = l_buffer; + + // JEDEC spec limits for this timing value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC + + // best we can do? + // I had to combine parts from two different bytes. + // Chose one of them (byte 37) to for error printout of this decode + constexpr size_t ERROR_BYTE_INDEX = 37; + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + ERROR_BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Four Activate Window Delay Time (tFAWmin) in MTB") ); + + // Update output only after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Four Activate Window Delay Time (tFAWmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tRRD_Smin MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 38 +/// @note Item JC-45-2220.01x +/// @note Page 43 +/// @note DDR4 SPD Document Release 3 +/// @warning If tRRD_Smin cannot be divided evenly by the MTB, +/// this byte must be rounded up to the next larger +/// integer and the Fine Offset for tRRD_Smin (SPD byte 119) +/// used for correction to get the actual value. +/// +fapi2::ReturnCode decoder::min_trrd_s(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 38; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Minimum Activate to Activate Delay Time - Different Bank Group + // explicit conversion to int64_t + int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); + + // Find valid value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tRRD_Lmin MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 39 +/// @note Item JC-45-2220.01x +/// @note Page 43-44 +/// @note DDR4 SPD Document Release 3 +/// @warning If tRRD_Lmin cannot be divided evenly by the MTB, +/// this byte must be rounded up to the next larger +/// integer and the Fine Offset for tRRD_Lmin (SPD byte 118) +/// used for correction to get the actual value. +/// +fapi2::ReturnCode decoder::min_trrd_l(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 39; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Minimum Activate to Activate Delay Time - Same Bank Group + // explicit conversion to int64_t + int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); + + // Find valid value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tCCD_Lmin MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 40 +/// @note Item JC-45-2220.01x +/// @note Page 44-45 +/// @note DDR4 SPD Document Release 3 +/// @warning If tCCD_Lmin cannot be divided evenly by the MTB, +/// this byte must be rounded up to the next larger +/// integer and the Fine Offset for tCCD_Lmin (SPD byte 117) +/// used for correction to get the actual value. +/// +fapi2::ReturnCode decoder::min_tccd_l(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 40; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Minimum CAS to CAS Delay Time - Same Bank Group + // explicit conversion to int64_t + int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Minimum Write Recovery Time +/// @param[in] i_target dimm target +/// @param[out] o_value tWRmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) +/// @note Item JC-45-2220.01x +/// @note Page 40 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::min_write_recovery_time(const fapi2::Target& i_target, + int64_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) were reserved + // and coded as zeros. There was no concept of + // min write recovery time so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; + +} + +/// +/// @brief Decodes Minimum Write to Read Time - Different Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tWRT_Smin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) +/// @note Item JC-45-2220.01x +/// @note Page 40 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::min_twtr_s(const fapi2::Target& i_target, + int64_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) were reserved + // and coded as zeros. There was no concept of twtr_s so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decodes Minimum Write to Read Time - Same Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tWRT_Lmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) +/// @note Item JC-45-2220.01x +/// @note Page 46 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::min_twtr_l(const fapi2::Target& i_target, + int64_t& o_value) +{ + // For General Section rev 1.0 of the SPD, + // SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) were reserved + // and coded as zeros. There was no concept of twtr_l so this + // is thus hard-wired to zero. + o_value = 0x00; + return fapi2::FAPI2_RC_SUCCESS; + +} + +/// +/// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tCCD_Lmin offset in FTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 117 +/// @note Item JC-45-2220.01x +/// @note Page 52 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_offset_min_tccd_l(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 117; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Fine Offset for Minimum CAS to CAS Delay Time + // int8_t conversion - allows me to get a negative offset + // then implicit conversion to int64_t + int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the fine offset for min RAS to CAS Delay Time (tCCD_Lmin)") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Fine offset for Minimum RAS to CAS Delay Time (tCCD_Lmin) in FTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tRRD_Lmin offset in FTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 118 +/// @note Item JC-45-2220.01x +/// @note Page 52 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_offset_min_trrd_l(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 118; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Fine Offset for Minimum Activate to Activate Delay Time + // int8_t conversion - allows me to get a negative offset + // then implicit conversion to int64_t + int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin)") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin) in FTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tRRD_Smin offset in FTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 119 +/// @note Item JC-45-2220.01x +/// @note Page 52 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_offset_min_trrd_s(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 119; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group + // int8_t conversion - allows me to get a negative offset + // then implicit conversion to int64_t + int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin)") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in FTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time +/// @param[in] i_target dimm target +/// @param[out] o_value tRCmin offset in FTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 120 +/// @note Item JC-45-2220.01x +/// @note Page 52 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_offset_min_trc(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 120; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Fine Offset for Minimum Active to Active/Refresh Delay Time + // int8_t conversion - allows me to get a negative offset + // then implicit conversion to int64_t + int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); + + // Check for vali value + constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin)") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin) in FTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time +/// @param[in] i_target dimm target +/// @param[out] o_value tRPmin offset in FTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 121 +/// @note Item JC-45-2220.01x +/// @note Page 52 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_offset_min_trp(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 121; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Fine Offset for Minimum Row Precharge Delay Time + // int8_t conversion - allows me to get a negative offset + // then implicit conversion to int64_t + int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the fine offset for Minimum Row Precharge Delay Time (tRPmin)") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Fine offset for Minimum Row Precharge Delay Time (tRPmin) in FTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} +/// +/// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time +/// @param[in] i_target dimm target +/// @param[out] o_value tRCDmin offset in FTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 122 +/// @note Item JC-45-2220.01x +/// @note Page 52 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_offset_min_trcd(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 122; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Fine Offset for SDRAM Minimum RAS to CAS Delay Time + // int8_t conversion - allows me to get a negative offset + // then implicit conversion to int64_t + int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the fine offset for min RAS to CAS Delay Time (tRCDmin)") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Fine offset for Minimum RAS to CAS Delay Time (tRCDmin) in FTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time +/// @param[in] i_target dimm target +/// @param[out] o_value tAAmin offset in FTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 123 +/// @note Item JC-45-2220.01x +/// @note Page 52 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_offset_min_taa(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 123; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Fine Offset for SDRAM Minimum CAS Latency Time + // int8_t conversion - allows me to get a negative offset + // then implicit conversion to int64_t + int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the Fine offset for Minimum CAS Latency Time (tAAmin)") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Fine offset for Minimum CAS Latency Time (tAAmin) in FTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time +/// @param[in] i_target dimm target +/// @param[out] o_value tCKmax offset in FTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 124 +/// @note Item JC-45-2220.01x +/// @note Page 52 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_offset_max_tck(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 124; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Fine Offset for SDRAM Maximum Cycle Time + // int8_t conversion - allows me to get a negative offset + // then implicit conversion to int64_t + int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the fine offset for max cycle time (tckmax)") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Fine offset for Maximum Cycle Time (tCKmax) in FTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time +/// @param[in] i_target dimm target +/// @param[out] o_value tCKmin offset in FTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 125 +/// @note Item JC-45-2220.01x +/// @note Page 52 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::fine_offset_min_tck(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 125; + + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + iv_spd_data[BYTE_INDEX]); + + // Retrieve Fine Offset for SDRAM Minimum Cycle Time + // int8_t conversion - allows me to get a negative offset + // then implicit conversion to int64_t + int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); + + // Check for valid value + constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC + constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + BYTE_INDEX, + l_timing_val, + "Failed check on the Fine offset for Minimum Cycle Time (tCKmin)") ); + + // Update output value only if range check passes + o_value = l_timing_val; + + FAPI_INF("%s. Fine offset for Minimum Cycle Time (tCKmin) in FTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section +/// @param[in] i_target dimm target +/// @param[out] o_value crc value from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 127 & Byte 126 +/// @note Item JC-45-2220.01x +/// @note Page 53 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder::cyclical_redundancy_code(const fapi2::Target& i_target, + uint16_t& o_value) +{ + constexpr size_t BYTE_INDEX_MSB = 127; + uint8_t crc_MSB = extract_spd_field< BYTE_INDEX_MSB, CRC_MSB_START, CRC_MSB_LEN >(i_target, iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 126; + uint8_t crc_LSB = extract_spd_field< BYTE_INDEX_LSB, CRC_LSB_START, CRC_LSB_LEN >(i_target, iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSN_START = 0; + constexpr size_t MSN_LEN = 8; + constexpr size_t LSB_START = 8; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + l_buffer.insertFromRight( crc_MSB ) + .insertFromRight( crc_LSB ); + + // This value isn't bounded in the SPD document + o_value = l_buffer; + + FAPI_INF("%s. Cyclical Redundancy Code (CRC): %d", + mss::c_str(i_target), + o_value); + + // Returns "happy" until we can figure out a way to test this - AAM + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Returns Logical ranks in Primary SDRAM type +/// @param[in] i_target dimm target +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode decoder::prim_sdram_logical_ranks(const fapi2::Target& i_target, + uint8_t& o_logical_ranks) +{ + uint8_t l_signal_loading = 0; + uint8_t l_ranks_per_dimm = 0; + + FAPI_TRY( prim_sdram_signal_loading(i_target, l_signal_loading) ); + FAPI_TRY( num_package_ranks_per_dimm(i_target, l_ranks_per_dimm) ); + + if(l_signal_loading == spd::SINGLE_LOAD_STACK) + { + // For single-load-stack(3DS) the logical ranks per package ends up being the same as the die count. + uint8_t l_die_count = 0; + FAPI_TRY( prim_sdram_die_count(i_target, l_die_count) ); + + o_logical_ranks = l_ranks_per_dimm * l_die_count; + } + else + { + // Covers case for MONOLITHIC & MULTI_LOAD_STACK + // The die count isn't guaranteed to be 1 (e.g. SDP - 1 die package, DDP - 2 die package). + // Value of 1 is used for calculation purposes as defined by the SPD spec. + o_logical_ranks = l_ranks_per_dimm; + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Returns Logical ranks per DIMM +/// @param[in] i_target dimm target +/// @param[in] i_pDecoder shared pointer to the SPD decoder +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode decoder::logical_ranks_per_dimm(const fapi2::Target& i_target, + uint8_t& o_logical_rank_per_dimm) +{ + FAPI_TRY( prim_sdram_logical_ranks(i_target, o_logical_rank_per_dimm) ); + +fapi_try_exit: + return fapi2::current_err; +} + +}//spd +}// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H new file mode 100644 index 000000000..0a8bfbd19 --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H @@ -0,0 +1,1454 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/// +/// @file spd_decoder.H +/// @brief SPD decoder declarations +/// +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Brian Silver +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_SPD_DECODER_H_ +#define _MSS_SPD_DECODER_H_ + +// std lib +#include +#include +#include + +// fapi2 +#include + +// mss lib +#include +#include + +namespace mss +{ +namespace spd +{ + +enum byte_extract : uint8_t +{ + // Byte 0 + BYTES_USED_START = 4, + BYTES_USED_LEN = 4, + + BYTES_TOTAL_START = 1, + BYTES_TOTAL_LEN = 3, + + // Byte 1 + ENCODING_LEVEL_START = 0, + ENCODING_LEVEL_LEN = 4, + + ADDITIONS_LEVEL_START = 4, + ADDITIONS_LEVEL_LEN = 4, + + // Byte 2 - Entire byte used + + // Byte 3 + BASE_MODULE_START = 4, + BASE_MODULE_LEN = 4, + + HYBRID_MEDIA_START = 1, + HYBRID_MEDIA_LEN = 3, + + HYBRID_START = 0, + HYBRID_LEN = 1, + + // Byte 4 + SDRAM_CAPACITY_START = 4, + SDRAM_CAPACITY_LEN = 4, + + SDRAM_BANKS_START = 2, + SDRAM_BANKS_LEN = 2, + + BANK_GROUP_START = 0, + BANK_GROUP_LEN = 2, + + // Byte 5 + COL_ADDRESS_START = 5, + COL_ADDRESS_LEN = 3, + + ROW_ADDRESS_START = 2, + ROW_ADDRESS_LEN = 3, + + ADDRESS_RESERVED_START = 0, + ADDRESS_RESERVED_LEN = 2, + + // Byte 6 + PRIM_SIGNAL_LOAD_START = 6, + PRIM_SIGNAL_LOAD_LEN = 2, + + PACKAGE_RESERVE_START = 4, + PACKAGE_RESERVE_LEN = 2, + + PRIM_DIE_COUNT_START = 1, + PRIM_DIE_COUNT_LEN = 3, + + PRIM_PACKAGE_TYPE_START = 0, + PRIM_PACKAGE_TYPE_LEN = 1, + + // Byte 7 + MAC_START = 4, + MAC_LEN = 4, + + TMAW_START = 2, + TMAW_LEN = 2, + + OPT_FEAT_RESERVED_START = 0, + OPT_FEAT_RESERVED_LEN = 2, + + // Byte 8 reserved + + // Byte 9 + PPR_RESERVED_START = 3, + PPR_RESERVED_LEN = 5, + + SOFT_PPR_START = 2, + SOFT_PPR_LEN = 1, + + PPR_START = 0, + PPR_LEN = 2, + + // Byte 10 + SEC_SIGNAL_LOAD_START = 5, + SEC_SIGNAL_LOAD_LEN = 2, + + DENSITY_RATIO_START = 4, + DENSITY_RATIO_LEN = 2, + + SEC_DIE_COUNT_START = 1, + SEC_DIE_COUNT_LEN = 3, + + SEC_PACKAGE_TYPE_START = 0, + SEC_PACKAGE_TYPE_LEN = 1, + + // Byte 11 + OPERABLE_START = 7, + OPERABLE_LEN = 1, + + ENDURANT_START = 6, + ENDURANT_LEN = 1, + + NOM_VOLT_START = 0, + NOM_VOLT_LEN = 6, + + // Byte 12 + SDRAM_WIDTH_START = 5, + SDRAM_WIDTH_LEN = 3, + + PACKAGE_RANKS_START = 2, + PACKAGE_RANKS_LEN = 3, + + RANK_MIX_START = 1, + RANK_MIX_LEN = 1, + + MODULE_ORG_RESERVED_START = 0, + MODULE_ORG_RESERVED_LEN = 1, + + // Byte 13 + BUS_WIDTH_START = 5, + BUS_WIDTH_LEN = 3, + + BUS_EXT_WIDTH_START = 3, + BUS_EXT_WIDTH_LEN = 2, + + BUS_WIDTH_RESERVED_START = 0, + BUS_WIDTH_RESERVED_LEN = 3, + + // Byte 14 + THERM_SENSOR_RESERV_START = 1, + THERM_SENSOR_RESERV_LEN = 7, + + THERM_SENSOR_START = 0, + THERM_SENSOR_LEN = 1, + + // Byte 15 + EXT_MOD_TYPE_START = 5, + EXT_MOD_TYPE_LEN = 3, + + EXT_MOD_TYPE_RESERV_START = 0, + EXT_MOD_TYPE_RESERV_LEN = 4, + + // Byte 16 - reserved + + // Byte 17 + FINE_TIMEBASE_START = 6, + FINE_TIMEBASE_LEN = 2, + + MED_TIMEBASE_START = 4, + MED_TIMEBASE_LEN = 2, + + TIMEBASE_RESERV_START = 0, + TIMEBASE_RESERV_LEN = 4, + + // Byte 18 - Entire byte used + // Byte 19 - Entire byte used + + // Byte 20-23 + CAS_BYTE_1_START = 56, + CAS_BYTE_1_LEN = 8, + CAS_BYTE_2_START = 48, + CAS_BYTE_2_LEN = 8, + CAS_BYTE_3_START = 40, + CAS_BYTE_3_LEN = 8, + CAS_BYTE_4_START = 32, + CAS_BYTE_4_LEN = 8, + + // Byte 24 - Entire byte used + // Byte 25 - Entire byte used + // Byte 26 - Entire byte used + + // Byte 27 + TRASMIN_MSN_START = 4, // MSN = most significant nibble + TRASMIN_MSN_LEN = 4, + + TRCMIN_MSN_START = 0, // MSN = most significant nibble + TRCMIN_MSN_LEN = 4, + + // Byte 28 + TRASMIN_LSB_START = 0, // LSB = least significant byte + TRASMIN_LSB_LEN = 8, + + // Byte 29 + TRCMIN_LSB_START = 0, // LSB = least significant byte + TRCMIN_LSB_LEN = 8, + + // Byte 30 + TRFC1MIN_LSB_START = 0, + TRFC1MIN_LSB_LEN = 8, + + // Byte 31 + TRFC1MIN_MSB_START = 0, + TRFC1MIN_MSB_LEN = 8, + + // Byte 32 + TRFC2MIN_LSB_START = 0, + TRFC2MIN_LSB_LEN = 8, + + // Byte 33 + TRFC2MIN_MSB_START = 0, + TRFC2MIN_MSB_LEN = 8, + + // Byte 34 & Byte 35 + TRFC4MIN_LSB_START = 0, + TRFC4MIN_LSB_LEN = 8, + + TRFC4MIN_MSB_START = 0, + TRFC4MIN_MSB_LEN = 8, + + // Byte 36 + TFAWMIN_MSN_START = 4, + TFAWMIN_MSN_LEN = 4, + + // Byte 37 + TFAWMIN_LSB_START = 0, + TFAWMIN_LSB_LEN = 8, + + // Byte 38 - Entire byte used + // Byte 39 - Entire byte used + // Byte 40 - Entire byte used + + // Byte 41 + TWRMIN_MSN_START = 4, // MSN = most significant nibble + TWRMIN_MSN_LEN = 4, + + // Byte 42 + TWRMIN_LSB_START = 0, // LSB = least significant nibble + TWRMIN_LSB_LEN = 8, + + // Byte 43 + TWTRMIN_L_MSN_START = 0, // MSN = most significant nibble + TWTRMIN_L_MSN_LEN = 4, + + TWTRMIN_S_MSN_START = 4, // MSN = most significant nibble + TWTRMIN_S_MSN_LEN = 4, + + // Byte 44 + TWTRMIN_S_LSB_START = 0, // LSB = least significant byte + TWTRMIN_S_LSB_LEN = 8, + + // Byte 45 + TWTRMIN_L_LSB_START = 0, + TWTRMIN_L_LSB_LEN = 8, + + // Bytes 46 - 59 - reserved + + // Bytes 60 - 77 - Connector to SDRAM Bit Mapping ?? + + // Bytes 78 - 116 - reserved + + // Bytes 117 - 125 : Entire byte used + + // Byte 126 + CRC_MSB_START = 0, + CRC_MSB_LEN = 8, + + // Byte 127 + CRC_LSB_START = 0, + CRC_LSB_LEN = 8, + + // Bytes 128 ~ 191 Module-Specific Section ?? + + // Bytes 192 ~ 255 Hybrid Memory Architecture Specific Parameters ?? + + // Bytes 256 ~ 319 Extended Function Parameter Block ?? + + // Bytes 320 ~ 383 Module Supplier’s Data ?? +}; + +enum sdram_package_type : size_t +{ + // Signal loading + MONOLITHIC = 0, + NON_MONOLITHIC = 1, + + // Package Type + UNSPECIFIED = MONOLITHIC, + MULTI_LOAD_STACK = 1, + SINGLE_LOAD_STACK = 2, +}; + +enum nominal_voltage : uint8_t +{ + NOT_OPERABLE = 0, + OPERABLE = 1, + + NOT_ENDURANT = 0, + ENDURANT = 1 +}; + +/// +/// @brief Helper function to extract byte information +/// @tparam I Byte index +/// @tparam S Start bit +/// @tparam L Bit length +/// @return extracted byte (right aligned) +/// +template +inline uint8_t extract_spd_field(const fapi2::Target& i_target, + const std::vector& i_spd_data) +{ + //TODO - RTC:159477 + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + I, + i_spd_data[I]); + + fapi2::buffer l_buffer(i_spd_data[I]); + + // Extracting desired bits + uint8_t l_field_bits = 0; + l_buffer.extractToRight(l_field_bits); + + return l_field_bits; +} + +/// +/// @class decoder +/// @brief Base SPD DRAM decoder +/// +class decoder +{ + public: + std::shared_ptr iv_module_decoder; + std::vector iv_spd_data; + + /// + /// @brief Default constructor + /// + decoder() = delete; + + /// + /// @brief ctor + /// @param[in] i_target dimm target + /// @param[in] i_spd_data SPD data vector + /// @param[in] i_module_decoder shared_ptr to dimm module decoder + /// + decoder(const fapi2::Target& i_target, + const std::vector& i_spd_data, + const std::shared_ptr& i_module_decoder); + + /// + /// @brief Default dtor + /// + virtual ~decoder() = default; + + ///////////////////////// + // Member Methods + ///////////////////////// + + /// + /// @brief Decodes number of used SPD bytes + /// @param[in] i_target dimm target + /// @param[out] o_value number of SPD bytes used + /// @return FAPI2_RC_SUCCESS if okay + /// @note Decodes SPD Byte 0 (3~0) + /// @note Item JC-45-2220.01x + /// @note Page 14 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode number_of_used_bytes(const fapi2::Target& i_target, + uint16_t& o_value); + + /// + /// @brief Decodes total number of SPD bytes + /// @param[in] i_target dimm target + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS if okay + /// @note Decodes SPD Byte 0 (bits 6~4) + /// @note Item JC-45-2220.01x + /// @note Page 14 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode number_of_total_bytes(const fapi2::Target& i_target, + uint16_t& o_value); + + /// + /// @brief Decodes hybrid media field from SPD + /// @param[in] i_target + /// @param[out] o_value + /// @return FAPI2_RC_SUCCESS if okay + /// @note Decodes SPD Byte 3 (bits 6~4) + /// @note Item JC-45-2220.01x + /// @note Page 17 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode hybrid_media(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes hybrid field from SPD + /// @param[in] i_target + /// @param[out] o_value + /// @return FAPI2_RC_SUCCESS if okay + /// @note Decodes SPD Byte 3 (bit 7) + /// @note Item JC-45-2220.01x + /// @note Page 17 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode hybrid(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes SDRAM density from SPD + /// @param[in] i_target dimm target + /// @param[out] o_value SDRAM density in GBs + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 4 (bits 3~0) + /// @note Item JC-45-2220.01x + /// @note Page 18 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sdram_density(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes number of SDRAM banks bits from SPD + /// @param[in] i_target dimm target + /// @param[out] o_value Number of SDRAM bank bits + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 4 (bits 5~4) + /// @note Item JC-45-2220.01x + /// @note Page 18 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode bank_bits(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes number of SDRAM bank groups bits from SPD + /// @param[in] i_target dimm target + /// @param[out] o_value Number of SDRAM bank groups bits + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 4 (bits 7~6) + /// @note Item JC-45-2220.01x + /// @note Page 18 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode bank_group_bits(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes number of SDRAM column address bits + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 5 (bits 2~0) + /// @note Item JC-45-2220.01x + /// @note Page 18 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode column_address_bits(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes number of SDRAM row address bits + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 5 (bits 5~3) + /// @note Item JC-45-2220.01x + /// @note Page 18 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode row_address_bits(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes Primary SDRAM signal loading + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 6 (bits 1~0) + /// @note Item JC-45-2220.01x + /// @note Page 19 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode prim_sdram_signal_loading(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes Primary SDRAM die count + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 6 (bits 6~4) + /// @note Item JC-45-2220.01x + /// @note Page 19 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode prim_sdram_die_count(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes Primary SDRAM package type + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 6 (bit 7) + /// @note Item JC-45-2220.01x + /// @note Page 19 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode prim_sdram_package_type(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decode SDRAM Maximum activate count + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 7 (bits 3~0) + /// @note Item JC-45-2220.01x + /// @note Page 20 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode maximum_activate_count(const fapi2::Target& i_target, + uint32_t& o_value); + + /// + /// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point + /// @param[in] i_target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 7 (bits 3~0) + /// @note Item JC-45-2220.01x + /// @note Page 20 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode maximum_activate_window_multiplier(const fapi2::Target& i_target, + uint32_t& o_value); + + /// + /// @brief Decode Post package repair (PPR) + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 9 (bits 7~6) + /// @note Item JC-45-2220.01x + /// @note Page 21 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode post_package_repair(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decode Soft post package repair (soft PPR) + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 9 (bit 5) + /// @note Item JC-45-2220.01x + /// @note Page 21 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode soft_post_package_repair(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes Secondary SDRAM signal loading + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 10 (bits 1~0) + /// @note Item JC-45-2220.01x + /// @note Page 22 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sec_sdram_signal_loading(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes Secondary DRAM Density Ratio + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 10 (bits 3~2) + /// @note Item JC-45-2220.01x + /// @note Page 22 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sec_dram_density_ratio(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes Secondary SDRAM die count + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 10 (bits 6~4) + /// @note Item JC-45-2220.01x + /// @note Page 22 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sec_sdram_die_count(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes Secondary SDRAM package type + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 10 (bit 7) + /// @note Item JC-45-2220.01x + /// @note Page 22 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sec_sdram_package_type(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decode Module Nominal Voltage, VDD + /// @param[in] i_target dimm target + /// @param[out] o_value enum representing if 1.2V is operable + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 11 (bit 0) + /// @note Item JC-45-2220.01x + /// @note Page 23 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode operable_nominal_voltage(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decode Module Nominal Voltage, VDD + /// @param[in] i_target dimm target + /// @param[out] o_value enum representing if 1.2V is endurant + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 11 (bit 1) + /// @note Item JC-45-2220.01x + /// @note Page 23 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode endurant_nominal_voltage(const fapi2::Target& i_target, + uint8_t& o_value); + /// + /// @brief Decodes SDRAM device width + /// @param[in] i_target dimm target + /// @param[out] o_value device width in bits + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 12 (bits 2~0) + /// @note Item JC-45-2220.01x + /// @note Page 23 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode device_width(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes number of package ranks per DIMM + /// @param[in] i_target dimm target + /// @param[out] o_value number of package ranks per DIMM + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 12 (bits 5~3) + /// @note Item JC-45-2220.01x + /// @note Page 23 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode num_package_ranks_per_dimm(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes Rank Mix + /// @param[in] i_target dimm target + /// @param[out] o_value rank mix value from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 12 (bit 6) + /// @note Item JC-45-2220.01x + /// @note Page 23 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode rank_mix(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes primary bus width + /// @param[in] i_target dimm target + /// @param[out] o_value primary bus width in bits + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 13 (bits 2~0) + /// @note Item JC-45-2220.01x + /// @note Page 27 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode prim_bus_width(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decodes bus width extension + /// @param[in] i_target dimm target + /// @param[out] o_value bus width extension in bits + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 13 (bits 4~3) + /// @note Item JC-45-2220.01x + /// @note Page 27 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode bus_width_extension(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decode Module Thermal Sensor + /// @param[in] i_target dimm target + /// @param[out] o_value thermal sensor value from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 14 (bit 7) + /// @note Item JC-45-2220.01x + /// @note Page 28 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode thermal_sensor(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decode Extended Base Module Type + /// @param[in] i_target dimm target + /// @param[out] o_value extended base module type value from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 15 (bits 3~0) + /// @note Item JC-45-2220.01x + /// @note Page 28 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode extended_base_module_type(const fapi2::Target& i_target, + uint8_t& o_value); + + /// + /// @brief Decode Fine Timebase + /// @param[in] i_target dimm target + /// @param[out] o_value fine_timebase from SPD in picoseconds + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 17 (bits 1~0) + /// @note Item JC-45-2220.01x + /// @note Page 29 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_timebase(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decode Medium Timebase + /// @param[in] i_target dimm target + /// @param[out] o_value fine_timebase from SPD in picoseconds + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 17 (bits 3~2) + /// @note Item JC-45-2220.01x + /// @note Page 29 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode medium_timebase(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// + /// @brief Decodes SDRAM Minimum Cycle Time in MTB + /// @param[in] i_target dimm target + /// @param[out] o_value tCKmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 18 + /// @note Item JC-45-2220.01x + /// @note Page 31-32 + /// @note DDR4 SPD Document Release 3 + /// @warning If tCKmin cannot be divided evenly by the MTB, + /// this byte must be rounded up to the next larger + /// integer and the Fine Offset for tCKmin (SPD byte 125) + /// used for correction to get the actual value. + /// + virtual fapi2::ReturnCode min_cycle_time(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes SDRAM Maximum Cycle Time in MTB + /// @param[in] i_target dimm target + /// @param[out] o_value tCKmax in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 19 + /// @note Item JC-45-2220.01x + /// @note Page 32 + /// @note DDR4 SPD Document Release 3 + /// @warning If tCKmax cannot be divided evenly by the MTB, + /// this byte must be rounded up to the next larger + /// integer and the Fine Offset for tCKmax (SPD byte 124) + /// used for correction to get the actual value. + /// + virtual fapi2::ReturnCode max_cycle_time(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decode CAS Latencies Supported + /// @param[in] i_target dimm target + /// @param[out] o_value bitmap of supported CAS latencies + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Bytes 20-23 + /// @note Item JC-45-2220.01x + /// @note Page 33-34 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode supported_cas_latencies(const fapi2::Target& i_target, + uint64_t& o_value); + + /// + /// @brief Decodes SDRAM Minimum CAS Latency Time in MTB + /// @param[in] i_target dimm target + /// @param[out] o_value tAAmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 24 + /// @note Item JC-45-2220.01x + /// @note Page 34 + /// @note DDR4 SPD Document Release 3 + /// @warning If tAAmin cannot be divided evenly by the MTB, + /// this byte must be rounded up to the next larger + /// integer and the Fine Offset for tAAmin (SPD byte 123) + /// used for correction to get the actual value. + /// + virtual fapi2::ReturnCode min_cas_latency_time(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB + /// @param[in] i_target dimm target + /// @param[out] o_value tRCDmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 25 + /// @note Item JC-45-2220.01x + /// @note Page 35 + /// @note DDR4 SPD Document Release 3 + /// @warning If tRCDmin cannot be divided evenly by the MTB, + /// this byte must be rounded up to the next larger + /// integer and the Fine Offset for tRCDmin (SPD byte 122) + /// used for correction to get the actual value + /// + virtual fapi2::ReturnCode min_ras_to_cas_delay_time(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB + /// @param[in] i_target dimm target + /// @param[out] o_value tRPmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 26 + /// @note Item JC-45-2220.01x + /// @note Page 36-37 + /// @note DDR4 SPD Document Release 3 + /// @warning If tRPmin cannot be divided evenly by the MTB, + /// this byte must be rounded up to the next larger + /// integer and the Fine Offset for tRPmin (SPD byte 121) + /// used for correction to get the actual value + /// + virtual fapi2::ReturnCode min_row_precharge_delay_time(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB + /// @param[in] i_target dimm target + /// @param[out] o_value tRASmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 28 (bits 7~4) & SPD Byte 27 (bits 3~0) + /// @note Item JC-45-2220.01x + /// @note Page 38 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_active_to_precharge_delay_time(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB + /// @param[in] i_target dimm target + /// @param[out] o_value tRCmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 27 (bits 7~4) & SPD Byte 29 (bits 7~0) + /// @note Item JC-45-2220.01x + /// @note Page 38 + /// @note DDR4 SPD Document Release 3 + /// @warning If tRCmin cannot be divided evenly by the MTB, + /// this byte must be rounded up to the next larger + /// integer and the Fine Offset for tRCmin (SPD byte 120) + /// used for correction to get the actual value. + /// + virtual + fapi2::ReturnCode min_active_to_active_refresh_delay_time(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1 + /// @param[in] i_target dimm target + /// @param[out] o_value tRFC1min in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 30 & Byte 31 + /// @note Item JC-45-2220.01x + /// @note Page 39-40 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_refresh_recovery_delay_time_1(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2 + /// @param[in] i_target dimm target + /// @param[out] o_value tRFC2min in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 32 & Byte 33 + /// @note Item JC-45-2220.01x + /// @note Page 40 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_refresh_recovery_delay_time_2(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4 + /// @param[in] i_target dimm target + /// @param[out] o_value tRFC4min in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 34 & Byte 35 + /// @note Item JC-45-2220.01x + /// @note Page 40 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_refresh_recovery_delay_time_4(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes SDRAM Minimum Four Activate Window Delay Time + /// @param[in] i_target dimm target + /// @param[out] o_value tFAWmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 36 (bits 3~0) & Byte 37 (bits 7~0) + /// @note Item JC-45-2220.01x + /// @note Page 42 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_tfaw(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tRRD_Smin MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 38 + /// @note Item JC-45-2220.01x + /// @note Page 43 + /// @note DDR4 SPD Document Release 3 + /// @warning If tRRD_Smin cannot be divided evenly by the MTB, + /// this byte must be rounded up to the next larger + /// integer and the Fine Offset for tRRD_Smin (SPD byte 119) + /// used for correction to get the actual value. + /// + virtual fapi2::ReturnCode min_trrd_s(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tRRD_Lmin MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 39 + /// @note Item JC-45-2220.01x + /// @note Page 43-44 + /// @note DDR4 SPD Document Release 3 + /// @warning If tRRD_Lmin cannot be divided evenly by the MTB, + /// this byte must be rounded up to the next larger + /// integer and the Fine Offset for tRRD_Lmin (SPD byte 118) + /// used for correction to get the actual value. + /// + virtual fapi2::ReturnCode min_trrd_l(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tCCD_Lmin MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 40 + /// @note Item JC-45-2220.01x + /// @note Page 44-45 + /// @note DDR4 SPD Document Release 3 + /// @warning If tCCD_Lmin cannot be divided evenly by the MTB, + /// this byte must be rounded up to the next larger + /// integer and the Fine Offset for tCCD_Lmin (SPD byte 117) + /// used for correction to get the actual value. + /// + virtual fapi2::ReturnCode min_tccd_l(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Minimum Write Recovery Time + /// @param[in] i_target dimm target + /// @param[out] o_value tWRmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) + /// @note Item JC-45-2220.01x + /// @note Page 40 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_write_recovery_time(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Minimum Write to Read Time - Different Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tWRT_Smin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) + /// @note Item JC-45-2220.01x + /// @note Page 40 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_twtr_s(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Minimum Write to Read Time - Same Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tWRT_Lmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) + /// @note Item JC-45-2220.01x + /// @note Page 46 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_twtr_l(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tCCD_Lmin offset in FTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 117 + /// @note Item JC-45-2220.01x + /// @note Page 52 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_offset_min_tccd_l(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tRRD_Lmin offset in FTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 118 + /// @note Item JC-45-2220.01x + /// @note Page 52 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_offset_min_trrd_l(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tRRD_Smin offset in FTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 119 + /// @note Item JC-45-2220.01x + /// @note Page 52 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_offset_min_trrd_s(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time + /// @param[in] i_target dimm target + /// @param[out] o_value tRCmin offset in FTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 120 + /// @note Item JC-45-2220.01x + /// @note Page 52 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_offset_min_trc(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time + /// @param[in] i_target dimm target + /// @param[out] o_value tRPmin offset in FTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 121 + /// @note Item JC-45-2220.01x + /// @note Page 52 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_offset_min_trp(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time + /// @param[in] i_target dimm target + /// @param[out] o_value tRCDmin offset in FTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 122 + /// @note Item JC-45-2220.01x + /// @note Page 52 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_offset_min_trcd(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time + /// @param[in] i_target dimm target + /// @param[out] o_value tAAmin offset in FTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 123 + /// @note Item JC-45-2220.01x + /// @note Page 52 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_offset_min_taa(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time + /// @param[in] i_target dimm target + /// @param[out] o_value tCKmax offset in FTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 124 + /// @note Item JC-45-2220.01x + /// @note Page 52 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_offset_max_tck(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time + /// @param[in] i_target dimm target + /// @param[out] o_value tCKmin offset in FTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 125 + /// @note Item JC-45-2220.01x + /// @note Page 52 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode fine_offset_min_tck(const fapi2::Target& i_target, + int64_t& o_value); + + /// + /// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section + /// @param[in] i_target dimm target + /// @param[out] o_value crc value from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 127 & Byte 126 + /// @note Item JC-45-2220.01x + /// @note Page 53 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode cyclical_redundancy_code(const fapi2::Target& i_target, + uint16_t& o_value); + + /// + /// @brief Returns Logical ranks per DIMM + /// @param[in] i_target dimm target + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode logical_ranks_per_dimm(const fapi2::Target& i_target, + uint8_t& o_logical_rank_per_dimm) ; + + protected: + // TODO RTC:159362 + const fapi2::Target iv_target; + + /// + /// @brief Helper function that turns Logical ranks in Primary SDRAM type + /// @param[in] i_target dimm target + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode prim_sdram_logical_ranks(const fapi2::Target& i_target, + uint8_t& o_logical_ranks); + +};// decoder + +/// +/// @class decoder_v1_1 +/// @brief Base SPD DRAM decoder, 1st addition to general section +/// +class decoder_v1_1 : public decoder +{ + protected: + + /// + /// @brief Helper functions that returns Logical ranks in Secondary SDRAM type + /// @param[in] i_target dimm target + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode sec_sdram_logical_ranks(const fapi2::Target& i_target, + uint8_t& o_logical_ranks); + + public: + /// + /// @brief Default constructor + /// + decoder_v1_1() = default; + + /// + /// @brief ctor + /// @param[in] i_target dimm target + /// @param[in] i_spd_data SPD data vector + /// + decoder_v1_1(const fapi2::Target& i_target, + const std::vector& i_spd_data, + const std::shared_ptr& i_module_decoder); + + /// + /// @brief Default dtor + /// + virtual ~decoder_v1_1() = default; + + ///////////////////////// + // Member Methods + ///////////////////////// + + /// + /// @brief Decodes hybrid media field from SPD + /// @param[in] i_target + /// @param[out] o_value + /// @return FAPI2_RC_SUCCESS if okay + /// @note Decodes SPD Byte 3 (bits 6~4) + /// @note Item JC-45-2220.01x + /// @note Page 17 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode hybrid_media(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decodes hybrid field from SPD + /// @param[in] i_target + /// @param[out] o_value + /// @return FAPI2_RC_SUCCESS if okay + /// @note Decodes SPD Byte 3 (bit 7) + /// @note Item JC-45-2220.01x + /// @note Page 17 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode hybrid(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decodes SDRAM density from SPD + /// @param[in] i_target dimm target + /// @param[out] o_value SDRAM density in GBs + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 4 (bits 3~0) + /// @note Item JC-45-2220.01x + /// @note Page 18 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sdram_density(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decode Soft post package repair (soft PPR) + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 9 (bit 5) + /// @note Item JC-45-2220.01x + /// @note Page 21 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode soft_post_package_repair(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decodes Secondary SDRAM signal loading + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 10 (bits 1~0) + /// @note Item JC-45-2220.01x + /// @note Page 22 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sec_sdram_signal_loading(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decodes Secondary DRAM Density Ratio + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 10 (bits 3~2) + /// @note Item JC-45-2220.01x + /// @note Page 22 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sec_dram_density_ratio(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decodes Secondary SDRAM die count + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 10 (bits 6~4) + /// @note Item JC-45-2220.01x + /// @note Page 22 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sec_sdram_die_count(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decodes Secondary SDRAM package type + /// @param[in] i_target dimm target + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 10 (bit 7) + /// @note Item JC-45-2220.01x + /// @note Page 22 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode sec_sdram_package_type(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decodes number of package ranks per DIMM + /// @param[in] i_target dimm target + /// @param[out] o_value number of package ranks per DIMM + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 12 (bits 5~3) + /// @note Item JC-45-2220.01x + /// @note Page 23 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode num_package_ranks_per_dimm(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decodes Rank Mix + /// @param[in] i_target dimm target + /// @param[out] o_value rank mix value from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 12 (bit 6) + /// @note Item JC-45-2220.01x + /// @note Page 23 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode rank_mix(const fapi2::Target& i_target, + uint8_t& o_value) override; + + /// + /// @brief Decode CAS Latencies Supported + /// @param[in] i_target dimm target + /// @param[out] o_value bitmap of supported CAS latencies + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Bytes 20-23 + /// @note Item JC-45-2220.01x + /// @note Page 33-34 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode supported_cas_latencies(const fapi2::Target& i_target, + uint64_t& o_value) override; + + /// + /// @brief Decodes Minimum Write Recovery Time + /// @param[in] i_target dimm target + /// @param[out] o_value tWRmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) + /// @note Item JC-45-2220.01x + /// @note Page 40 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_write_recovery_time(const fapi2::Target& i_target, + int64_t& o_value) override; + + /// + /// @brief Decodes Minimum Write to Read Time - Different Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tWRT_Smin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) + /// @note Item JC-45-2220.01x + /// @note Page 40 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_twtr_s(const fapi2::Target& i_target, + int64_t& o_value) override; + + /// + /// @brief Decodes Minimum Write to Read Time - Same Bank Group + /// @param[in] i_target dimm target + /// @param[out] o_value tWRT_Lmin in MTB units + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) + /// @note Item JC-45-2220.01x + /// @note Page 46 + /// @note DDR4 SPD Document Release 3 + /// + virtual fapi2::ReturnCode min_twtr_l(const fapi2::Target& i_target, + int64_t& o_value) override; + + /// + /// @brief Returns Logical ranks per DIMM + /// @param[in] i_target dimm target + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode logical_ranks_per_dimm(const fapi2::Target& i_target, + uint8_t& o_logical_rank_per_dimm) override; + +};// spd_decoder_v1_1 + +}// spd +}// mss + +#endif //_MSS_SPD_DECODER_H_ diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder_v1_1.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder_v1_1.C new file mode 100644 index 000000000..9af4097ff --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder_v1_1.C @@ -0,0 +1,910 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder_v1_1.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file spd_decoder_v1_1.C +/// @brief SPD decoder definitions +/// +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Brian Silver +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +// fapi2 +#include + +// mss lib +#include +#include +#include +#include +#include + +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_DIMM; + +namespace mss +{ +namespace spd +{ + +///////////////////////// +// Member method definitions +///////////////////////// + +/// +/// @brief ctor +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data vector +/// +decoder_v1_1::decoder_v1_1(const fapi2::Target& i_target, + const std::vector& i_spd_data, + const std::shared_ptr& i_module_decoder) + : decoder(i_target, i_spd_data, i_module_decoder) +{} + +/// +/// @brief Decodes SDRAM density from SPD +/// @param[in] i_target dimm target +/// @param[out] o_value SDRAM density in GBs +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 4 (bits 0~3) +/// @note Item JC-45-2220.01x +/// @note Page 18 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::sdram_density(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 4 maps + // Item JC-45-2220.01x + // Page 18 + // DDR4 SPD Document Release 3 + // Byte 4 (0x004): SDRAM Density and Banks + // ========================================================= + static const std::vector > SDRAM_DENSITY_MAP = + { + // {key byte, capacity in GBs} + {2, 1}, + {3, 2}, + {4, 4}, + {5, 8}, + {6, 16}, + {7, 32}, + {8, 12}, + {12, 24} + }; + + // Extracting desired biits + constexpr size_t BYTE_INDEX = 4; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN >(i_target, + iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check to assure SPD DRAM capacity (map) wont be at invalid values + bool l_is_val_found = mss::find_value_from_key(SDRAM_DENSITY_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for SPD DRAM capacity") ); + + FAPI_INF("%s. SDRAM density: %d Gb", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes hybrid media field from SPD +/// @param[in] i_target +/// @param[out] o_value enum representing hybrid memory type +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 3 (bits 4~6) +/// @note Item JC-45-2220.01x +/// @note Page 17 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::hybrid_media(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 3 maps + // Item JC-45-2220.01x + // Page 17 + // DDR4 SPD Document Release 3 + // Byte 3 (0x003): Key Byte / Module Type + // ========================================================= + static const std::vector > HYBRID_MEDIA_MAP = + { + //{key, value} + {0, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE}, + {1, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 3; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, HYBRID_MEDIA_START, HYBRID_MEDIA_LEN >(i_target, + iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(HYBRID_MEDIA_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check on Hybrid Media type") ); + + FAPI_INF("%s. Hybrid Media: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes hybrid field from SPD +/// @param[in] i_target +/// @param[out] o_value enum representing if module is hybrid +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 3 (bit 7) +/// @note Item JC-45-2220.01x +/// @note Page 17 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::hybrid(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 3 maps + // Item JC-45-2220.01x + // Page 17 + // DDR4 SPD Document Release 3 + // Byte 3 (0x003): Key Byte / Module Type + // ========================================================= + static const std::vector > HYBRID_MAP = + { + //{key byte, value} + {0, fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID}, + {1, fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 3; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, HYBRID_START, HYBRID_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(HYBRID_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check on hybrid field") ); + + FAPI_INF("%s. Hybrid: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Secondary SDRAM signal loading +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing signal loading type +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 10 (bits 1~0) +/// @note Item JC-45-2220.01x +/// @note Page 22 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::sec_sdram_signal_loading(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 10 maps + // Item JC-45-2220.01x + // Page 21-22 + // DDR4 SPD Document Release 3 + // Byte 10 (0x00A): Secondary SDRAM Package Type + // ========================================================= + static const std::vector > SEC_SIGNAL_LOADING_MAP = + { + // {key byte, signal loading} + {0, UNSPECIFIED}, + {1, MULTI_LOAD_STACK}, + {2, SINGLE_LOAD_STACK} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 10; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, SEC_SIGNAL_LOAD_START, SEC_SIGNAL_LOAD_LEN >(i_target, + iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(SEC_SIGNAL_LOADING_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Secondary SDRAM Signal Loading") ); + + FAPI_INF("%s. Secondary SDRAM Signal Loading: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decode Soft post package repair (soft PPR) +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing if soft PPR is supported +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 9 (bit 5) +/// @note Item JC-45-2220.01x +/// @note Page 21 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::soft_post_package_repair(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 9 maps + // Item JC-45-2220.01x + // Page 21 + // DDR4 SPD Document Release 3 + // Byte 9 (0x009): Other SDRAM Optional Features + // ========================================================= + static const std::vector > SOFT_PPR_MAP = + { + // {key byte, value } + {0, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED}, + {1, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 9; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, SOFT_PPR_START, SOFT_PPR_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(SOFT_PPR_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Soft PPR") ); + + FAPI_INF("%s. Soft Post Package Repair (Soft PPR): %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Secondary DRAM Density Ratio +/// @param[in] i_target dimm target +/// @param[out] o_value raw bits from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 10 (bits 3~2) +/// @note Item JC-45-2220.01x +/// @note Page 22 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::sec_dram_density_ratio(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 10; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, DENSITY_RATIO_START, DENSITY_RATIO_LEN >(i_target, + iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + constexpr size_t UNDEFINED = 3; // JEDEC map doesn't go beyond 3 + + FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, + l_field_bits < UNDEFINED, + BYTE_INDEX, + l_field_bits, + "Failed check for DRAM Density Ratio") ); + + FAPI_INF("%s. DRAM Density Ratio: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes Secondary SDRAM die count +/// @param[in] i_target dimm target +/// @param[out] o_value die count +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 10 (bits 6~4) +/// @note Item JC-45-2220.01x +/// @note Page 22 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::sec_sdram_die_count(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 10 maps + // Item JC-45-2220.01x + // Page 21-22 + // DDR4 SPD Document Release 3 + // Byte 10 (0x00A): Secondary SDRAM Package Type + // ========================================================= + static const std::vector > SEC_DIE_COUNT_MAP = + { + // {key byte, number of die} + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 5}, + {5, 6}, + {6, 7}, + {7, 8} + + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 10; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, SEC_DIE_COUNT_START, SEC_DIE_COUNT_LEN >(i_target, + iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(SEC_DIE_COUNT_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Secondary Die Count") ); + + FAPI_INF("%s. Secondary Die Count: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Secondary SDRAM package type +/// @param[in] i_target dimm target +/// @param[out] o_value enum representing package type +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 10 (bit 7) +/// @note Item JC-45-2220.01x +/// @note Page 22 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::sec_sdram_package_type(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 10 maps + // Item JC-45-2220.01x + // Page 21-22 + // DDR4 SPD Document Release 3 + // Byte 10 (0x00A): Secondary SDRAM Package Type + // ========================================================= + + static const std::vector > SEC_PACKAGE_TYPE_MAP = + { + // {key byte, value } + {0, MONOLITHIC}, + {1, NON_MONOLITHIC} + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 10; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, SEC_PACKAGE_TYPE_START, SEC_PACKAGE_TYPE_LEN >(i_target, + iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(SEC_PACKAGE_TYPE_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Secondary Package Type") ); + + FAPI_INF("%s. Secondary Package Type: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes number of package ranks per DIMM +/// @param[in] i_target dimm target +/// @param[out] o_value number of package ranks per DIMM +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 12 (bits 5~3) +/// @note Item JC-45-2220.01x +/// @note Page 23 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::num_package_ranks_per_dimm(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // ========================================================= + // Byte 12 maps + // Item JC-45-2220.01x + // Page 23 + // DDR4 SPD Document Release 3 + // Byte 12 (0x00C): Module Organization + // ========================================================= + static const std::vector > NUM_PACKAGE_RANKS_MAP = + { + // {key byte, num of package ranks per DIMM (package ranks)} + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 5}, + {5, 6}, + {6, 7}, + {7, 8}, + }; + + // Extracting desired bits + constexpr size_t BYTE_INDEX = 12; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, PACKAGE_RANKS_START, PACKAGE_RANKS_LEN >(i_target, + iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(NUM_PACKAGE_RANKS_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check for Num Package Ranks Per DIMM") ); + + FAPI_INF("%s. Num Package Ranks per DIMM: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Rank Mix +/// @param[in] i_target dimm target +/// @param[out] o_value rank mix value from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 12 (bit 6) +/// @note Item JC-45-2220.01x +/// @note Page 23 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::rank_mix(const fapi2::Target& i_target, + uint8_t& o_value) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 12; + uint8_t l_field_bits = extract_spd_field< BYTE_INDEX, RANK_MIX_START, RANK_MIX_LEN >(i_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Find map value + constexpr size_t INVALID_VALUE = 2; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + (l_field_bits < INVALID_VALUE), + BYTE_INDEX, + l_field_bits, + "Failed check for Rank Mix") ); + + // Update output after check passes + o_value = l_field_bits; + + FAPI_INF("%s. Rank Mix: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decode CAS Latencies Supported +/// @param[in] i_target dimm target +/// @param[out] o_value bitmap of supported CAS latencies +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Bytes 20-23 +/// @note Item JC-45-2220.01x +/// @note Page 33-34 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::supported_cas_latencies(const fapi2::Target& i_target, + uint64_t& o_value) +{ + // Trace print in the front assists w/ debug + constexpr size_t FIRST_BYTE = 20; + uint8_t first_raw_byte = iv_spd_data[FIRST_BYTE]; + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + c_str(i_target), + FIRST_BYTE, + first_raw_byte); + + constexpr size_t SEC_BYTE = 21; + uint8_t sec_raw_byte = iv_spd_data[SEC_BYTE]; + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + c_str(i_target), + SEC_BYTE, + sec_raw_byte); + + constexpr size_t THIRD_BYTE = 22; + uint8_t third_raw_byte = iv_spd_data[THIRD_BYTE]; + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + c_str(i_target), + THIRD_BYTE, + third_raw_byte); + + constexpr size_t FOURTH_BYTE = 23; + uint8_t fourth_raw_byte = iv_spd_data[FOURTH_BYTE]; + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + c_str(i_target), + FOURTH_BYTE, + fourth_raw_byte); + + // Buffers used for bit manipulation + // Combine Bytes to create bitmap - right aligned + fapi2::buffer l_buffer; + + l_buffer.insertFromRight(first_raw_byte) + .insertFromRight(sec_raw_byte) + .insertFromRight(third_raw_byte) + .insertFromRight(fourth_raw_byte); + + // According to the JEDEC spec: + // Byte 23 bit 6 is reserved and must be coded as 0. + // Should we warn instead of fail because in last revision this was a reserved byte coded as 0x00 + constexpr size_t BIT_START = 33; // relative position of bit 6 in byte 23 relative to uint64_t + constexpr size_t BIT_LEN = 1; + + // Check for a valid value + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + !(l_buffer.getBit()), + FOURTH_BYTE, + fourth_raw_byte, + "Failed check on CAS latencies supported") ); + + // Update output value only if range check passes + o_value = l_buffer; + + FAPI_INF("%s. CAS latencies supported (bitmap): 0x%llX", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Minimum Write Recovery Time +/// @param[in] i_target dimm target +/// @param[out] o_value tWRmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) +/// @note Item JC-45-2220.01x +/// @note Page 40 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::min_write_recovery_time(const fapi2::Target& i_target, + int64_t& o_value) +{ + constexpr size_t BYTE_INDEX_MSN = 41; + uint8_t tWRmin_MSN = extract_spd_field< BYTE_INDEX_MSN, TWRMIN_MSN_START, TWRMIN_MSN_LEN >(i_target, iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 42; + uint8_t tWRmin_LSB = extract_spd_field< BYTE_INDEX_LSB, TWRMIN_LSB_START, TWRMIN_LSB_LEN >(i_target, iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSN_START = 52; + constexpr size_t MSN_LEN = 4; + constexpr size_t LSB_START = 56; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + l_buffer.insertFromRight( tWRmin_MSN ). + insertFromRight( tWRmin_LSB ); + + // Extract timing value from the buffer into an integral type + int64_t l_timing_val = l_buffer; + + // JEDEC spec limits for this timing value + // This value used to be reserved to 0 - before spec update + // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + + constexpr int64_t TIMING_LOWER_BOUND = 0; + constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC + + // best we can do? + // I had to combine parts from two different bytes. + // Chose one of them (byte 42) to for error printout of this decode + constexpr size_t ERROR_BYTE_INDEX = 42; + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + ERROR_BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Write Recovery Time (tWRmin) in MTB") ); + + // Update output only after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Write Recovery Time (tWRmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes Minimum Write to Read Time - Different Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tWRT_Smin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) +/// @note Item JC-45-2220.01x +/// @note Page 40 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::min_twtr_s(const fapi2::Target& i_target, + int64_t& o_value) +{ + constexpr size_t BYTE_INDEX_MSN = 43; + uint8_t tWRT_Smin_MSN = extract_spd_field< BYTE_INDEX_MSN, TWTRMIN_S_MSN_START, TWTRMIN_S_MSN_LEN >(i_target, + iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 44; + uint8_t tWRT_Smin_LSB = extract_spd_field< BYTE_INDEX_LSB, TWTRMIN_S_LSB_START, TWTRMIN_S_LSB_LEN >(i_target, + iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSN_START = 52; + constexpr size_t MSN_LEN = 4; + constexpr size_t LSB_START = 56; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + + l_buffer.insertFromRight( tWRT_Smin_MSN ) + .insertFromRight( tWRT_Smin_LSB ); + + // Extract timing value from the buffer into an integral type + int64_t l_timing_val = l_buffer; + + // JEDEC spec limits for this timing value + + // This value used to be reserved to 0 - before spec update - AAM + // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC + constexpr int64_t TIMING_LOWER_BOUND = 0; + constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC + + // best we can do? + // I had to combine parts from two different bytes. + // Chose one of them (byte 44) to for error printout of this decode + constexpr size_t ERROR_BYTE_INDEX = 44; + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + ERROR_BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Write to Read Time - Different Bank Group (tWRT_Smin) in MTB") ); + + // Update output only after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Write to Read Time - Different Bank Group (tWRT_Smin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes Minimum Write to Read Time - Same Bank Group +/// @param[in] i_target dimm target +/// @param[out] o_value tWRT_Lmin in MTB units +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) +/// @note Item JC-45-2220.01x +/// @note Page 46 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode decoder_v1_1::min_twtr_l(const fapi2::Target& i_target, + int64_t& o_value) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX_MSN = 43; + uint8_t tWRT_Lmin_MSN = extract_spd_field< BYTE_INDEX_MSN, TWTRMIN_L_MSN_START, TWTRMIN_L_MSN_LEN >(i_target, + iv_spd_data); + + constexpr size_t BYTE_INDEX_LSB = 45; + uint8_t tWRT_Lmin_LSB = extract_spd_field< BYTE_INDEX_LSB, TWTRMIN_L_LSB_START, TWTRMIN_L_LSB_LEN >(i_target, + iv_spd_data); + + // Combining bits to create timing value (in a buffer) + constexpr size_t MSN_START = 52; + constexpr size_t MSN_LEN = 4; + constexpr size_t LSB_START = 56; + constexpr size_t LSB_LEN = 8; + + fapi2::buffer l_buffer; + + l_buffer.insertFromRight( tWRT_Lmin_MSN ) + .insertFromRight( tWRT_Lmin_LSB ); + + // Extract timing value from the buffer into an integral type + int64_t l_timing_val = l_buffer; + + // JEDEC spec limits for this timing value + // This value used to be reserved to 0 - before spec update + //constexpr int64_t TIMING_LOWER_BOUND = 1 // from JEDEC + constexpr int64_t TIMING_LOWER_BOUND = 0; + constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC + + // best we can do? + // I had to combine parts from two different bytes. + // Chose one of them (byte 45) to for error printout of this decode + constexpr size_t ERROR_BYTE_INDEX = 45; + + FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, + (l_timing_val <= TIMING_UPPER_BOUND) && + (l_timing_val >= TIMING_LOWER_BOUND), + ERROR_BYTE_INDEX, + l_timing_val, + "Failed check on the Minimum Write to Read Time - Same Bank Group (tWRT_Lmin) in MTB") ); + + // Update output only after check passes + o_value = l_timing_val; + + FAPI_INF("%s. Minimum Write to Read Time - Same Bank Group (tWRT_Lmin) in MTB units: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function that returns Logical ranks in SDRAM type +/// @param[in] i_target dimm target +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode decoder_v1_1::sec_sdram_logical_ranks(const fapi2::Target& i_target, + uint8_t& o_logical_ranks) +{ + uint8_t l_signal_loading = 0; + uint8_t l_ranks_per_dimm = 0; + + FAPI_TRY( sec_sdram_signal_loading(i_target, l_signal_loading) ); + FAPI_TRY( num_package_ranks_per_dimm(i_target, l_ranks_per_dimm) ); + + if(l_signal_loading == spd::SINGLE_LOAD_STACK) + { + // For single-load-stack(3DS) the logical ranks per package ends up being the same as the die count. + uint8_t l_die_count = 0; + FAPI_TRY( sec_sdram_die_count(i_target, l_die_count) ); + + o_logical_ranks = l_ranks_per_dimm * l_die_count; + } + else + { + // Covers case for MONOLITHIC & MULTI_LOAD_STACK + // The die count isn't guaranteed to be 1 (e.g. SDP - 1 die package, DDP - 2 die package). + // Value of 1 is used for calculation purposes as defined by the SPD spec. + o_logical_ranks = l_ranks_per_dimm; + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Returns Logical ranks per DIMM +/// @param[in] i_target dimm target +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode decoder_v1_1::logical_ranks_per_dimm(const fapi2::Target& i_target, + uint8_t& o_logical_rank_per_dimm) +{ + uint8_t l_rank_mix = 0; + + FAPI_TRY( rank_mix(i_target, l_rank_mix) ); + + if(l_rank_mix == fapi2::ENUM_ATTR_EFF_DRAM_RANK_MIX_SYMMETRICAL) + { + FAPI_TRY( prim_sdram_logical_ranks(i_target, o_logical_rank_per_dimm) ); + } + else + { + // Rank mix is ASYMMETRICAL + uint8_t l_prim_logical_rank_per_dimm = 0; + uint8_t l_sec_logical_rank_per_dimm = 0; + + FAPI_TRY( prim_sdram_logical_ranks(i_target, l_prim_logical_rank_per_dimm) ); + FAPI_TRY( sec_sdram_logical_ranks(i_target, l_sec_logical_rank_per_dimm) ); + + o_logical_rank_per_dimm = l_prim_logical_rank_per_dimm + l_sec_logical_rank_per_dimm; + } + +fapi_try_exit: + return fapi2::current_err; +} + +}//spd +}// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder.H new file mode 100644 index 000000000..bb6cfacd5 --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder.H @@ -0,0 +1,796 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/// +/// @file rdimm_decoder.H +/// @brief RDIMM module SPD decoder declarations +/// +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Brian Silver +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_RDIMM_DECODER_H_ +#define _MSS_RDIMM_DECODER_H_ + +#include +#include + +namespace mss +{ +namespace spd +{ + +enum rdimm_byte_extract +{ + // Byte 128 + MODULE_NOM_HEIGHT_START = 3, + MODULE_NOM_HEIGHT_LEN = 5, + RAW_CARD_EXT_START = 0, + RAW_CARD_EXT_LEN = 3, + + // Byte 129 + FRONT_MODULE_THICKNESS_START = 4, + FRONT_MODULE_THICKNESS_LEN = 4, + BACK_MODULE_THICKNESS_START = 0, + BACK_MODULE_THICKNESS_LEN = 4, + + // Byte 130 + REF_RAW_CARD_START = 3, + REF_RAW_CARD_LEN = 5, + REF_RAW_CARD_REV_START = 1, + REF_RAW_CARD_REV_LEN = 2, + REF_RAW_CARD_EXT_START = 0, + REF_RAW_CARD_EXT_LEN = 1, + + // Byte 131 + REGS_USED_START = 6, + REGS_USED_LEN = 2, + ROWS_OF_DRAMS_START = 4, + ROWS_OF_DRAMS_LEN = 2, + + // Byte 132 + HEAT_SPREADER_CHAR_START = 1, + HEAT_SPREADER_CHAR_LEN = 7, + HEAT_SPREADER_SOL_START = 0, + HEAT_SPREADER_SOL_LEN = 1, + + // Byte 133 + CONTINUATION_CODES_START = 1, + CONTINUATION_CODES_LEN = 7, + + // Byte 134 - whole byte taken + // Byte 135 - whole byte taken + + // Byte 136 + ADDR_MAPPING_START = 7, + ADDR_MAPPING_LEN = 1, + + // Byte 137 + CKE_DRIVER_START = 6, + CKE_DRIVER_LEN = 2, + ODT_DRIVER_START = 4, + ODT_DRIVER_LEN = 2, + CA_DRIVER_START = 2, + CA_DRIVER_LEN = 2, + CS_DRIVER_START = 0, + CS_DRIVER_LEN = 2, + + // Byte 138 + YO_Y2_DRIVER_START = 6, + YO_Y2_DRIVER_LEN = 2, + Y1_Y3_DRIVER_START = 4, + Y1_Y3_DRIVER_LEN = 2, + +}; + +enum addr_mapping +{ + STANDARD = 0, + MIRRORED = 1, +}; + +/// +/// @class dimm_module_decoder +/// @brief Abstract class for RDIMM module SPD DRAM decoder +/// +class dimm_module_decoder +{ + public: + + /// + /// @brief default ctor + /// + dimm_module_decoder() = default; + + /// + /// @brief default dtor + /// + virtual ~dimm_module_decoder() = default; + + /// + /// @brief Decodes module nominal height max, in mm + /// @param[out] o_output height range encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 128 (Bits 4~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes raw card extension + /// @param[out] o_output raw card rev + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 128 (Bits 7~5) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode raw_card_extension(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes front module maximum thickness max, in mm + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 129 (Bits 3~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes back module maximum thickness max, in mm + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 129 (Bits 7~4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes reference raw card + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 130 (Bits 4~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 49 + /// + virtual fapi2::ReturnCode reference_raw_card(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes reference raw card revision + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 130 (Bits 6~5) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 49 + /// + virtual fapi2::ReturnCode reference_raw_card_rev(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes reference raw card extension + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 130 (Bit 7) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 49 + /// + virtual fapi2::ReturnCode reference_raw_card_extension(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes number of registers used on RDIMM + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 131 (Bits 1~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 50 + /// + virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes number of rows of DRAMs on RDIMM + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 131 (Bits 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 50 + /// + virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes heat spreader thermal characteristics + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCEawSS if okay + /// @note SPD Byte 132 (Bits 6~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode heat_spreader_thermal_char(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes heat spreader solution + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 132 (Bit 7) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes number of continuation codes + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 133 (bit 6~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes manufacturer ID code + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 133 (bit 6~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode manufacturer_id_code(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes register revision number + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 135 (bit 7~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes address mapping from register to dram + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 136 (bit 0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 52 + /// + virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes register output drive strength for CKE signal + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 1~0) + /// @note Item JC-45-2220.01x + /// @note Page 76 + /// @note DDR4 SPD Document Release 4 + /// + virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes register output drive strength for ODT signal + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 3~2) + /// @note Item JC-45-2220.01x + /// @note Page 76 + /// @note DDR4 SPD Document Release 4 + /// + virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes register output drive strength for command/address (CA) signal + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 5~4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 53 + /// + virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes register output drive strength for chip select (CS) signal + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 6~7) + /// @note Item JC-45-2220.01x + /// @note Page 76 + /// @note DDR4 SPD Document Release 4 + /// + virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes register output drive strength for clock (B side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (bit 1~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 53 + /// + virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes register output drive strength for clock (A side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (bit 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 53 + /// + virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } +}; + +/// +/// @class decoder +/// @brief RDIMM module SPD DRAM decoder for rev 1.0 +/// +class rdimm_decoder_v1_0 : public dimm_module_decoder +{ + public: + // deleted default ctor + rdimm_decoder_v1_0() = delete; + + /// + /// @brief ctor + /// @param[in] i_target dimm target + /// @param[in] i_spd_data vector DIMM SPD data + /// + rdimm_decoder_v1_0(const fapi2::Target& i_target, + const std::vector& i_spd_data): iv_target(i_target), iv_spd_data(i_spd_data) + {} + + /// + /// @brief default dtor + /// + virtual ~rdimm_decoder_v1_0() = default; + + /// + /// @brief Decodes module nominal height max, in mm + /// @param[out] o_output height range encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 128 (Bits 4~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) override; + + /// + /// @brief Decodes raw card extension + /// @param[out] o_output raw card rev + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 128 (Bits 7~5) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode raw_card_extension(uint8_t& o_output) override; + + /// + /// @brief Decodes front module maximum thickness max, in mm + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 129 (Bits 3~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) override; + + /// + /// @brief Decodes back module maximum thickness max, in mm + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 129 (Bits 7~4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) override; + + /// + /// @brief Decodes reference raw card + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 130 (Bits 4~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 49 + /// + virtual fapi2::ReturnCode reference_raw_card(uint8_t& o_output) override; + + /// + /// @brief Decodes reference raw card revision + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 130 (Bits 6~5) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 49 + /// + virtual fapi2::ReturnCode reference_raw_card_rev(uint8_t& o_output) override; + + /// + /// @brief Decodes reference raw card extension + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 130 (Bit 7) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 49 + /// + virtual fapi2::ReturnCode reference_raw_card_extension(uint8_t& o_output) override; + + /// + /// @brief Decodes number of registers used on RDIMM + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 131 (Bits 1~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 50 + /// + virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) override; + + /// + /// @brief Decodes number of rows of DRAMs on RDIMM + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 131 (Bits 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 50 + /// + virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) override; + + /// + /// @brief Decodes heat spreader thermal characteristics + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCEawSS if okay + /// @note SPD Byte 132 (Bits 6~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode heat_spreader_thermal_char(uint8_t& o_output) override; + + /// + /// @brief Decodes heat spreader solution + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 132 (Bit 7) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) override; + + /// + /// @brief Decodes number of continuation codes + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 133 (bit 6~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output) override; + + /// + /// @brief Decodes manufacturer ID code + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 133 (bit 6~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode manufacturer_id_code(uint8_t& o_output) override; + + /// + /// @brief Decodes register revision number + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 136 (bit 7~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 51 + /// + virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) override; + + /// + /// @brief Decodes address mapping from register to dram + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 136 (bit 0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 52 + /// + virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for CKE signal + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 1~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 53 + /// + virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for ODT signal + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 53 + /// + virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for command/address (CA) signal + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 5~4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 53 + /// + virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for chip select (CS) signal + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 6~7) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 53 + /// + virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for clock (B side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (bit 1~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 53 + /// + virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for clock (A side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (bit 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 53 + /// + virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) override; + + protected: + const fapi2::Target iv_target; + const std::vector iv_spd_data; + +};// rdimm_decoder_v1_0 + +/// +/// @class decoder +/// @brief RDIMM module SPD DRAM decoder for rev 1.1 +/// +class rdimm_decoder_v1_1 : public rdimm_decoder_v1_0 +{ + public: + + // deleted default ctor + rdimm_decoder_v1_1() = delete; + + /// + /// @brief ctor + /// @param[in] i_target dimm target + /// @param[in] i_spd_data vector DIMM SPD data + /// + rdimm_decoder_v1_1(const fapi2::Target& i_target, + const std::vector& i_spd_data): rdimm_decoder_v1_0(i_target, i_spd_data) + {} + + /// + /// @brief default dtor + /// + virtual ~rdimm_decoder_v1_1() = default; + + /// + /// @brief Decodes register output drive strength for CKE signal + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 1~0) + /// @note Item JC-45-2220.01x + /// @note Page 76 + /// @note DDR4 SPD Document Release 4 + /// + virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for ODT signal + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 3~2) + /// @note Item JC-45-2220.01x + /// @note Page 76 + /// @note DDR4 SPD Document Release 4 + /// + virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for chip select (CS) signal + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (bit 6~7) + /// @note Item JC-45-2220.01x + /// @note Page 76 + /// @note DDR4 SPD Document Release 4 + /// + virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for clock (B side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (bit 1~0) + /// @note Item JC-45-2220.01x + /// @note Page 76 + /// @note DDR4 SPD Document Release 4 + /// + virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for clock (A side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (bit 3~2) + /// @note Item JC-45-2220.01x + /// @note Page 76 + /// @note DDR4 SPD Document Release 4 + /// + virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) override; + +};//rdimm_decoder_v1_1 + +}// spd +}// mss + +#endif //_MSS_RDIMM_DECODER_H_ diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C new file mode 100644 index 000000000..ef9669c7e --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C @@ -0,0 +1,819 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file rdimm_decoder.C +/// @brief RDIMM module specific SPD decoder definitions +/// +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Brian Silver +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +// std lib +#include + +// fapi2 +#include + +// mss lib +#include +#include +#include +#include +#include + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_DIMM; + + +namespace mss +{ +namespace spd +{ + +///////////////////////// +// Member Method implementation +// For RDIMM module rev 1.0 +///////////////////////// + +/// +/// @brief Decodes module nominal height max, in mm +/// @param[out] o_output height range encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 128 (Bits 4~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 48 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::max_module_nominal_height(uint8_t& o_output) +{ + constexpr size_t BYTE_INDEX = 128; + uint8_t l_field_bits = extract_spd_field(iv_target, + iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b11111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for module nominal height max") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Max module nominal height: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes front module maximum thickness max, in mm +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 129 (Bits 3~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 48 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::front_module_max_thickness(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 129; + uint8_t l_field_bits = extract_spd_field + (iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b1111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for front module max thickness") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Front module max thickness: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes back module maximum thickness max, in mm +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 129 (Bits 7~4) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 48 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::back_module_max_thickness(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 129; + uint8_t l_field_bits = extract_spd_field(iv_target, + iv_spd_data); + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b1111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for back module max thickness") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Back module max thickness: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes raw card extension +/// @param[out] o_output raw card rev +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 128 (Bits 7~5) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 48 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::raw_card_extension(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 130; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for raw card extension") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Raw card extension: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes reference raw card +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 130 (Bits 4~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @Note Page 4.1.2.12 - 49 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::reference_raw_card(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 130; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b11111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for reference raw card") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Reference raw card: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes reference raw card revision +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 130 (Bits 6~5) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 49 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::reference_raw_card_rev(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 130; + uint8_t l_field_bits = extract_spd_field(iv_target, + iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b11; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for reference raw card revision") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Reference raw card revision: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes reference raw card extension +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 130 (Bit 7) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 49 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::reference_raw_card_extension(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 130; + uint8_t l_field_bits = extract_spd_field(iv_target, + iv_spd_data); + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 1; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for reference raw card extension") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Reference raw card extension: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes number of registers used on RDIMM +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 131 (Bits 1~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 50 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::num_registers_used(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 131; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b11; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for number of registers used on RDIMM ") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Number of registers used on RDIMM : %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes number of rows of DRAMs on RDIMM +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 131 (Bits 3~2) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 50 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::num_rows_of_drams(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 131; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b11; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for number of rows of DRAMs on RDIMM ") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Number of rows of DRAMs on RDIMM : %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes heat spreader thermal characteristics +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCEawSS if okay +/// @note SPD Byte 132 (Bits 6~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 51 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::heat_spreader_thermal_char(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 132; + uint8_t l_field_bits = extract_spd_field(iv_target, + iv_spd_data); + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 1; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for heat spreader thermal characteristics") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Heat spreader thermal characteristics: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes heat spreader solution +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 132 (Bit 7) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 51 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::heat_spreader_solution(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 132; + uint8_t l_field_bits = extract_spd_field(iv_target, + iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 1; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for heat spreader solution") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Heat spreader solution: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Decodes number of continuation codes +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 133 (bit 6~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 51 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::num_continuation_codes(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 133; + uint8_t l_field_bits = extract_spd_field(iv_target, + iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 10; // JEP106AS + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BYTE_INDEX, + l_field_bits, + "Failed bound check for number of continuation codes") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Number of continuation codes: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes manufacturer ID code +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 134 (bit 7~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 51 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::manufacturer_id_code(uint8_t& o_output) +{ + constexpr size_t BYTE_INDEX = 134; + uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(iv_target), + BYTE_INDEX, + l_raw_byte); + + o_output = l_raw_byte; + + FAPI_INF("%s. Register revision number: %d", + mss::c_str(iv_target), + o_output); + + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decodes register revision number +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 135 (bit 7~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 51 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::register_rev_num(uint8_t& o_output) +{ + constexpr size_t BYTE_INDEX = 135; + uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(iv_target), + BYTE_INDEX, + l_raw_byte); + + o_output = l_raw_byte; + + FAPI_INF("%s. Register revision number: %d", + mss::c_str(iv_target), + o_output); + + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decodes address mapping from register to dram +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 136 (bit 0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 52 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::register_to_dram_addr_mapping(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 136; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 0b11; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + BYTE_INDEX, + l_field_bits, + "Failed bound check for to register to dram addr mapping") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Address mapping from register to dram: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for CKE signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 1~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 53 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::cke_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 137; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 2; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + BYTE_INDEX, + l_field_bits, + "Failed bounds check for Register Output Driver for CKE") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CKE: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for ODT signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 3~2) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 53 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::odt_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 137; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 2; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + BYTE_INDEX, + l_field_bits, + "Failed bounds check for Register Output Driver for ODT") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for ODT: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for command/address (CA) signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 5~4) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 53 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::ca_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 137; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t INVALID_VAL = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < INVALID_VAL, // extract sanity check + BYTE_INDEX, + l_field_bits, + "Failed bounds check for Register Output Driver for CA") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CA: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for chip select (CS) signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 6~7) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 53 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::cs_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 137; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 2; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + BYTE_INDEX, + l_field_bits, + "Failed bounds check for Register Output Driver for CS") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CS: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for clock (B side) +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (bit 1~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 53 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::b_side_clk_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 138; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 2; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + BYTE_INDEX, + l_field_bits, + "Failed bounds check for Register Output Driver for clock (Y0,Y2)") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for clock (A side) +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (bit 3~2) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12 - 53 +/// +fapi2::ReturnCode rdimm_decoder_v1_0::a_side_clk_output_driver(uint8_t& o_output) +{ + // Trace in the front assists w/ debug + constexpr size_t BYTE_INDEX = 138; + + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 2; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, + BYTE_INDEX, + l_field_bits, + "Failed bounds check for Register Output Driver for clock (Y1,Y3)") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +}//spd namespace +}// mss namespace diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_1.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_1.C new file mode 100644 index 000000000..d4e81228c --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_1.C @@ -0,0 +1,236 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_1.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +// std lib +#include + +// fapi2 +#include + +// mss lib +#include +#include +#include +#include +#include + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_DIMM; + + +namespace mss +{ +namespace spd +{ + +///////////////////////// +// Member Method implementation +// For RDIMM module rev 1.1 +///////////////////////// + +/// +/// @brief Decodes register output drive strength for CKE signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 1~0) +/// @note Item JC-45-2220.01x +/// @note Page 76 +/// @note DDR4 SPD Document Release 4 +/// +fapi2::ReturnCode rdimm_decoder_v1_1::cke_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE = 137; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This really just checks my extract gives me a valid value + constexpr size_t MAX_VALID_VALUE = 0b11; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, // extract sanity check + BYTE, + l_field_bits, + "Failed bounds check for Register Output Driver for CKE") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CKE: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for ODT signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 3~2) +/// @note Item JC-45-2220.01x +/// @note Page 76 +/// @note DDR4 SPD Document Release 4 +/// +fapi2::ReturnCode rdimm_decoder_v1_1::odt_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE = 137; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This really just checks my extract gives me a valid value + constexpr size_t MAX_VALID_VALUE = 0b11; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, // extract sanity check + BYTE, + l_field_bits, + "Failed bounds check for Register Output Driver for ODT") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for ODT: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for chip select (CS) signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 6~7) +/// @note Item JC-45-2220.01x +/// @note Page 76 +/// @note DDR4 SPD Document Release 4 +/// +fapi2::ReturnCode rdimm_decoder_v1_1::cs_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE = 137; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This really just checks my extract gives me a valid value + constexpr size_t MAX_VALID_VALUE = 0b11; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, // extract sanity check + BYTE, + l_field_bits, + "Failed bounds check for Register Output Driver for chip select") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CS: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for clock (B side) +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (bit 1~0) +/// @note Item JC-45-2220.01x +/// @note Page 76 +/// @note DDR4 SPD Document Release 4 +/// +fapi2::ReturnCode rdimm_decoder_v1_1::b_side_clk_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE = 138; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This really just checks my extract gives me a valid value + constexpr size_t MAX_VALID_VAL = 2; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + BYTE, + l_field_bits, + "Failed bounds check for Register Output Driver for clock (Y0,Y2)") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for clock (A side) +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (bit 3~2) +/// @note Item JC-45-2220.01x +/// @note Page 76 +/// @note DDR4 SPD Document Release 4 +/// +fapi2::ReturnCode rdimm_decoder_v1_1::a_side_clk_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE = 138; + uint8_t l_field_bits = extract_spd_field(iv_target, iv_spd_data); + + FAPI_INF("Field_Bits value: %d", l_field_bits); + + // This really just checks my extract gives me a valid value + constexpr size_t MAX_VALID_VAL = 2; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + BYTE, + l_field_bits, + "Failed bounds check for Register Output Driver for clock (Y1,Y3)") ); + + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +}//spd +}// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C deleted file mode 100644 index 201baef07..000000000 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C +++ /dev/null @@ -1,4155 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - - -/// -/// @file spd_decoder.C -/// @brief SPD decoder definitions -/// -// *HWP HWP Owner: Andre Marin -// *HWP HWP Backup: Brian Silver -// *HWP Team: Memory -// *HWP Level: 2 -// *HWP Consumed by: HB:FSP -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -using fapi2::TARGET_TYPE_MCBIST; -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_MCS; -using fapi2::TARGET_TYPE_DIMM; - - -namespace mss -{ -namespace spd -{ - -// ========================================================= -// Byte 0 maps -// Item JC-45-2220.01x -// Page 14 -// DDR4 SPD Document Release 3 -// Byte 0 (0x000): Number of Bytes Used / Number of Bytes in SPD Device -// ========================================================= -static const std::vector > BYTES_USED_MAP = -{ - //{key byte, number of used bytes} - {1, 128}, - {2, 256}, - {3, 384}, - {4, 512} -}; - - -static const std::vector > BYTES_TOTAL_MAP = -{ - //{key byte, number of total bytes} - {1, 256}, - {2, 512} -}; - -// ========================================================= -// Byte 2 maps -// Item JC-45-2220.01x -// Page 16 -// DDR4 SPD Document Release 3 -// Byte 2 (0x002): Key Byte / DRAM Device Type -// ========================================================= -static const std::vector > DRAM_GEN_MAP = -{ - //{key value, dram gen} - {0x0B, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR3}, - {0x0C, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4} - // Other key bytes reserved or not supported -}; - -// ========================================================= -// Byte 3 maps -// Item JC-45-2220.01x -// Page 17 -// DDR4 SPD Document Release 3 -// Byte 3 (0x003): Key Byte / Module Type -// ========================================================= -static const std::vector > BASE_MODULE_TYPE_MAP = -{ - //{key byte, dimm type} - {1, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM}, - {2, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM}, - {4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM} -}; - -static const std::vector > HYBRID_MEDIA_MAP = -{ - //{key, value} - {0, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE}, - {1, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM} -}; - -static const std::vector > HYBRID_MAP = -{ - //{key byte, value} - {0, fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID}, - {1, fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID} -}; - -// ========================================================= -// Byte 4 maps -// Item JC-45-2220.01x -// Page 18 -// DDR4 SPD Document Release 3 -// Byte 4 (0x004): SDRAM Density and Banks -// ========================================================= -static const std::vector > SDRAM_DENSITY_MAP = -{ - // {key byte, capacity in GBs} - {2, 1}, - {3, 2}, - {4, 4}, - {5, 8}, - {6, 16}, - {7, 32}, - {8, 12}, - {12, 24} -}; - -static const std::vector > BANK_ADDR_BITS_MAP = -{ - // {key byte, number of bank address bits} - {0, 2}, - {1, 3} -}; - -static const std::vector > BANK_GROUP_BITS_MAP = -{ - // {key byte, number of bank groups bits} - {0, 0}, - {1, 1}, - {2, 2} -}; - - -// ========================================================= -// Byte 5 maps -// Item JC-45-2220.01x -// Page 18 -// DDR4 SPD Document Release 3 -// Byte 5 (0x005): SDRAM Addressing -// ========================================================= -static const std::vector > COLUMN_ADDRESS_BITS_MAP = -{ - //{key byte,col address bits} - {0, 9}, - {1, 10}, - {2, 11}, - {3, 12} -}; - -static const std::vector > ROW_ADDRESS_BITS_MAP = -{ - //{key byte,row address bits} - {0, 12}, - {1, 13}, - {2, 14}, - {3, 15}, - {4, 16}, - {5, 17}, - {6, 18} -}; - -// ========================================================= -// Byte 6 maps -// Item JC-45-2220.01x -// Page 19 -// DDR4 SPD Document Release 3 -// Byte 6 (0x006): Primary SDRAM Package Type -// ========================================================= -static const std::vector > PRIM_SIGNAL_LOADING_MAP = -{ - // {key byte, signal loading} - {0, UNSPECIFIED}, - {1, MULTI_LOAD_STACK}, - {2, SINGLE_LOAD_STACK} -}; - -static const std::vector > PRIM_DIE_COUNT_MAP = -{ - // {key byte, number of die} - {0, 1}, - {1, 2}, - {2, 3}, - {3, 4}, - {4, 5}, - {5, 6}, - {6, 7}, - {7, 8} - -}; - -static const std::vector > PRIM_PACKAGE_TYPE_MAP = -{ - // {key byte, value} - {0, MONOLITHIC}, - {1, NON_MONOLITHIC} -}; - -// ========================================================= -// Byte 7 maps -// Item JC-45-2220.01x -// Page 20 -// DDR4 SPD Document Release 3 -// Byte 7 (0x007): SDRAM Optional Features -// ========================================================= -static const std::vector > MAC_MAP = -{ - // {key byte, maximum activate count} - {0, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNTESTED}, - {1, fapi2::ENUM_ATTR_EFF_DRAM_MAC_700K}, - {2, fapi2::ENUM_ATTR_EFF_DRAM_MAC_600K}, - {3, fapi2::ENUM_ATTR_EFF_DRAM_MAC_500K}, - {4, fapi2::ENUM_ATTR_EFF_DRAM_MAC_400K}, - {5, fapi2::ENUM_ATTR_EFF_DRAM_MAC_300K}, - {6, fapi2::ENUM_ATTR_EFF_DRAM_MAC_200K}, - {8, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNLIMITED} -}; - -// Multiplier with tREFI is not taken into account here -static const std::vector > TMAW_MAP = -{ - // {key byte, tMAW multiplier} - {0, 8192}, - {1, 4096}, - {2, 2048} -}; - -// ========================================================= -// Byte 9 maps -// Item JC-45-2220.01x -// Page 21 -// DDR4 SPD Document Release 3 -// Byte 9 (0x009): Other SDRAM Optional Features -// ========================================================= -static const std::vector > SOFT_PPR_MAP = -{ - // {key byte, value } - {0, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED}, - {1, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED} -}; - -static const std::vector > PPR_MAP = -{ - // {key byte, value } - {0, fapi2::ENUM_ATTR_EFF_DRAM_PPR_NOT_SUPPORTED}, - {1, fapi2::ENUM_ATTR_EFF_DRAM_PPR_SUPPORTED} -}; - -// ========================================================= -// Byte 10 maps -// Item JC-45-2220.01x -// Page 21-22 -// DDR4 SPD Document Release 3 -// Byte 10 (0x00A): Secondary SDRAM Package Type -// ========================================================= -static const std::vector > SEC_SIGNAL_LOADING_MAP = -{ - // {key byte, signal loading} - {0, UNSPECIFIED}, - {1, MULTI_LOAD_STACK}, - {2, SINGLE_LOAD_STACK} -}; - -static const std::vector > SEC_DIE_COUNT_MAP = -{ - // {key byte, number of die} - {0, 1}, - {1, 2}, - {2, 3}, - {3, 4}, - {4, 5}, - {5, 6}, - {6, 7}, - {7, 8} - -}; - -static const std::vector > SEC_PACKAGE_TYPE_MAP = -{ - // {key byte, value } - {0, MONOLITHIC}, - {1, NON_MONOLITHIC} -}; - - -// ========================================================= -// Byte 11 maps -// Item JC-45-2220.01x -// Page 22-23 -// DDR4 SPD Document Release 3 -// Byte 11 (0x00B): Modle Nominal Voltage -// ========================================================= -static const std::vector > ENDURANT_MAP = -{ - // {key byte, value } - {0, NOT_ENDURANT}, - {1, ENDURANT} -}; - -static const std::vector > OPERABLE_MAP = -{ - // {key byte, value } - {0, NOT_OPERABLE }, - {1, OPERABLE} -}; - -// ========================================================= -// Byte 12 maps -// Item JC-45-2220.01x -// Page 23 -// DDR4 SPD Document Release 3 -// Byte 12 (0x00C): Module Organization -// ========================================================= -static const std::vector > DEVICE_WIDTH_MAP = -{ - // {key byte, device width (bits)} - {0, 4}, - {1, 8}, - {2, 16}, - {3, 32}, - // All others reserved -}; - -static const std::vector > NUM_PACKAGE_RANKS_MAP = -{ - // {key byte, num of package ranks per DIMM (package ranks)} - {0, 1}, - {1, 2}, - {2, 3}, - {3, 4}, - {4, 5}, - {5, 6}, - {6, 7}, - {7, 8} -}; - -// ========================================================= -// Byte 13 maps -// Item JC-45-2220.01x -// Page 27 -// DDR4 SPD Document Release 3 -// Byte 13 (0x00D): Module Memory Bus Width -// ========================================================= -static const std::vector > BUS_WIDTH_MAP = -{ - // {key byte, bus width (in bits) - {0, 8}, - {1, 16}, - {2, 32}, - {3, 64} - // All others reserved -}; - -static const std::vector > BUS_WIDTH_EXT_MAP = -{ - {0, 0}, - {1, 8} - // All others reserved -}; - -// ========================================================= -// Byte 17 maps -// Item JC-45-2220.01x -// Page 29 -// DDR4 SPD Document Release 3 -// Byte 17 (0x011): Timebases -// ========================================================= -// Created a maps of a single value in case mapping expands to more values -static const std::vector > MEDIUM_TIMEBASE_MAP = -{ - // {key byte, medium timebase (in picoseconds) - {0, 125} - // All others reserved -}; - -static const std::vector > FINE_TIMEBASE_MAP = -{ - // {key byte, fine timebase (in picoseconds) - {0, 1} - // All others reserved -}; - - -///////////////////////// -// Non-member function implementations -///////////////////////// -// -// Why not static member functions? Literature states -// that static member functions may reduce class -// encapsulation, hence, non-member functions are preferred. -// But I can be convinced otherwise - AAM -///////////////////////// - -/// -/// @brief Decodes SPD Revision encoding level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value encoding revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (3~0). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_encoding_level(const fapi2::Target& i_target, - const std::vector& i_spd_data, - uint8_t& o_value) -{ - // Buffer used for bit manipulation - constexpr size_t BYTE_INDEX = 1; - uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; - fapi2::buffer l_buffer(l_raw_byte); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - l_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check that value is valid - constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - (l_field_bits != UNDEFINED), - BYTE_INDEX, - l_raw_byte, - "Failed check on SPD rev encoding level") ); - - // Update output only after check passes - o_value = l_field_bits; - - // Print decoded info - FAPI_DBG("%s. Rev - Encoding Level : %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SPD Revision additions level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value additions revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (bits 7~4). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_additions_level(const fapi2::Target& i_target, - const std::vector& i_spd_data, - uint8_t& o_value) -{ - // Buffer used for bit manipulation - constexpr size_t BYTE_INDEX = 1; - uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; - fapi2::buffer l_buffer(l_raw_byte); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - l_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check that value is valid - constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - (l_field_bits != UNDEFINED), - BYTE_INDEX, - l_raw_byte, - "Failed check on SPD rev encoding level") ); - - // Update output only after check passes - o_value = l_field_bits; - - // Print decoded info - FAPI_DBG("%s. Rev - Additions Level : %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes base module type (DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value base module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode base_module_type(const fapi2::Target& i_target, - const std::vector& i_spd_data, - uint8_t& o_value) -{ - // Buffer used for bit manipulation - constexpr size_t BYTE_INDEX = 3; - uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; - fapi2::buffer l_spd_buffer(l_raw_byte); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX", - c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check that value is valid - bool l_is_val_found = find_value_from_key(BASE_MODULE_TYPE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check on Base Module Type") ); - - FAPI_DBG("%s. Base Module Type: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes DRAM Device Type -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value dram device type enumeration -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 2 -/// @note Item JC-45-2220.01x -/// @note Page 16 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode dram_device_type(const fapi2::Target& i_target, - const std::vector& i_spd_data, - uint8_t& o_value) -{ - constexpr size_t BYTE_INDEX = 2; - uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(DRAM_GEN_MAP, l_raw_byte, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_raw_byte, - "Failed check on SPD dram device type") ); - // Print decoded info - FAPI_DBG("%s Device type : %d", - c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Object factory to select correct decoder -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -fapi2::ReturnCode factory(const fapi2::Target& i_target, - const std::vector& i_spd_data, - std::shared_ptr& o_fact_obj) -{ - uint8_t l_dimm_type = 0; - uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - uint8_t l_dram_gen = 0; - uint8_t l_dram_gen_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - uint8_t l_encoding_rev = 0; - uint8_t l_additions_rev = 0; - - const auto l_mcs = mss::find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - if( i_spd_data.empty() ) - { - // This won't work with no data - return fapi2::FAPI2_RC_INVALID_PARAMETER; - } - - // Get dimm type & set attribute (needed by c_str) - FAPI_TRY( base_module_type(i_target, i_spd_data, l_dimm_type), - "Failed to find base module type" ); - FAPI_TRY( eff_dimm_type(l_mcs, &l_dimm_types_mcs[0][0]) ); - - l_dimm_types_mcs[l_port_num][l_dimm_num] = l_dimm_type; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_TYPE, l_mcs, l_dimm_types_mcs) ); - - // Get dram generation & set attribute (needed by c_str) - FAPI_TRY( eff_dram_gen(l_mcs, &l_dram_gen_mcs[0][0]) ); - FAPI_TRY( dram_device_type(i_target, i_spd_data, l_dram_gen), - "Failed to find base module type" ); - - l_dram_gen_mcs[l_port_num][l_dimm_num] = l_dram_gen; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, l_mcs, l_dram_gen_mcs) ); - - // Get revision levels - FAPI_TRY( rev_encoding_level(i_target, i_spd_data, l_encoding_rev), - "Failed to find encoding level" ); - FAPI_TRY( rev_additions_level(i_target, i_spd_data, l_additions_rev), - "Failed to find additons level" ); - - // Get decoder object needed for current dimm type and spd rev - switch(l_dimm_type) - { - // Each dimm type rev is independent - case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM: - - // SPD Revision format #.# - // 1st # = encoding level - // 2nd # = additions level - switch(l_encoding_rev) - { - case 1: - switch(l_additions_rev) - { - case 0: - case 1: - // Rev 1.0 or Rev 1.1 - o_fact_obj = std::make_shared(); - break; - - default: - FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, - l_dimm_type, - l_encoding_rev, - l_additions_rev, - "Additions Level Unsupported!") ); - break; - }//end additions - - break; - - default: - FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, - l_dimm_type, - l_encoding_rev, - l_additions_rev, - "Encoding Level Unsupported!") ); - break; - }// end encodings - - break; - - default: - FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, - l_dimm_type, - l_encoding_rev, - l_additions_rev, - "DIMM Type Unsupported!") ); - break; - - } // end dimm type - - // If we get here than a correct object reference obtained - // Save off SPD data - o_fact_obj->iv_spd_data = i_spd_data; - -fapi_try_exit: - return fapi2::current_err; - -} - - -/// -/// @brief Creates factory object & SPD data caches -/// @param[in] i_target controller target -/// @param[out] o_factory_caches map of factory objects with a dimm position key -/// @return FAPI2_RC_SUCCESS if okay -/// @note This specialization is suited for creating a cache with platform -/// SPD data. -/// -template<> -fapi2::ReturnCode populate_decoder_caches( const fapi2::Target& i_target, - std::map >& o_factory_caches, - const std::shared_ptr& i_pDecoder) -{ - // Input decoder for this version of populating cache would get overriden - // so I don't bother with it here - std::shared_ptr l_pDecoder; - - for( const auto& l_mca : i_target.getChildren() ) - { - for( const auto& l_dimm : l_mca.getChildren() ) - { - size_t l_size = 0; - FAPI_TRY( fapi2::getSPD(l_dimm, nullptr, l_size) ); - - { - // "Container" for SPD data - std::vector l_spd; - l_spd.resize(l_size); - - // Retrive SPD data - FAPI_TRY( fapi2::getSPD(l_dimm, l_spd.data(), l_size)) ; - - // Retrieve factory object instance & populate spd data for that instance - FAPI_TRY( factory(l_dimm, l_spd, l_pDecoder) ); - - // Populate spd caches maps based on dimm pos - o_factory_caches.emplace(std::make_pair(mss::pos(l_dimm), l_pDecoder)); - } - - }// end dimm - }// end mca - - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Creates factory object & SPD data caches -/// @param[in] i_target the dimm target -/// @param[out] o_factory_caches map of factory objects with a dimm position key -/// @return FAPI2_RC_SUCCESS if okay -/// @note This specialization is suited for creating a cache with custom -/// SPD data (e.g. testing custom SPD). -/// -template<> -fapi2::ReturnCode populate_decoder_caches( const fapi2::Target& i_target, - std::map >& o_factory_caches, - const std::shared_ptr& i_pDecoder) -{ - if(i_pDecoder == nullptr) - { - // This won't work w/a null parameter - return fapi2::FAPI2_RC_INVALID_PARAMETER; - } - - // This shouldn't be null so there is a specific decoder we are wanting to populate - std::shared_ptr l_pDecoder(i_pDecoder); - - // Custom decoder provided (usually done for testing) - // Populate custom spd caches maps one dimm at a time - o_factory_caches.emplace(std::make_pair( mss::pos(i_target), l_pDecoder) ); - - // TK - else what do we want here - return fapi2::FAPI2_RC_SUCCESS; -} - -///////////////////////// -// Member Method implementation -///////////////////////// - -/// -/// @brief Decodes number of used SPD bytes -/// @param[in] i_target dimm target -/// @param[out] o_value number of SPD bytes used -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 0 bits(0~3) -/// @note Item JC-45-2220.01x -/// @note Page 14 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::number_of_used_bytes(const fapi2::Target& i_target, - uint16_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 0; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(BYTES_USED_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check on SPD used bytes") ); - - FAPI_DBG("%s. Bytes Used: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes total number of SPD bytes -/// @param[in] i_target dimm target -/// @param[out] o_value number of total SPD bytes -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 0 (bits 4~6) -/// @note Item JC-45-2220.01x -/// @note Page 14 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::number_of_total_bytes(const fapi2::Target& i_target, - uint16_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 0; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(BYTES_TOTAL_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check on SPD total bytes") ); - - FAPI_DBG("%s. Total Bytes: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes hybrid media field from SPD -/// @param[in] i_target -/// @param[out] o_value enum representing hybrid memory type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 4~6) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::hybrid_media(const fapi2::Target& i_target, - uint8_t& o_value) - -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 3; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(HYBRID_MEDIA_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check on Hybrid Media type") ); - - FAPI_DBG("%s. Hybrid Media: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes hybrid field from SPD -/// @param[in] i_target -/// @param[out] o_value enum representing if module is hybrid -/// @return fapi2::ReturnCode -/// @note Decodes SPD Byte 3 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::hybrid(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 3; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - mss::find_value_from_key(HYBRID_MAP, l_field_bits, o_value), - BYTE_INDEX, - l_field_bits, - "Failed check on hybrid field") ); - - FAPI_DBG("%s. Hybrid: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM density from SPD -/// @param[in] i_target dimm target -/// @param[out] o_value SDRAM density in GBs -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 4 (bits 0~3) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::sdram_density(const fapi2::Target& i_target, - uint8_t& o_value) - -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 4; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(iv_spd_data[BYTE_INDEX]); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - bool l_is_val_found = mss::find_value_from_key(SDRAM_DENSITY_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for SPD DRAM capacity") ); - FAPI_DBG("%s. SDRAM density: %d Gb", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of SDRAM banks from SPD -/// @param[in] i_target dimm target -/// @param[out] o_value Number of SDRAM banks -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 4 (bits 4~5) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::banks(const fapi2::Target& i_target, - uint8_t& o_value) - -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 4; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(iv_spd_data[BYTE_INDEX]); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - mss::find_value_from_key(BANK_ADDR_BITS_MAP, l_field_bits, o_value), - BYTE_INDEX, - l_field_bits, - "Failed check for SPD DRAM banks") ); - - FAPI_DBG("%s. Banks: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of SDRAM bank groups from SPD -/// @param[in] i_target dimm target -/// @param[out] o_value Number of SDRAM bank groups -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 4 (bits 6~7) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::bank_groups(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 4; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(iv_spd_data[BYTE_INDEX]); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - bool l_is_val_found = mss::find_value_from_key(BANK_GROUP_BITS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for SPD DRAM bank groups") ); - FAPI_DBG("%s. Bank Groups: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of SDRAM column address bits -/// @param[in] i_target dimm target -/// @param[out] o_value number of column address bits -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 5 (bits 2~0) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::column_address_bits(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 5; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(iv_spd_data[BYTE_INDEX]); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - bool l_is_val_found = mss::find_value_from_key(COLUMN_ADDRESS_BITS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for SDRAM Column Address Bits") ); - - FAPI_DBG("%s. Number of Column Address Bits: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of SDRAM row address bits -/// @param[in] i_target dimm target -/// @param[out] o_value number of row address bits -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 5 (bits 5~3) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::row_address_bits(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 5; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(iv_spd_data[BYTE_INDEX]); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - bool l_is_val_found = mss::find_value_from_key(ROW_ADDRESS_BITS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for SDRAM Row Address Bits") ); - - FAPI_DBG("%s. Number of Row Address Bits: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes Primary SDRAM signal loading -/// @param[in] i_target dimm target -/// @param[out] o_value enum representing signal loading type -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 6 (bits 1~0) -/// @note Item JC-45-2220.01x -/// @note Page 19 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::prim_sdram_signal_loading(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 6; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(PRIM_SIGNAL_LOADING_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Primary SDRAM Signal Loading") ); - - FAPI_DBG("%s. Primary SDRAM Signal Loading: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Primary SDRAM die count -/// @param[in] i_target dimm target -/// @param[out] o_value die count -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 6 (bits 6~4) -/// @note Item JC-45-2220.01x -/// @note Page 19 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::prim_sdram_die_count(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 6; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(PRIM_DIE_COUNT_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for SDRAM Row Address Bits") ); - - FAPI_DBG("%s. Number of Row Address Bits: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Primary SDRAM package type -/// @param[in] i_target dimm target -/// @param[out] o_value enum representing package type -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 6 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 19 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::prim_sdram_package_type(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 6; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(PRIM_PACKAGE_TYPE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for SDRAM Row Address Bits") ); - - FAPI_DBG("%s. Number of Row Address Bits: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decode SDRAM Maximum activate count -/// @param[in] i_target dimm target -/// @param[out] o_value enum representing max activate count -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 7 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 20 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::maximum_activate_count(const fapi2::Target& i_target, - uint32_t& o_value) -{ - // Buffer used for bit manipulation - constexpr size_t BYTE_INDEX = 7; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(MAC_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for SDRAM Maximum Active Count (MAC)") ); - - FAPI_DBG("%s. Maximum Active Count (MAC): %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point -/// @param[in] i_target dimm target -/// @param[out] o_value max activate window multiplier -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 7 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 20 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::maximum_activate_window_multiplier(const fapi2::Target& i_target, - uint32_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 7; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(TMAW_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Maximum Active Window (tMAW)") ); - - FAPI_DBG("%s. Maximum Active Window multiplier: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Soft post package repair (soft PPR) -/// @param[in] i_target dimm target -/// @param[out] o_value enum representing if soft PPR is supported -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 9 (bit 5) -/// @note Item JC-45-2220.01x -/// @note Page 21 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::soft_post_package_repair(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 9; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(SOFT_PPR_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Soft PPR") ); - - FAPI_DBG("%s. Soft Post Package Repair (Soft PPR): %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Post package repair (PPR) -/// @param[in] i_target dimm target -/// @param[out] o_value enum representing if (hard) PPR is supported -/// @return fapi2::ReturnCode -/// @note SPD Byte 9 (bits 7~6) -/// @note Item JC-45-2220.01x -/// @note Page 21 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::post_package_repair(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Buffer used for bit manipulation - constexpr size_t BYTE_INDEX = 9; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - fapi2::buffer l_spd_buffer(l_raw_byte); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(PPR_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for PPR") ); - - FAPI_DBG("%s. Post Package Repair (PPR): %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes Secondary SDRAM signal loading -/// @param[in] i_target dimm target -/// @param[out] o_value enum representing signal loading type -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 10 (bits 1~0) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::sec_sdram_signal_loading(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 10; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(SEC_SIGNAL_LOADING_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for SDRAM Row Address Bits") ); - - FAPI_DBG("%s. Number of Row Address Bits: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Secondary DRAM Density Ratio -/// @param[in] i_target dimm target -/// @param[out] o_value raw bits from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 10 (bits 3~2) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::sec_dram_density_ratio(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Buffer used for bit manipulation - constexpr size_t BYTE_INDEX = 10; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - constexpr size_t UNDEFINED = 3; // JEDEC map doesn't go beyond 3 - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, - l_field_bits < UNDEFINED, - BYTE_INDEX, - l_field_bits, - "Failed check for DRAM Density Ratio") ); - - FAPI_DBG("%s. DRAM Density Ratio: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes Secondary SDRAM die count -/// @param[in] i_target dimm target -/// @param[out] o_value die count -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 10 (bits 6~4) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::sec_sdram_die_count(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Buffer used for bit manipulation - constexpr size_t BYTE_INDEX = 5; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - fapi2::buffer l_spd_buffer(l_raw_byte); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(SEC_DIE_COUNT_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Secondary Die Count") ); - - FAPI_DBG("%s. Secondary Die Count: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Secondary SDRAM package type -/// @param[in] i_target dimm target -/// @param[out] o_value enum representing package type -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 10 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::sec_sdram_package_type(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Buffer used for bit manipulation - constexpr size_t BYTE_INDEX = 5; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(SEC_PACKAGE_TYPE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Secondary Package Type") ); - - FAPI_DBG("%s. Secondary Package Type: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decode Module Nominal Voltage, VDD -/// @param[in] i_target dimm target -/// @param[out] o_value enum representing if 1.2V is operable -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 11 (bit 0) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::operable_nominal_voltage(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 11; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(OPERABLE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Operable nominal voltage") ); - - FAPI_DBG("%s. Operable: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Module Nominal Voltage, VDD -/// @param[in] i_target dimm target -/// @param[out] o_value enum representing if 1.2V is endurant -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 11 (bit 1) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::endurant_nominal_voltage(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 11; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(ENDURANT_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Endurant nominal voltage") ); - - FAPI_DBG("%s. Endurant: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM device width -/// @param[in] i_target dimm target -/// @param[out] o_value device width in bits -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 12 (bits 2~0) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::device_width(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 12; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - fapi2::buffer l_spd_buffer(l_raw_byte); - uint8_t l_field_bits = 0; - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(DEVICE_WIDTH_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Device Width") ); - - FAPI_DBG("%s. Device Width: %d bits", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes number of package ranks per DIMM -/// @param[in] i_target dimm target -/// @param[out] o_value number of package ranks per DIMM -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 12 (bits 5~3) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::num_package_ranks_per_dimm(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 12; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - fapi2::buffer l_spd_buffer(l_raw_byte); - uint8_t l_field_bits = 0; - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(NUM_PACKAGE_RANKS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Num Package Ranks Per DIMM") ); - - FAPI_DBG("%s. Num Package Ranks per DIMM: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Rank Mix -/// @param[in] i_target dimm target -/// @param[out] o_value rank mix value from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 12 (bit 6) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::rank_mix(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 12; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - constexpr size_t INVALID_VALUE = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - (l_field_bits < INVALID_VALUE), - BYTE_INDEX, - l_field_bits, - "Failed check for Rank Mix") ); - - // Update output after check passes - o_value = l_field_bits; - - FAPI_DBG("%s. Rank Mix: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes primary bus width -/// @param[in] i_target dimm target -/// @param[out] o_value primary bus width in bits -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 13 (bits 2~0) -/// @note Item JC-45-2220.01x -/// @note Page 27 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::prim_bus_width(const fapi2::Target& i_target, - uint8_t& o_value) -{ - - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 13; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - fapi2::buffer l_spd_buffer(l_raw_byte); - uint8_t l_field_bits = 0; - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(BUS_WIDTH_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Primary Bus Width") ); - - FAPI_DBG("%s. Primary Bus Width: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes bus width extension -/// @param[in] i_target dimm target -/// @param[out] o_value bus width extension in bits -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 13 (bits 2~0) -/// @note Item JC-45-2220.01x -/// @note Page 28 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::bus_width_extension(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 13; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(BUS_WIDTH_EXT_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Bus Width Extension") ); - - FAPI_DBG("%s. Bus Width Extension (bits): %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decode Module Thermal Sensor -/// @param[in] i_target dimm target -/// @param[out] o_value thermal sensor value from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 14 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 28 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::thermal_sensor(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 14; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check for valid value - constexpr size_t INVALID_VALUE = 2; // single bit value 0 or 1 - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_field_bits < INVALID_VALUE, - BYTE_INDEX, - l_field_bits, - "Failed check for Thermal Sensor") ); - - // Update output after check passes - o_value = l_field_bits; - - FAPI_DBG("%s. Thermal Sensor: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Extended Base Module Type -/// @param[in] i_target dimm target -/// @param[out] o_value raw data from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 15 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 28 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::extended_base_module_type(const fapi2::Target& i_target, - uint8_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 15; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check for valid value - // Currently reserved to 0b000 - constexpr size_t RESERVED = 0; - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_field_bits == RESERVED, - BYTE_INDEX, - l_field_bits, - "Failed check for Extended Base Module Type") ); - - // Update output for check passes - o_value = l_field_bits; - - FAPI_DBG("%s. Extended Base Module Type: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decode Fine Timebase -/// @param[in] i_target dimm target -/// @param[out] o_value fine_timebase from SPD in picoseconds -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 17 (bits 1~0) -/// @note Item JC-45-2220.01x -/// @note Page 29 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_timebase(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 17; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(FINE_TIMEBASE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Fine Timebase") ); - - FAPI_DBG("%s. Fine Timebase: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Medium Timebase -/// @param[in] i_target dimm target -/// @param[out] o_value medium timebase from SPD in picoseconds -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 17 (bits 3~2) -/// @note Item JC-45-2220.01x -/// @note Page 29 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::medium_timebase(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 17; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Extracting desired bits - uint8_t l_field_bits = 0; - fapi2::buffer l_spd_buffer(l_raw_byte); - l_spd_buffer.extractToRight(l_field_bits); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(MEDIUM_TIMEBASE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_field_bits, - "Failed check for Medium Timebase") ); - - FAPI_DBG("%s. Medium Timebase: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes SDRAM Minimum Cycle Time in MTB -/// @param[in] i_target dimm target -/// @param[out] o_value tCKmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 18 -/// @note Item JC-45-2220.01x -/// @note Page 31-32 -/// @note DDR4 SPD Document Release 3 -/// @warning If tCKmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tCKmin (SPD byte 125) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder::min_cycle_time(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 18; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: %d.", - mss::c_str(i_target), - BYTE_INDEX, - l_timing_val); - - // Check if value is valid - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the min cycle time (tckmin) in MTB") ); - - // Update output after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Cycle Time (tCKmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Maximum Cycle Time in MTB -/// @param[in] i_target dimm target -/// @param[out] o_value tCKmax in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 19 -/// @note Item JC-45-2220.01x -/// @note Page 32 -/// @note DDR4 SPD Document Release 3 -/// @warning If tCKmax cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tCKmax (SPD byte 124) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder::max_cycle_time(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 19; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: %d.", - mss::c_str(i_target), - BYTE_INDEX, - l_timing_val); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the max cycle time (tckmax) in MTB") ); - - // Update output after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Maximum Cycle Time (tCKmax) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decode CAS Latencies Supported -/// @param[in] i_target dimm target -/// @param[out] o_value bitmap of supported CAS latencies -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Bytes 20-23 -/// @note Item JC-45-2220.01x -/// @note Page 33-34 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::supported_cas_latencies(const fapi2::Target& i_target, - uint64_t& o_value) -{ - // Trace print in the front assists w/ debug - constexpr size_t FIRST_BYTE = 20; - uint8_t first_raw_byte = iv_spd_data[FIRST_BYTE]; - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - c_str(i_target), - FIRST_BYTE, - first_raw_byte); - - constexpr size_t SEC_BYTE = 21; - uint8_t sec_raw_byte = iv_spd_data[SEC_BYTE]; - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - c_str(i_target), - SEC_BYTE, - sec_raw_byte); - - constexpr size_t THIRD_BYTE = 22; - uint8_t third_raw_byte = iv_spd_data[THIRD_BYTE]; - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - c_str(i_target), - THIRD_BYTE, - third_raw_byte); - - constexpr size_t FOURTH_BYTE = 23; - uint8_t fourth_raw_byte = iv_spd_data[FOURTH_BYTE]; - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - c_str(i_target), - FOURTH_BYTE, - fourth_raw_byte); - - // Buffers used for bit manipulation - // Combine Bytes to create bitmap - right aligned - fapi2::buffer l_buffer; - - l_buffer.insertFromRight(first_raw_byte) - .insertFromRight(sec_raw_byte) - .insertFromRight(third_raw_byte) - .insertFromRight(fourth_raw_byte); - - // According to the JEDEC spec: - // Byte 23 bit 6 is reserved and must be coded as 0. - // Should we warn instead of fail because in last revision this was a reserved byte coded as 0x00 - constexpr size_t BIT_START = 33; // relative position of bit 6 in byte 23 relative to uint64_t - constexpr size_t BIT_LEN = 1; - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - - // Check for a valid value - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - !(l_buffer.getBit()), - FOURTH_BYTE, - fourth_raw_byte, - "Failed check on CAS latencies supported") ); - - // Update output value only if range check passes - l_buffer.extractToRight(o_value); - - FAPI_DBG("%s. CAS latencies supported (bitmap): 0x%llX", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes SDRAM Minimum CAS Latency Time in MTB -/// @param[in] i_target dimm target -/// @param[out] o_value tAAmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 24 -/// @note Item JC-45-2220.01x -/// @note Page 34 -/// @note DDR4 SPD Document Release 3 -/// @warning If tAAmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tAAmin (SPD byte 123) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder::min_cas_latency_time(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 24; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_timing_val); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum CAS Latency Time (tAAmin) in MTB") ); - - // Only update output if it passes check - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum CAS Latency Time (tAAmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB -/// @param[in] i_target dimm target -/// @param[out] o_value tRCDmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 25 -/// @note Item JC-45-2220.01x -/// @note Page 35 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRCDmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRCDmin (SPD byte 122) -/// used for correction to get the actual value -/// -fapi2::ReturnCode decoder::min_ras_to_cas_delay_time(const fapi2::Target& i_target, - - int64_t& o_value) -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 25; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_timing_val); - - // Find valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum RAS to CAS Delay Time (tRCDmin) in MTB") ); - - // Only update output if it passes check - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum RAS to CAS Delay Time (tRCDmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB -/// @param[in] i_target dimm target -/// @param[out] o_value tRPmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 26 -/// @note Item JC-45-2220.01x -/// @note Page 36-37 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRPmin cannot be divided evenly by the MTB, -// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRPmin (SPD byte 121) -/// used for correction to get the actual value -/// -fapi2::ReturnCode decoder::min_row_precharge_delay_time(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 26; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_timing_val); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Row Precharge Delay Time (tRPmin) in MTB") ); - - // Only update output if it passes check - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Row Precharge Delay Time (tRPmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB -/// @param[in] i_target dimm target -/// @param[out] o_value tRASmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 27 (bits 3~0) & Byte 28 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 38 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::min_active_to_precharge_delay_time(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Lambda expression to retrieve tRASmin's most significant nibble (MSN) - auto tRASmin_MSN = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 27; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve tRASmin's least significant byte (LSB) - auto tRASmin_LSB = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 28; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - l_buffer.extractToRight(l_out); - - return l_out; - }; - - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer l_buffer; - - l_buffer.insertFromRight( tRASmin_MSN(i_target, iv_spd_data) ). - insertFromRight( tRASmin_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - int64_t l_timing_val = 0; - - l_buffer.extractToRight(l_timing_val); - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // But byte 28 of the JEDEC spec explains how to piece this together - AAM - constexpr size_t ERROR_BYTE_INDEX = 28; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Active to Precharge Delay Time (tRASmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Active to Precharge Delay Time (tRASmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB -/// @param[in] i_target dimm target -/// @param[out] o_value tRCmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 27 (bits 7~4) & SPD Byte 29 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 38 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRCmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRCmin (SPD byte 120) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder::min_active_to_active_refresh_delay_time(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Lambda expression to retrieve tRCmin's most significant nibble (MSN) - auto tRCmin_MSN = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 27; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve tRCmin's least significant byte (LSB) - auto tRCmin_LSB = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 29; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer l_buffer; - - l_buffer.insertFromRight( tRCmin_MSN(i_target, iv_spd_data) ). - insertFromRight( tRCmin_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - int64_t l_timing_val = 0; - - l_buffer.extractToRight(l_timing_val); - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // But byte 29 of the JEDEC spec explains how to piece this together - AAM - constexpr size_t ERROR_BYTE_INDEX = 29; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1 -/// @param[in] i_target dimm target -/// @param[out] o_value tRFC1min in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 30 & Byte 31 -/// @note Item JC-45-2220.01x -/// @note Page 39-40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_1(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Lambda expression to retrieve tRFC1min's most significant byte (MSB) - auto tRFC1min_MSB = [](const fapi2::Target& i_target, const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 31; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve tRFC1min's least significant byte (LSB) - auto tRFC1min_LSB = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 30; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSB_START = 48; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer l_buffer; - - l_buffer.insertFromRight( tRFC1min_MSB(i_target, iv_spd_data) ). - insertFromRight( tRFC1min_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - int64_t l_timing_val = 0; - - l_buffer.extractToRight(l_timing_val); - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 30) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 30; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2 -/// @param[in] i_target dimm target -/// @param[out] o_value tRFC2min in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 32 & Byte 33 -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_2(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Lambda expression to retrieve tRFC2min's most significant byte (MSB) - auto tRFC2min_MSB = [](const fapi2::Target& i_target, const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 33; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve tRFC2min's least significant byte (LSB) - auto tRFC2min_LSB = [](const fapi2::Target& i_target, const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 32; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSB_START = 48; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer l_buffer; - - l_buffer.insertFromRight( tRFC2min_MSB(i_target, iv_spd_data) ). - insertFromRight( tRFC2min_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - int64_t l_timing_val = 0; - - l_buffer.extractToRight(l_timing_val); - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 33) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 33; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4 -/// @param[in] i_target dimm target -/// @param[out] o_value tRFC4min in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 34 & Byte 35 -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_4(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Lambda expression to retrieve tRFC4min's most significant byte (MSB) - auto tRFC4min_MSB = [](const fapi2::Target& i_target, const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 35; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve tRFC4min's least significant byte (LSB) - auto tRFC4min_LSB = [](const fapi2::Target& i_target, const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 34; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSB_START = 48; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer l_buffer; - - l_buffer.insertFromRight( tRFC4min_MSB(i_target, iv_spd_data) ). - insertFromRight( tRFC4min_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - int64_t l_timing_val = 0; - - l_buffer.extractToRight(l_timing_val); - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 34) for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 34; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum Four Activate Window Delay Time -/// @param[in] i_target dimm target -/// @param[out] o_value tFAWmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 36 (bits 3~0) & Byte 37 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 42 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::min_tfaw(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Lambda expression to retrieve tFAWmin's most significant nibble (MSN) - auto tFAWmin_MSN = [](const fapi2::Target& i_target, const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 36; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve tFAWmin's least significant byte (LSB) - auto tFAWmin_LSB = [](const fapi2::Target& i_target, const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 37; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer l_buffer; - - l_buffer.insertFromRight( tFAWmin_MSN(i_target, iv_spd_data) ). - insertFromRight( tFAWmin_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - int64_t l_timing_val = 0; - - l_buffer.extractToRight(l_timing_val); - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 37) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 37; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Four Activate Window Delay Time (tFAWmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Four Activate Window Delay Time (tFAWmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group -/// @param[in] i_target dimm target -/// @param[out] o_value tRRD_Smin MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 38 -/// @note Item JC-45-2220.01x -/// @note Page 43 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRRD_Smin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRRD_Smin (SPD byte 119) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder::min_trrd_s(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 38; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Minimum Activate to Activate Delay Time - Different Bank Group - // explicit conversion to int64_t - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Find valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group -/// @param[in] i_target dimm target -/// @param[out] o_value tRRD_Lmin MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 39 -/// @note Item JC-45-2220.01x -/// @note Page 43-44 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRRD_Lmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRRD_Lmin (SPD byte 118) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder::min_trrd_l(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 39; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Minimum Activate to Activate Delay Time - Same Bank Group - // explicit conversion to int64_t - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Find valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group -/// @param[in] i_target dimm target -/// @param[out] o_value tCCD_Lmin MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 40 -/// @note Item JC-45-2220.01x -/// @note Page 44-45 -/// @note DDR4 SPD Document Release 3 -/// @warning If tCCD_Lmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tCCD_Lmin (SPD byte 117) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder::min_tccd_l(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 40; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Minimum CAS to CAS Delay Time - Same Bank Group - // explicit conversion to int64_t - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum Write Recovery Time -/// @param[in] i_target dimm target -/// @param[out] o_value tWRmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::min_write_recovery_time(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Lambda expression to retrieve tWRmin's most nibble byte (MSN) - auto tWRmin_MSN = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 41; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve tWRmin's least significant byte (LSB) - auto tWRmin_LSB = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 42; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer l_buffer; - l_buffer.insertFromRight( tWRmin_MSN(i_target, iv_spd_data) ). - insertFromRight( tWRmin_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - int64_t l_timing_val = 0; - - l_buffer.extractToRight(l_timing_val); - - // JEDEC spec limits for this timing value - // This value used to be reserved to 0 - before spec update - // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - - constexpr int64_t TIMING_LOWER_BOUND = 0; - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 42) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 42; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Write Recovery Time (tWRmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Write Recovery Time (tWRmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes Minimum Write to Read Time - Different Bank Group -/// @param[in] i_target dimm target -/// @param[out] o_value tWRT_Smin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::min_twtr_s(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Lambda expression to retrieve tWRT_Smin's most nibble byte (MSN) - auto tWRT_Smin_MSN = [](const fapi2::Target& i_target, const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 43; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve tWRT_Smin's least significant byte (LSB) - auto tWRT_Smin_LSB = [](const fapi2::Target& i_target, const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 44; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer l_buffer; - - l_buffer.insertFromRight( tWRT_Smin_MSN(i_target, iv_spd_data) ). - insertFromRight( tWRT_Smin_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - int64_t l_timing_val = 0; - - l_buffer.extractToRight(l_timing_val); - - - // JEDEC spec limits for this timing value - - // This value used to be reserved to 0 - before spec update - AAM - // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_LOWER_BOUND = 0; - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 44) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 44; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Write to Read Time - Different Bank Group (tWRT_Smin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Write to Read Time - Different Bank Group (tWRT_Smin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum Write to Read Time - Same Bank Group -/// @param[in] i_target dimm target -/// @param[out] o_value tWRT_Lmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 46 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::min_twtr_l(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Lambda expression to retrieve tWRT_Lmin's most nibble byte (MSN) - auto tWRT_Lmin_MSN = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 43; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve tWRT_Lmin's least significant byte (LSB) - auto tWRT_Lmin_LSB = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 45; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - // Extracting desired bits - uint8_t l_out = 0; - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer l_buffer; - - l_buffer.insertFromRight( tWRT_Lmin_MSN(i_target, iv_spd_data) ). - insertFromRight( tWRT_Lmin_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 64; - int64_t l_timing_val = 0; - - l_buffer.extractToRight(l_timing_val); - - // JEDEC spec limits for this timing value - // This value used to be reserved to 0 - before spec update - //constexpr int64_t TIMING_LOWER_BOUND = 1 // from JEDEC - constexpr int64_t TIMING_LOWER_BOUND = 0; - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 45) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 45; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Write to Read Time - Same Bank Group (tWRT_Lmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Minimum Write to Read Time - Same Bank Group (tWRT_Lmin) in MTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group -/// @param[in] i_target dimm target -/// @param[out] o_value tCCD_Lmin offset in FTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 117 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_offset_min_tccd_l(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 117; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum CAS to CAS Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for min RAS to CAS Delay Time (tCCD_Lmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Fine offset for Minimum RAS to CAS Delay Time (tCCD_Lmin) in FTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group -/// @param[in] i_target dimm target -/// @param[out] o_value tRRD_Lmin offset in FTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 118 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_offset_min_trrd_l(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 118; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum Activate to Activate Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin) in FTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group -/// @param[in] i_target dimm target -/// @param[out] o_value tRRD_Smin offset in FTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 119 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_offset_min_trrd_s(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 119; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in FTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time -/// @param[in] i_target dimm target -/// @param[out] o_value tRCmin offset in FTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 120 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_offset_min_trc(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 120; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum Active to Active/Refresh Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for vali value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin) in FTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time -/// @param[in] i_target dimm target -/// @param[out] o_value tRPmin offset in FTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 121 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_offset_min_trp(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 121; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum Row Precharge Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for Minimum Row Precharge Delay Time (tRPmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Fine offset for Minimum Row Precharge Delay Time (tRPmin) in FTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} -/// -/// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time -/// @param[in] i_target dimm target -/// @param[out] o_value tRCDmin offset in FTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 122 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_offset_min_trcd(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 122; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for SDRAM Minimum RAS to CAS Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for min RAS to CAS Delay Time (tRCDmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Fine offset for Minimum RAS to CAS Delay Time (tRCDmin) in FTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time -/// @param[in] i_target dimm target -/// @param[out] o_value tAAmin offset in FTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 123 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_offset_min_taa(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 123; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for SDRAM Minimum CAS Latency Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Fine offset for Minimum CAS Latency Time (tAAmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Fine offset for Minimum CAS Latency Time (tAAmin) in FTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time -/// @param[in] i_target dimm target -/// @param[out] o_value tCKmax offset in FTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 124 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_offset_max_tck(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 124; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for SDRAM Maximum Cycle Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for max cycle time (tckmax)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Fine offset for Maximum Cycle Time (tCKmax) in FTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time -/// @param[in] i_target dimm target -/// @param[out] o_value tCKmin offset in FTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 125 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::fine_offset_min_tck(const fapi2::Target& i_target, - int64_t& o_value) -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 125; - - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for SDRAM Minimum Cycle Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Fine offset for Minimum Cycle Time (tCKmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_DBG("%s. Fine offset for Minimum Cycle Time (tCKmin) in FTB units: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section -/// @param[in] i_target dimm target -/// @param[out] o_value crc value from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 127 & Byte 126 -/// @note Item JC-45-2220.01x -/// @note Page 53 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder::cyclical_redundancy_code(const fapi2::Target& i_target, - uint16_t& o_value) -{ - // Lambda expression to retrieve crc's most significant byte (MSB) - auto crc_MSB = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - constexpr size_t BYTE_INDEX = 127; - uint8_t l_out = 0; - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - // Extracting desired bits - l_buffer.extractToRight(l_out); - - return l_out; - }; - - // Lambda expression to retrieve crc's least significant byte (LSB) - auto crc_LSB = [](const fapi2::Target& i_target, - const std::vector& i_data) - { - constexpr size_t BYTE_INDEX = 126; - uint8_t l_out = 0; - - // Trace in the front assists w/ debug - FAPI_DBG("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_data[BYTE_INDEX]); - - fapi2::buffer l_buffer(i_data[BYTE_INDEX]); - - // Extracting desired bits - l_buffer.extractToRight(l_out); - - return l_out; - }; - - fapi2::buffer l_buffer; - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 0; - constexpr size_t MSN_LEN = 8; - constexpr size_t LSB_START = 8; - constexpr size_t LSB_LEN = 8; - - l_buffer.insertFromRight( crc_MSB(i_target, iv_spd_data) ). - insertFromRight( crc_LSB(i_target, iv_spd_data) ); - - // Extract timing value from the buffer into an integral type - constexpr size_t OUTPUT_START = 0; - constexpr size_t OUTPUT_LEN = 16; - - // This value isn't bounded in the SPD document - l_buffer.extractToRight(o_value); - - FAPI_DBG("%s. Cyclical Redundancy Code (CRC): %d", - mss::c_str(i_target), - o_value); - - // Returns "happy" until we can figure out a way to test this - AAM - return fapi2::FAPI2_RC_SUCCESS; -} - -}//spd namespace -}// mss namespace diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.H deleted file mode 100644 index 088ccb00f..000000000 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.H +++ /dev/null @@ -1,1200 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -/// -/// @file spd_decoder.H -/// @brief SPD decoder declarations -/// -// *HWP HWP Owner: Andre Marin -// *HWP HWP Backup: Brian Silver -// *HWP Team: Memory -// *HWP Level: 2 -// *HWP Consumed by: HB:FSP - -#ifndef _MSS_SPD_DECODER_H_ -#define _MSS_SPD_DECODER_H_ - -#include -#include -#include -#include - -namespace mss -{ -namespace spd -{ - - -enum BYTE_EXTRACT : uint64_t -{ - // Byte 0 - BYTES_USED_START = 4, - BYTES_USED_LEN = 4, - - BYTES_TOTAL_START = 1, - BYTES_TOTAL_LEN = 3, - - BYTES_RESERVED_START = 0, - BYTES_RESERVED_LEN = 1, - - // Byte 1 - ENCODING_LEVEL_START = 0, - ENCODING_LEVEL_LEN = 4, - - ADDITIONS_LEVEL_START = 4, - ADDITIONS_LEVEL_LEN = 4, - - // Byte 2 - Entire byte used - - // Byte 3 - BASE_MODULE_START = 4, - BASE_MODULE_LEN = 4, - - HYBRID_MEDIA_START = 1, - HYBRID_MEDIA_LEN = 3, - - HYBRID_START = 0, - HYBRID_LEN = 1, - - // Byte 4 - SDRAM_CAPACITY_START = 4, - SDRAM_CAPACITY_LEN = 4, - - SDRAM_BANKS_START = 2, - SDRAM_BANKS_LEN = 2, - - BANK_GROUP_START = 0, - BANK_GROUP_LEN = 2, - - // Byte 5 - COL_ADDRESS_START = 5, - COL_ADDRESS_LEN = 3, - - ROW_ADDRESS_START = 2, - ROW_ADDRESS_LEN = 3, - - ADDRESS_RESERVED_START = 0, - ADDRESS_RESERVED_LEN = 2, - - // Byte 6 - PRIM_SIGNAL_LOAD_START = 6, - PRIM_SIGNAL_LOAD_LEN = 2, - - PACKAGE_RESERVE_START = 4, - PACKAGE_RESERVE_LEN = 2, - - PRIM_DIE_COUNT_START = 1, - PRIM_DIE_COUNT_LEN = 3, - - PRIM_PACKAGE_TYPE_START = 0, - PRIM_PACKAGE_TYPE_LEN = 1, - - // Byte 7 - MAC_START = 4, - MAC_LEN = 4, - - TMAW_START = 2, - TMAW_LEN = 2, - - OPT_FEAT_RESERVED_START = 0, - OPT_FEAT_RESERVED_LEN = 2, - - // Byte 8 reserved - - // Byte 9 - PPR_RESERVED_START = 3, - PPR_RESERVED_LEN = 5, - - SOFT_PPR_START = 2, - SOFT_PPR_LEN = 1, - - PPR_START = 0, - PPR_LEN = 2, - - // Byte 10 - SEC_SIGNAL_LOAD_START = 5, - SEC_SIGNAL_LOAD_LEN = 2, - - DENSITY_RATIO_START = 4, - DENSITY_RATIO_LEN = 2, - - SEC_DIE_COUNT_START = 1, - SEC_DIE_COUNT_LEN = 3, - - SEC_PACKAGE_TYPE_START = 0, - SEC_PACKAGE_TYPE_LEN = 1, - - // Byte 11 - OPERABLE_START = 7, - OPERABLE_LEN = 1, - - ENDURANT_START = 6, - ENDURANT_LEN = 1, - - NOM_VOLT_START = 0, - NOM_VOLT_LEN = 6, - - // Byte 12 - SDRAM_WIDTH_START = 5, - SDRAM_WIDTH_LEN = 3, - - PACKAGE_RANKS_START = 2, - PACKAGE_RANKS_LEN = 3, - - RANK_MIX_START = 1, - RANK_MIX_LEN = 1, - - MODULE_ORG_RESERVED_START = 0, - MODULE_ORG_RESERVED_LEN = 1, - - // Byte 13 - BUS_WIDTH_START = 5, - BUS_WIDTH_LEN = 3, - - BUS_EXT_WIDTH_START = 3, - BUS_EXT_WIDTH_LEN = 2, - - BUS_WIDTH_RESERVED_START = 0, - BUS_WIDTH_RESERVED_LEN = 3, - - // Byte 14 - THERM_SENSOR_RESERV_START = 1, - THERM_SENSOR_RESERV_LEN = 7, - - THERM_SENSOR_START = 0, - THERM_SENSOR_LEN = 1, - - // Byte 15 - EXT_MOD_TYPE_START = 5, - EXT_MOD_TYPE_LEN = 3, - - EXT_MOD_TYPE_RESERV_START = 0, - EXT_MOD_TYPE_RESERV_LEN = 4, - - // Byte 16 - reserved - - // Byte 17 - FINE_TIMEBASE_START = 6, - FINE_TIMEBASE_LEN = 2, - - MED_TIMEBASE_START = 4, - MED_TIMEBASE_LEN = 2, - - TIMEBASE_RESERV_START = 0, - TIMEBASE_RESERV_LEN = 4, - - // Byte 18 - Entire byte used - // Byte 19 - Entire byte used - - // Byte 20-23 - CAS_BYTE_1_START = 56, - CAS_BYTE_1_LEN = 8, - CAS_BYTE_2_START = 48, - CAS_BYTE_2_LEN = 8, - CAS_BYTE_3_START = 40, - CAS_BYTE_3_LEN = 8, - CAS_BYTE_4_START = 32, - CAS_BYTE_4_LEN = 8, - - // Byte 24 - Entire byte used - // Byte 25 - Entire byte used - // Byte 26 - Entire byte used - - // Byte 27 - TRASMIN_MSN_START = 4, // MSN = most significant nibble - TRASMIN_MSN_LEN = 4, - - TRCMIN_MSN_START = 0, // MSN = most significant nibble - TRCMIN_MSN_LEN = 4, - - // Byte 28 - TRASMIN_LSB_START = 0, // LSB = least significant byte - TRASMIN_LSB_LEN = 8, - - // Byte 29 - TRCMIN_LSB_START = 0, // LSB = least significant byte - TRCMIN_LSB_LEN = 8, - - // Byte 30 - TRFC1MIN_LSB_START = 0, - TRFC1MIN_LSB_LEN = 8, - - // Byte 31 - TRFC1MIN_MSB_START = 0, - TRFC1MIN_MSB_LEN = 8, - - // Byte 32 - TRFC2MIN_LSB_START = 0, - TRFC2MIN_LSB_LEN = 8, - - // Byte 33 - TRFC2MIN_MSB_START = 0, - TRFC2MIN_MSB_LEN = 8, - - // Byte 34 & Byte 35 - TRFC4MIN_LSB_START = 0, - TRFC4MIN_LSB_LEN = 8, - - TRFC4MIN_MSB_START = 0, - TRFC4MIN_MSB_LEN = 8, - - // Byte 36 - TFAWMIN_MSN_START = 4, - TFAWMIN_MSN_LEN = 4, - - // Byte 37 - TFAWMIN_LSB_START = 0, - TFAWMIN_LSB_LEN = 8, - - // Byte 38 - Entire byte used - // Byte 39 - Entire byte used - // Byte 40 - Entire byte used - - // Byte 41 - TWRMIN_MSN_START = 4, // MSN = most significant nibble - TWRMIN_MSN_LEN = 4, - - // Byte 42 - TWRMIN_LSB_START = 0, // LSB = least significant nibble - TWRMIN_LSB_LEN = 8, - - // Byte 43 - TWTRMIN_L_MSN_START = 0, // MSN = most significant nibble - TWTRMIN_L_MSN_LEN = 4, - - TWTRMIN_S_MSN_START = 4, // MSN = most significant nibble - TWTRMIN_S_MSN_LEN = 4, - - // Byte 44 - TWTRMIN_S_LSB_START = 0, // LSB = least significant byte - TWTRMIN_S_LSB_LEN = 8, - - // Byte 45 - TWTRMIN_L_LSB_START = 0, - TWTRMIN_L_LSB_LEN = 8, - - // Bytes 46 - 59 - reserved - - // Bytes 60 - 77 - Connector to SDRAM Bit Mapping ?? - - // Bytes 78 - 116 - reserved - - // Bytes 117 - 125 : Entire byte used - - // Byte 126 - CRC_MSB_START = 0, - CRC_MSB_LEN = 8, - - // Byte 127 - CRC_LSB_START = 0, - CRC_LSB_LEN = 8, - - // Bytes 128 ~ 191 Module-Specific Section ?? - - // Bytes 192 ~ 255 Hybrid Memory Architecture Specific Parameters ?? - - // Bytes 256 ~ 319 Extended Function Parameter Block ?? - - // Bytes 320 ~ 383 Module Supplier’s Data ?? -}; - -enum SDRAM_PACKAGE_TYPE : size_t -{ - // Signal loading - MONOLITHIC = 0, - NON_MONOLITHIC = 1, - - // Package Type - UNSPECIFIED = MONOLITHIC, - MULTI_LOAD_STACK = 1, - SINGLE_LOAD_STACK = 2, -}; - -enum NOMINAL_VOLTAGE : size_t -{ - NOT_OPERABLE = 0, - OPERABLE = 1, - - NOT_ENDURANT = 0, - ENDURANT = 1 -}; - -enum rank_mix : size_t -{ - SYMMETRICAL, - ASYMMETRICAL, -}; - -/// -/// @class decoder -/// @brief Base SPD DRAM decoder -/// -class decoder -{ - - public: - std::vector iv_spd_data; - - // Constructor - decoder() = default; - - // Deconstructor - virtual ~decoder() = default; - - ///////////////////////// - // Member Methods - ///////////////////////// - - /// - /// @brief Decodes number of used SPD bytes - /// @param[in] i_target dimm target - /// @param[out] o_value number of SPD bytes used - /// @return FAPI2_RC_SUCCESS if okay - /// @note Decodes SPD Byte 0 (3~0) - /// @note Item JC-45-2220.01x - /// @note Page 14 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode number_of_used_bytes(const fapi2::Target& i_target, - uint16_t& o_value); - - /// - /// @brief Decodes total number of SPD bytes - /// @param[in] i_target dimm target - /// @param[out] o_value number of total SPD bytes - /// @return FAPI2_RC_SUCCESS if okay - /// @note Decodes SPD Byte 0 (bits 6~4) - /// @note Item JC-45-2220.01x - /// @note Page 14 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode number_of_total_bytes(const fapi2::Target& i_target, - uint16_t& o_value); - - /// - /// @brief Decodes hybrid media field from SPD - /// @param[in] i_target - /// @param[out] o_value - /// @return FAPI2_RC_SUCCESS if okay - /// @note Decodes SPD Byte 3 (bits 6~4) - /// @note Item JC-45-2220.01x - /// @note Page 17 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode hybrid_media(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes hybrid field from SPD - /// @param[in] i_target - /// @param[out] o_value - /// @return FAPI2_RC_SUCCESS if okay - /// @note Decodes SPD Byte 3 (bit 7) - /// @note Item JC-45-2220.01x - /// @note Page 17 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode hybrid(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes SDRAM density from SPD - /// @param[in] i_target dimm target - /// @param[out] o_value SDRAM density in GBs - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 4 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode sdram_density(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes number of SDRAM banks from SPD - /// @param[in] i_target dimm target - /// @param[out] o_value Number of SDRAM banks - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 4 (bits 5~4) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode banks(const fapi2::Target& i_target, - uint8_t& o_value); - - /// - /// @brief Decodes number of SDRAM bank groups from SPD - /// @param[in] i_target dimm target - /// @param[out] o_value Number of SDRAM bank groups - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 4 (bits 7~6) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode bank_groups(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes number of SDRAM column address bits - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 5 (bits 2~0) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode column_address_bits(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes number of SDRAM row address bits - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 5 (bits 5~3) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode row_address_bits(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes Primary SDRAM signal loading - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 6 (bits 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 19 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode prim_sdram_signal_loading(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes Primary SDRAM die count - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 6 (bits 6~4) - /// @note Item JC-45-2220.01x - /// @note Page 19 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode prim_sdram_die_count(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes Primary SDRAM package type - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 6 (bit 7) - /// @note Item JC-45-2220.01x - /// @note Page 19 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode prim_sdram_package_type(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decode SDRAM Maximum activate count - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 7 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 20 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode maximum_activate_count(const fapi2::Target& i_target, - uint32_t& o_value); - /// - /// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point - /// @param[in] i_target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 7 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 20 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode maximum_activate_window_multiplier(const fapi2::Target& i_target, - uint32_t& o_value); - /// - /// @brief Decode Soft post package repair (soft PPR) - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 9 (bit 5) - /// @note Item JC-45-2220.01x - /// @note Page 21 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode soft_post_package_repair(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decode Post package repair (PPR) - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 9 (bits 7~6) - /// @note Item JC-45-2220.01x - /// @note Page 21 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode post_package_repair(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes Secondary SDRAM signal loading - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 10 (bits 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode sec_sdram_signal_loading(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes Secondary DRAM Density Ratio - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 10 (bits 3~2) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode sec_dram_density_ratio(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes Secondary SDRAM die count - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 10 (bits 6~4) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode sec_sdram_die_count(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes Secondary SDRAM package type - /// @param[in] i_target dimm target - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 10 (bit 7) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode sec_sdram_package_type(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decode Module Nominal Voltage, VDD - /// @param[in] i_target dimm target - /// @param[out] o_value enum representing if 1.2V is operable - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 11 (bit 0) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode operable_nominal_voltage(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decode Module Nominal Voltage, VDD - /// @param[in] i_target dimm target - /// @param[out] o_value enum representing if 1.2V is endurant - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 11 (bit 1) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode endurant_nominal_voltage(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes SDRAM device width - /// @param[in] i_target dimm target - /// @param[out] o_value device width in bits - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 12 (bits 2~0) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode device_width(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes number of package ranks per DIMM - /// @param[in] i_target dimm target - /// @param[out] o_value number of package ranks per DIMM - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 12 (bits 5~3) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode num_package_ranks_per_dimm(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes Rank Mix - /// @param[in] i_target dimm target - /// @param[out] o_value rank mix value from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 12 (bit 6) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode rank_mix(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes primary bus width - /// @param[in] i_target dimm target - /// @param[out] o_value primary bus width in bits - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 13 (bits 2~0) - /// @note Item JC-45-2220.01x - /// @note Page 27 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode prim_bus_width(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decodes bus width extension - /// @param[in] i_target dimm target - /// @param[out] o_value bus width extension in bits - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 13 (bits 4~3) - /// @note Item JC-45-2220.01x - /// @note Page 27 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode bus_width_extension(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decode Module Thermal Sensor - /// @param[in] i_target dimm target - /// @param[out] o_value thermal sensor value from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 14 (bit 7) - /// @note Item JC-45-2220.01x - /// @note Page 28 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode thermal_sensor(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decode Extended Base Module Type - /// @param[in] i_target dimm target - /// @param[out] o_value extended base module type value from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 15 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 28 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode extended_base_module_type(const fapi2::Target& i_target, - uint8_t& o_value); - /// - /// @brief Decode Fine Timebase - /// @param[in] i_target dimm target - /// @param[out] o_value fine_timebase from SPD in picoseconds - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 17 (bits 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 29 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_timebase(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decode Medium Timebase - /// @param[in] i_target dimm target - /// @param[out] o_value fine_timebase from SPD in picoseconds - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 17 (bits 3~2) - /// @note Item JC-45-2220.01x - /// @note Page 29 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode medium_timebase(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// - /// @brief Decodes SDRAM Minimum Cycle Time in MTB - /// @param[in] i_target dimm target - /// @param[out] o_value tCKmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 18 - /// @note Item JC-45-2220.01x - /// @note Page 31-32 - /// @note DDR4 SPD Document Release 3 - /// @warning If tCKmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tCKmin (SPD byte 125) - /// used for correction to get the actual value. - /// - virtual fapi2::ReturnCode min_cycle_time(const fapi2::Target& i_target, - int64_t& o_value); - - /// - /// @brief Decodes SDRAM Maximum Cycle Time in MTB - /// @param[in] i_target dimm target - /// @param[out] o_value tCKmax in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 19 - /// @note Item JC-45-2220.01x - /// @note Page 32 - /// @note DDR4 SPD Document Release 3 - /// @warning If tCKmax cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tCKmax (SPD byte 124) - /// used for correction to get the actual value. - /// - virtual fapi2::ReturnCode max_cycle_time(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decode CAS Latencies Supported - /// @param[in] i_target dimm target - /// @param[out] o_value bitmap of supported CAS latencies - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Bytes 20-23 - /// @note Item JC-45-2220.01x - /// @note Page 33-34 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode supported_cas_latencies(const fapi2::Target& i_target, - uint64_t& o_value); - /// - /// @brief Decodes SDRAM Minimum CAS Latency Time in MTB - /// @param[in] i_target dimm target - /// @param[out] o_value tAAmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 24 - /// @note Item JC-45-2220.01x - /// @note Page 34 - /// @note DDR4 SPD Document Release 3 - /// @warning If tAAmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tAAmin (SPD byte 123) - /// used for correction to get the actual value. - /// - virtual fapi2::ReturnCode min_cas_latency_time(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB - /// @param[in] i_target dimm target - /// @param[out] o_value tRCDmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 25 - /// @note Item JC-45-2220.01x - /// @note Page 35 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRCDmin cannot be divided evenly by the MTB, - // this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRCDmin (SPD byte 122) - /// used for correction to get the actual value - /// - virtual fapi2::ReturnCode min_ras_to_cas_delay_time(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB - /// @param[in] i_target dimm target - /// @param[out] o_value tRPmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 26 - /// @note Item JC-45-2220.01x - /// @note Page 36-37 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRPmin cannot be divided evenly by the MTB, - // this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRPmin (SPD byte 121) - /// used for correction to get the actual value - /// - virtual fapi2::ReturnCode min_row_precharge_delay_time(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB - /// @param[in] i_target dimm target - /// @param[out] o_value tRASmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 28 (bits 7~4) & SPD Byte 27 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 38 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_active_to_precharge_delay_time(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB - /// @param[in] i_target dimm target - /// @param[out] o_value tRCmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 27 (bits 7~4) & SPD Byte 29 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 38 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRCmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRCmin (SPD byte 120) - /// used for correction to get the actual value. - /// - virtual - fapi2::ReturnCode min_active_to_active_refresh_delay_time(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1 - /// @param[in] i_target dimm target - /// @param[out] o_value tRFC1min in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 30 & Byte 31 - /// @note Item JC-45-2220.01x - /// @note Page 39-40 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_refresh_recovery_delay_time_1(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2 - /// @param[in] i_target dimm target - /// @param[out] o_value tRFC2min in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 32 & Byte 33 - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_refresh_recovery_delay_time_2(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4 - /// @param[in] i_target dimm target - /// @param[out] o_value tRFC4min in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 34 & Byte 35 - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_refresh_recovery_delay_time_4(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes SDRAM Minimum Four Activate Window Delay Time - /// @param[in] i_target dimm target - /// @param[out] o_value tFAWmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 36 (bits 3~0) & Byte 37 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 42 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_tfaw(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group - /// @param[in] i_target dimm target - /// @param[out] o_value tRRD_Smin MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 38 - /// @note Item JC-45-2220.01x - /// @note Page 43 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRRD_Smin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRRD_Smin (SPD byte 119) - /// used for correction to get the actual value. - /// - virtual fapi2::ReturnCode min_trrd_s(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group - /// @param[in] i_target dimm target - /// @param[out] o_value tRRD_Lmin MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 39 - /// @note Item JC-45-2220.01x - /// @note Page 43-44 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRRD_Lmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRRD_Lmin (SPD byte 118) - /// used for correction to get the actual value. - /// - virtual fapi2::ReturnCode min_trrd_l(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group - /// @param[in] i_target dimm target - /// @param[out] o_value tCCD_Lmin MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 40 - /// @note Item JC-45-2220.01x - /// @note Page 44-45 - /// @note DDR4 SPD Document Release 3 - /// @warning If tCCD_Lmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tCCD_Lmin (SPD byte 117) - /// used for correction to get the actual value. - /// - virtual fapi2::ReturnCode min_tccd_l(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Minimum Write Recovery Time - /// @param[in] i_target dimm target - /// @param[out] o_value tWRmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_write_recovery_time(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Minimum Write to Read Time - Different Bank Group - /// @param[in] i_target dimm target - /// @param[out] o_value tWRT_Smin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_twtr_s(const fapi2::Target& i_target, - int64_t& o_value); - - /// - /// @brief Decodes Minimum Write to Read Time - Same Bank Group - /// @param[in] i_target dimm target - /// @param[out] o_value tWRT_Lmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 46 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_twtr_l(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group - /// @param[in] i_target dimm target - /// @param[out] o_value tCCD_Lmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 117 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_offset_min_tccd_l(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group - /// @param[in] i_target dimm target - /// @param[out] o_value tRRD_Lmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 118 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_offset_min_trrd_l(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group - /// @param[in] i_target dimm target - /// @param[out] o_value tRRD_Smin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 119 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_offset_min_trrd_s(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time - /// @param[in] i_target dimm target - /// @param[out] o_value tRCmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 120 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_offset_min_trc(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time - /// @param[in] i_target dimm target - /// @param[out] o_value tRPmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 121 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_offset_min_trp(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time - /// @param[in] i_target dimm target - /// @param[out] o_value tRCDmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 122 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_offset_min_trcd(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time - /// @param[in] i_target dimm target - /// @param[out] o_value tAAmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 123 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_offset_min_taa(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time - /// @param[in] i_target dimm target - /// @param[out] o_value tCKmax offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 124 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_offset_max_tck(const fapi2::Target& i_target, - int64_t& o_value); - /// - /// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time - /// @param[in] i_target dimm target - /// @param[out] o_value tCKmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 125 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode fine_offset_min_tck(const fapi2::Target& i_target, - int64_t& o_value); - - /// - /// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section - /// @param[in] i_target dimm target - /// @param[out] o_value crc value from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 127 & Byte 126 - /// @note Item JC-45-2220.01x - /// @note Page 53 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode cyclical_redundancy_code(const fapi2::Target& i_target, - uint16_t& o_value); -};// decoder - - -///////////////////////// -// Non-members functions -///////////////////////// - -/// -/// @brief Decodes SPD Revision encoding level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value encoding revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (3~0). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_encoding_level(const fapi2::Target& i_target, - const std::vector& i_spd_data, - uint8_t& o_value); -/// -/// @brief Decodes SPD Revision additions level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD blob -/// @param[out] o_value additions revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (bits 7~4). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_additions_level(const fapi2::Target& i_target, - const std::vector& i_spd_data, - uint8_t& o_value); - -/// -/// @brief Decodes base module type (DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value base module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode base_module_type(const fapi2::Target& i_target, - const std::vector& i_spd_data, - uint8_t& o_value); -/// -/// @brief Decodes DRAM Device Type -/// @param[in] i_target dimm target -/// @param[out] o_value dram device type enumeration -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 2 -/// @note Item JC-45-2220.01x -/// @note Page 16 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode dram_device_type(const fapi2::Target& i_target, - const std::vector& i_spd_data, - uint8_t& o_value); - -/// -/// @brief Object factory to select correct decoder -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -fapi2::ReturnCode factory(const fapi2::Target& i_target, - const std::vector& i_spd_data, - std::shared_ptr& o_fact_obj); - -/// -/// @brief Creates factory object & SPD data caches -/// @param[in] i_target the fapi2 target -/// @param[out] o_factory_caches map of factory objects with a dimm position key -/// @return FAPI2_RC_SUCCESS if okay -/// -template -fapi2::ReturnCode populate_decoder_caches(const fapi2::Target& i_target, - std::map >& o_factory_caches, - const std::shared_ptr& i_pDecoder = nullptr); - - -}// spd -}// mss - -#endif //_MSS_SPD_DECODER_H_ diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C new file mode 100644 index 000000000..9c054b63b --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C @@ -0,0 +1,492 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file spd_factory.C +/// @brief SPD factory and functions +/// +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Brian Silver +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +// std lib +#include +#include + +// fapi2 +#include +#include + +// mss lib +#include +#include + +#include +#include +#include +#include + +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_DIMM; + +namespace mss +{ +namespace spd +{ + +/// +/// @brief Decodes SPD Revision encoding level +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data +/// @param[out] o_value encoding revision num +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 1 (3~0). +/// @note Item JC-45-2220.01x +/// @note Page 14-15 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode rev_encoding_level(const fapi2::Target& i_target, + const std::vector& i_spd_data, + uint8_t& o_value) +{ + // Buffer used for bit manipulation + constexpr size_t BYTE_INDEX = 1; + uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + c_str(i_target), + BYTE_INDEX, + l_raw_byte); + + // Extracting desired bits + uint8_t l_field_bits = 0; + fapi2::buffer l_buffer(l_raw_byte); + l_buffer.extractToRight(l_field_bits); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check that value is valid + constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + (l_field_bits != UNDEFINED), + BYTE_INDEX, + l_raw_byte, + "Failed check on SPD rev encoding level") ); + + // Update output only after check passes + o_value = l_field_bits; + + // Print decoded info + FAPI_INF("%s. Rev - Encoding Level : %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes SPD Revision additions level +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data +/// @param[out] o_value additions revision num +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 1 (bits 7~4). +/// @note Item JC-45-2220.01x +/// @note Page 14-15 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode rev_additions_level(const fapi2::Target& i_target, + const std::vector& i_spd_data, + uint8_t& o_value) +{ + // Buffer used for bit manipulation + constexpr size_t BYTE_INDEX = 1; + uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + l_raw_byte); + + // Extracting desired bits + fapi2::buffer l_buffer(l_raw_byte); + uint8_t l_field_bits = 0; + l_buffer.extractToRight(l_field_bits); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check that value is valid + constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + (l_field_bits != UNDEFINED), + BYTE_INDEX, + l_raw_byte, + "Failed check on SPD rev encoding level") ); + + // Update output only after check passes + o_value = l_field_bits; + + // Print decoded info + FAPI_INF("%s. Rev - Additions Level : %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes base module type (DIMM type) from SPD +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data +/// @param[out] o_value base module type +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 3 (bits 3~0) +/// @note Item JC-45-2220.01x +/// @note Page 17 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode base_module_type(const fapi2::Target& i_target, + const std::vector& i_spd_data, + uint8_t& o_value) +{ + // ========================================================= + // Byte 3 maps + // Item JC-45-2220.01x + // Page 17 + // DDR4 SPD Document Release 3 + // Byte 3 (0x003): Key Byte / Module Type + // ========================================================= + static const std::vector > BASE_MODULE_TYPE_MAP = + { + //{key byte, dimm type} + {1, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM}, + {2, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM}, + {4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM} + // All others reserved or not supported + }; + + // Buffer used for bit manipulation + constexpr size_t BYTE_INDEX = 3; + uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX", + c_str(i_target), + BYTE_INDEX, + l_raw_byte); + + // Extracting desired bits + fapi2::buffer l_spd_buffer(l_raw_byte); + uint8_t l_field_bits = 0; + l_spd_buffer.extractToRight(l_field_bits); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Check that value is valid + bool l_is_val_found = find_value_from_key(BASE_MODULE_TYPE_MAP, l_field_bits, o_value); + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_field_bits, + "Failed check on Base Module Type") ); + + FAPI_INF("%s. Base Module Type: %d", + mss::c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM Device Type +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data +/// @param[out] o_value dram device type enumeration +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 2 +/// @note Item JC-45-2220.01x +/// @note Page 16 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode dram_device_type(const fapi2::Target& i_target, + const std::vector& i_spd_data, + uint8_t& o_value) +{ + // ========================================================= + // Byte 2 maps + // Item JC-45-2220.01x + // Page 16 + // DDR4 SPD Document Release 3 + // Byte 2 (0x002): Key Byte / DRAM Device Type + // ========================================================= + static const std::vector > DRAM_GEN_MAP = + { + //{key value, dram gen} + {0x0B, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR3}, + {0x0C, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4} + // Other key bytes reserved or not supported + }; + + constexpr size_t BYTE_INDEX = 2; + uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + BYTE_INDEX, + l_raw_byte); + + // Find map value + bool l_is_val_found = mss::find_value_from_key(DRAM_GEN_MAP, l_raw_byte, o_value); + + FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, + l_is_val_found, + BYTE_INDEX, + l_raw_byte, + "Failed check on SPD dram device type") ); + // Print decoded info + FAPI_INF("%s Device type : %d", + c_str(i_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Object factory to select correct decoder +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data +/// @param[out] o_fact_obj shared pointer to the factory object +/// @return FAPI2_RC_SUCCESS if okay +/// @note Factory dependent on SPD revision & dimm type +/// +fapi2::ReturnCode factory(const fapi2::Target& i_target, + const std::vector& i_spd_data, + std::shared_ptr& o_fact_obj) +{ + if( i_spd_data.empty() ) + { + // This won't work with no data + return fapi2::FAPI2_RC_INVALID_PARAMETER; + } + + const auto l_mcs = mss::find_target(i_target); + const auto l_port_num = index( find_target(i_target) ); + const auto l_dimm_num = index(i_target); + uint8_t l_dimm_type = 0; + + { + // Get dimm type & set attribute (needed by c_str) + uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + FAPI_TRY( base_module_type(i_target, i_spd_data, l_dimm_type), + "Failed to find base module type" ); + FAPI_TRY( eff_dimm_type(l_mcs, &l_dimm_types_mcs[0][0]) ); + + l_dimm_types_mcs[l_port_num][l_dimm_num] = l_dimm_type; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_TYPE, l_mcs, l_dimm_types_mcs) ); + } + + { + // Get dram generation & set attribute (needed by c_str) + uint8_t l_dram_gen = 0; + uint8_t l_dram_gen_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + FAPI_TRY( eff_dram_gen(l_mcs, &l_dram_gen_mcs[0][0]) ); + FAPI_TRY( dram_device_type(i_target, i_spd_data, l_dram_gen), + "Failed to find base module type" ); + + l_dram_gen_mcs[l_port_num][l_dimm_num] = l_dram_gen; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, l_mcs, l_dram_gen_mcs) ); + } + + { + std::shared_ptr l_module_decoder; + uint8_t l_encoding_rev = 0; + uint8_t l_additions_rev = 0; + + // Get revision levels + FAPI_TRY( rev_encoding_level(i_target, i_spd_data, l_encoding_rev), + "Failed to find encoding level" ); + FAPI_TRY( rev_additions_level(i_target, i_spd_data, l_additions_rev), + "Failed to find additons level" ); + + // Get decoder object needed for current dimm type and spd rev + switch(l_dimm_type) + { + // Each dimm type rev is independent + case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM: + + // SPD Revision format #.# + // 1st # = encoding level + // 2nd # = additions level + switch(l_encoding_rev) + { + // Skipping case 0 since we shouldn't be using pre-production revisions + case 1: + switch(l_additions_rev) + { + // Rev 1.0 + case 0: + // Life starts out at base revision level + l_module_decoder = std::make_shared(i_target, i_spd_data); + o_fact_obj = std::make_shared( i_target, i_spd_data, l_module_decoder ); + break; + + case 1: + // Rev 1.1 + // Changes to both the general section & rdimm section occured + l_module_decoder = std::make_shared(i_target, i_spd_data); + o_fact_obj = std::make_shared( i_target, i_spd_data, l_module_decoder ); + break; + + default: + FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, + l_dimm_type, + l_encoding_rev, + l_additions_rev, + "Additions Level Unsupported!") ); + break; + }//end additions + + break; + + default: + FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, + l_dimm_type, + l_encoding_rev, + l_additions_rev, + "Encoding Level Unsupported!") ); + break; + }// end encodings + + break; + + default: + FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, + l_dimm_type, + l_encoding_rev, + l_additions_rev, + "DIMM Type Unsupported!") ); + break; + + } // end dimm type + + FAPI_INF("%s: Decoder created SPD revision %d.%d", + c_str(i_target), + l_encoding_rev, + l_additions_rev); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Creates factory object & SPD data caches +/// @param[in] i_target controller target +/// @param[out] o_factory_caches map of factory objects with a dimm position key +/// @return FAPI2_RC_SUCCESS if okay +/// @note This specialization is suited for creating a cache with platform +/// SPD data. +/// +template<> +fapi2::ReturnCode populate_decoder_caches( const fapi2::Target& i_target, + std::map >& o_factory_caches, + const std::shared_ptr& i_pDecoder) +{ + // Input decoder for this version of populating cache would get overriden + // so I don't bother with it here + std::shared_ptr l_pDecoder; + + for( const auto& l_dimm : find_targets(i_target) ) + { + size_t l_size = 0; + FAPI_TRY( fapi2::getSPD(l_dimm, nullptr, l_size) ); + + { + // "Container" for SPD data + std::vector l_spd(l_size); + + // Retrive SPD data + FAPI_TRY( fapi2::getSPD(l_dimm, l_spd.data(), l_size) ); + + // Retrieve factory object instance & populate spd data for that instance + FAPI_TRY( factory(l_dimm, l_spd, l_pDecoder) ); + + // Populate spd caches maps based on dimm pos + o_factory_caches.emplace( std::make_pair( pos(l_dimm), l_pDecoder ) ); + } + + }// end dimm + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Creates factory object & SPD data caches +/// @param[in] i_target the dimm target +/// @param[out] o_factory_caches map of factory objects with a dimm position key +/// @return FAPI2_RC_SUCCESS if okay +/// @note This specialization is suited for creating a cache with custom +/// SPD data (e.g. testing custom SPD). +/// +template<> +fapi2::ReturnCode populate_decoder_caches( const fapi2::Target& i_target, + std::map >& o_factory_caches, + const std::shared_ptr& i_pDecoder) +{ + if(i_pDecoder == nullptr) + { + // This won't work w/a null parameter + return fapi2::FAPI2_RC_INVALID_PARAMETER; + } + + // This shouldn't be null so there is a specific decoder we are wanting to populate + std::shared_ptr l_pDecoder(i_pDecoder); + + // Custom decoder provided (usually done for testing) + // Populate custom spd caches maps one dimm at a time + o_factory_caches.emplace( std::make_pair( pos(i_target), l_pDecoder ) ); + + // TK - else what do we want here + return fapi2::FAPI2_RC_SUCCESS; +} + +}// spd +}// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H new file mode 100644 index 000000000..d0113227e --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H @@ -0,0 +1,139 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file spd_factory.H +/// @brief SPD factory and functions +/// +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Brian Silver +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_SPD_FACTORY_H_ +#define _MSS_SPD_FACTORY_H_ + +// std lib +#include +#include +#include + +// fapi2 +#include + +// mss lib +#include + +namespace mss +{ +namespace spd +{ + +/// +/// @brief Decodes SPD Revision encoding level +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data +/// @param[out] o_value encoding revision num +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 1 (3~0). +/// @note Item JC-45-2220.01x +/// @note Page 14-15 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode rev_encoding_level(const fapi2::Target& i_target, + const std::vector& i_spd_data, + uint8_t& o_value); +/// +/// @brief Decodes SPD Revision additions level +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD blob +/// @param[out] o_value additions revision num +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 1 (bits 7~4). +/// @note Item JC-45-2220.01x +/// @note Page 14-15 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode rev_additions_level(const fapi2::Target& i_target, + const std::vector& i_spd_data, + uint8_t& o_value); + +/// +/// @brief Decodes base module type (DIMM type) from SPD +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data +/// @param[out] o_value base module type +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 3 (bits 3~0) +/// @note Item JC-45-2220.01x +/// @note Page 17 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode base_module_type(const fapi2::Target& i_target, + const std::vector& i_spd_data, + uint8_t& o_value); +/// +/// @brief Decodes DRAM Device Type +/// @param[in] i_target dimm target +/// @param[out] o_value dram device type enumeration +/// @return FAPI2_RC_SUCCESS if okay +/// @note Decodes SPD Byte 2 +/// @note Item JC-45-2220.01x +/// @note Page 16 +/// @note DDR4 SPD Document Release 3 +/// +fapi2::ReturnCode dram_device_type(const fapi2::Target& i_target, + const std::vector& i_spd_data, + uint8_t& o_value); + +/// +/// @brief Object factory to select correct decoder +/// @param[in] i_target dimm target +/// @param[in] i_spd_data SPD data +/// @param[out] o_fact_obj shared pointer to the factory object +/// @return FAPI2_RC_SUCCESS if okay +/// @note Factory dependent on SPD revision & dimm type +/// +fapi2::ReturnCode factory(const fapi2::Target& i_target, + const std::vector& i_spd_data, + std::shared_ptr& o_fact_obj); + +/// +/// @brief Creates factory object & SPD data caches +/// @param[in] i_target the fapi2 target +/// @param[out] o_factory_caches map of factory objects with a dimm position key +/// @param[in] i_pDecoder optional input decoder to insert custom decoder, defaulted to nullptr +/// @return FAPI2_RC_SUCCESS if okay +/// +template +fapi2::ReturnCode populate_decoder_caches(const fapi2::Target& i_target, + std::map< uint32_t, std::shared_ptr >& o_factory_caches, + const std::shared_ptr& i_pDecoder = nullptr); + + +}// spd +}// mss + +#endif //_MSS_SPD_FACTORY_H_ diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/checker.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/checker.H index 934b61cdc..8e255f7c9 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/checker.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/checker.H @@ -169,7 +169,7 @@ inline void warn_for_invalid_value(const fapi2::Target& const T i_spd_data, const char* i_err_str) { - // Don't print warning conditional is true + // Don't print warning conditional if true if(!i_conditional) { FAPI_IMP("%s. %s. Byte %d, Data returned: %d.", diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C index 89366ee8b..40ddaa572 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C @@ -32,14 +32,20 @@ // *HWP Team: Memory // *HWP Level: 2 // *HWP Consumed by: FSP:HB + +#include + +// std #include -#include +// fapi2 #include -#include -#include -#include + +// mss lib +#include +#include #include +#include #include #include diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C index 3bd5288fc..562b797c2 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C @@ -36,13 +36,17 @@ //---------------------------------------------------------------------- // Includes //---------------------------------------------------------------------- -#include -#include +#include + +// std lib +#include +// fapi2 #include -#include -#include -#include + +// mss lib +#include +#include #include #include #include diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C index 87d41ffda..4673896ef 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C @@ -34,13 +34,23 @@ // *HWP Level: 2 // *HWP Consumed by: FSP:HB +#include +// std lib +#include +#include +// fapi2 #include -#include -#include -#include +// mss lib +#include +#include +#include +#include +#include +#include +#include using fapi2::TARGET_TYPE_MCBIST; using fapi2::TARGET_TYPE_MCS; diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.H b/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.H index 2172af81b..15a75a1a6 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.H +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.H @@ -39,8 +39,6 @@ #include #include -#include -#include typedef fapi2::ReturnCode (*p9_mss_volt_FP_t) (const std::vector >&); diff --git a/src/import/chips/p9/procedures/hwp/memory/tests/mss_rdimm_decoder_ut.C b/src/import/chips/p9/procedures/hwp/memory/tests/mss_rdimm_decoder_ut.C new file mode 100644 index 000000000..8643a2c6c --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/tests/mss_rdimm_decoder_ut.C @@ -0,0 +1,581 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/tests/mss_rdimm_decoder_ut.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file mss_spd_ut.C +/// @brief Unit tests for spd decoder api +/// +// *HWP HWP Owner: Andre Marin +// *HWP FW Owner: Brian Silver +// *HWP Team: Memory +// *HWP Level: 4 +// *HWP Consumed by: CI + +#include +#include + +#include +#include + +#include +#include +#include +#include + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_DIMM; + +namespace mss +{ +namespace test +{ + +// Blob of "bad" SPD data used for unit testing +// Involves using key-byte values that are not in the SPD maps +static constexpr uint8_t BAD_SPD[] = +{ + +// Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7 + 0x35, 0xFF, 0x07, 0x45, 0xDA, 0x3F, 0x83, 0x3A, + +// Byte 8 Byte 9 Byte 10 Byte 11 Byte 12 Byte 13 Byte 14 Byte 15 + uint8_t(~0), 0xD0, 0xFF, 0x00, 0x04, 0x1F, 0x80, 0x01, + +// Byte 16 Byte 17 Byte 18 Byte 19 Byte 20 Byte 21 Byte 22 Byte 23 + uint8_t(~0), 0x0F, 0x00, 0x00, 0x01, 0x01, 0x01, 0x40, + +// Byte 24 Byte 25 Byte 26 Byte 27 Byte 28 Byte 29 Byte 30 Byte 31 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 32 Byte 33 Byte 34 Byte 35 Byte 36 Byte 37 Byte 38 Byte 39 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 40 Byte 41 Byte 42 Byte 43 Byte 44 Byte 45 Byte 46 Byte 47 + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + +// Byte 48 Byte 49 Byte 50 Byte 51 Byte 52 Byte 53 Byte 54 Byte 55 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 56 Byte 57 Byte 58 Byte 59 Byte 60 Byte 61 Byte 62 Byte 63 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 64 Byte 65 Byte 66 Byte 67 Byte 68 Byte 69 Byte 70 Byte 71 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 72 Byte 73 Byte 74 Byte 75 Byte 76 Byte 77 Byte 78 Byte 79 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 80 Byte 81 Byte 82 Byte 83 Byte 84 Byte 85 Byte 86 Byte 87 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 88 Byte 89 Byte 90 Byte 91 Byte 92 Byte 93 Byte 94 Byte 95 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 96 Byte 97 Byte 98 Byte 99 Byte 100 Byte 101 Byte 102 Byte 103 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 104 Byte 105 Byte 106 Byte 107 Byte 108 Byte 109 Byte 110 Byte 111 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +// Byte 112 Byte 113 Byte 114 Byte 115 Byte 116 Byte 117 Byte 118 Byte 119 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, + +//Byte 120 Byte 121 Byte 122 Byte 123 Byte 124 Byte 125 Byte 126 Byte 127 + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFE, + +//Byte 128 Byte 129 Byte 130 Byte 131 Byte 132 Byte 133 Byte 134 Byte 135 + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFE, + +//Byte 136 Byte 137 Byte 138 Byte 139 Byte 140 Byte 141 Byte 142 Byte 143 + 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0xFE, + + + // add rest here +}; + +/// +/// @brief Unit test cases for SPD Decoder +/// @param[in] test_fixture, description, tag +/// @return void +/// @note mcbist_target_test_fixture is the fixture to use with this test case +/// +SCENARIO_METHOD(mcbist_target_test_fixture, "Verify RDIMM SPD Decoding", "[rdimm_decoder]") +{ + ////////////////////////////// + // SPD Byte 128~191. Module-Specific Section + ///////////////////////////// + + GIVEN("Passing test cases w/valid VBU SPD data (rev 1.0)") + { + //Loops over MCBIST targets that were defined in the associated config + for_each_target([](const fapi2::Target& i_target) + { + for( const auto& l_dimm : mss::find_targets(i_target) ) + { + size_t l_read_spd_size = 0; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Enforce requirements + REQUIRE(l_read_spd_size == 0); + REQUIRE_FALSE(fapi2::current_err); + + // Get the SPD size + REQUIRE_FALSE(getSPD(l_dimm, nullptr, l_read_spd_size)); + + // "Container" for SPD data + std::vector l_spd(l_read_spd_size, 0); + + // Retrive SPD data + REQUIRE_FALSE(getSPD(l_dimm, l_spd.data(), l_read_spd_size)); + + // Create RDIMM decoder w/good VBU SPD Data + mss::spd::rdimm_decoder_v1_0 l_decoder(l_dimm, l_spd); + + { + ////////////////////////////// + /// SPD Byte 128 (Bits 4~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 17; // from VBU fake SPD + + REQUIRE_FALSE( l_decoder.max_module_nominal_height(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 128 (Bits 7~5) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x1; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.raw_card_extension(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 129 (Bits 3~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x1; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.front_module_max_thickness(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 129 (Bits 7~4) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x1; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.back_module_max_thickness(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 130 (Bits 4~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x3; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.reference_raw_card(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 130 (Bits 6~5) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x1; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.reference_raw_card_rev(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 130 (Bit 7) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.reference_raw_card_extension(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 131 (Bits 1~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x1; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.num_registers_used(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 131 (Bits 3~2) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x1; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.num_rows_of_drams(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 132 (Bits 6~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.heat_spreader_thermal_char( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 132 (Bit 7) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.heat_spreader_solution( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 133 (Bits 6~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.num_continuation_codes( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 134 (Bits 7~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0xB3; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.manufacturer_id_code(l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 135 (Bits 7~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x30; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.register_rev_num( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 136 (Bit 0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.register_to_dram_addr_mapping( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 1~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.cke_signal_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 3~2) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.odt_signal_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 5~4) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.ca_signal_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 7~6) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.cs_signal_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 138 (Bits 1~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.b_side_clk_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 138 (Bits 3~2) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.a_side_clk_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + }// dimm + + return 0; + }); + + }// GIVEN + + GIVEN("FAILING test cases w/invalid SPD data (rev 1.0)") + { + //Loops over MCBIST targets that were defined in the associated config + for_each_target([](const fapi2::Target& i_target) + { + for( const auto& l_dimm : mss::find_targets(i_target) ) + { + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + uint8_t l_decoder_output = 0; + std::vector l_spd( std::begin(BAD_SPD), std::end(BAD_SPD) ); + + // Enforce requirements + REQUIRE_FALSE(fapi2::current_err); + REQUIRE(0 == l_decoder_output); + + // Create RDIMM decoder w/BAD VBU SPD Data + mss::spd::rdimm_decoder_v1_0 l_decoder(l_dimm, l_spd); + + ////////////////////////////// + /// SPD Byte 128 - 136 + ///////////////////////////// + + // All bits are used for encoding + // All bit combinations are valid + // Any errors will be caught in the previous test case + // What this means is that I CAN'T inject invalid SPD + // to make it fail + ////////////////////////////// + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 1~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + REQUIRE( l_decoder.cke_signal_output_driver( l_decoder_output) ); + + // Output should never return JEDEC RESERVED encoding value + REQUIRE( 0 == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 3~2) + ///////////////////////////// + uint8_t l_decoder_output = 0; + REQUIRE( l_decoder.odt_signal_output_driver( l_decoder_output) ); + + // Output should never return JEDEC RESERVED encoding value + REQUIRE( 0 == l_decoder_output); + } + + ////////////////////////////// + /// SPD Byte 137 (Bits 5~4) + ///////////////////////////// + + // All bits are used for encoding + // All bit combinations are valid + // Any errors will be caught in the previous test case + // What this means is that I CAN'T inject invalid SPD + // to make it fail + ////////////////////////////// + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 7~6) + ///////////////////////////// + uint8_t l_decoder_output = 0; + REQUIRE( l_decoder.cs_signal_output_driver( l_decoder_output) ); + + // Output should remain unchanged + REQUIRE( 0 == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 138 (Bits 1~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + REQUIRE( l_decoder.b_side_clk_output_driver( l_decoder_output) ); + + // Output should remain unchanged + REQUIRE( 0 == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 138 (Bits 3~2) + ///////////////////////////// + uint8_t l_decoder_output = 0; + REQUIRE( l_decoder.a_side_clk_output_driver( l_decoder_output) ); + + // Output should remain unchanged + REQUIRE( 0 == l_decoder_output); + } + + }// dimm + + return 0; + }); + + }// GIVEN + + GIVEN("Passing test cases w/valid VBU SPD data (rev 1.1)") + { + //Loops over MCBIST targets that were defined in the associated config + for_each_target([](const fapi2::Target& i_target) + { + for( const auto& l_dimm : mss::find_targets(i_target) ) + { + size_t l_read_spd_size = 0; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Enforce requirements + REQUIRE(l_read_spd_size == 0); + REQUIRE_FALSE(fapi2::current_err); + + // Get the SPD size + REQUIRE_FALSE(getSPD(l_dimm, nullptr, l_read_spd_size)); + + // "Container" for SPD data + std::vector l_spd(l_read_spd_size, 0); + + // Retrive SPD data + REQUIRE_FALSE(getSPD(l_dimm, l_spd.data(), l_read_spd_size)); + + // Create RDIMM decoder w/good VBU SPD Data + mss::spd::rdimm_decoder_v1_0 l_decoder(l_dimm, l_spd); + + ////////////////////////////// + /// SPD Byte 128 - 136 + ///////////////////////////// + + // Remain unchanged from previous rev so + // tests from rev 1.0 still valid due to inheritane + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 1~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.cke_signal_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 3~2) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.odt_signal_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + + { + ////////////////////////////// + /// SPD Byte 137 (Bits 7~6) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.cs_signal_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 138 (Bits 1~0) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.b_side_clk_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + { + ////////////////////////////// + /// SPD Byte 138 (Bits 3~2) + ///////////////////////////// + uint8_t l_decoder_output = 0; + uint8_t l_expected = 0x0; // from VBU fake SPD + REQUIRE_FALSE( l_decoder.a_side_clk_output_driver( l_decoder_output) ); + REQUIRE( l_expected == l_decoder_output); + } + + ///////////////////////////////// + // SPD Bytes 137 - 138 for rev 1.1 + ///////////////////////////////// + // All bits are used for encoding + // All bit combinations are valid + // Any errors will be caught in the previous test case + // What this means is that I CAN'T inject invalid SPD + // to make it fail + ////////////////////////////// + + }// dimm + + return 0; + }); + + }// GIVEN + +}//scenario + +} /* ns test */ +} /* ns mss */ -- cgit v1.2.1