summaryrefslogtreecommitdiffstats
path: root/src/import/chips
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2016-08-05 11:40:28 -0500
committerWilliam G. Hoffa <wghoffa@us.ibm.com>2016-08-22 13:42:43 -0400
commit984f7f35a02e4894c8cb448223bea8d53b64f459 (patch)
tree654bf5a9986160ac7f990e963547d72f7055042e /src/import/chips
parenta840da561aa1f3bfabcf4b2aa7a8ffea3327e600 (diff)
downloadtalos-hostboot-984f7f35a02e4894c8cb448223bea8d53b64f459.tar.gz
talos-hostboot-984f7f35a02e4894c8cb448223bea8d53b64f459.zip
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 <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Brian R. Silver <bsilver@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/28199 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/import/chips')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C123
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H44
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C7
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H7
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C2858
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H1454
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder_v1_1.C910
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder.H796
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C819
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_1.C236
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C4155
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.H1200
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C492
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H139
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/utils/checker.H2
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C14
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C14
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C16
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.H2
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/tests/mss_rdimm_decoder_ut.C581
20 files changed, 8344 insertions, 5525 deletions
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 <fapi2.H>
#include <vpd_access.H>
-#include <mss.H>
-#include <lib/mss_vpd_decoder.H>
+// mss lib
#include <lib/eff_config/eff_config.H>
+#include <lib/mss_vpd_decoder.H>
+#include <lib/spd/spd_factory.H>
+#include <lib/spd/common/spd_decoder.H>
#include <lib/eff_config/timing.H>
-#include <lib/spd/spd_decoder.H>
#include <lib/dimm/rank.H>
#include <lib/utils/conversions.H>
-
#include <lib/utils/fake_vpd.H>
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<TARGET_TYPE_DIMM>& i_target,
- const std::shared_ptr<spd::decoder>& 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<TARGET_TYPE_DIMM>& i_target,
- const std::shared_ptr<spd::decoder>& 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<TARGET_TYPE_DIMM>& i_target,
- const std::shared_ptr<spd::decoder>& 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::Target<TARGET_TYPE_DIM
// Get & update MCS attribute
FAPI_TRY( eff_num_ranks_per_dimm(l_mcs, &l_attrs_ranks_per_dimm[0][0]) );
- FAPI_TRY( logical_ranks_per_dimm(i_target, iv_pDecoder, l_ranks_per_dimm) );
+ FAPI_TRY( iv_pDecoder->logical_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<TARGET_TYPE_DIMM>& 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::Target<TARGET_TYPE_DIM
uint8_t l_attrs_bank_bits[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {};
FAPI_TRY( eff_dram_bank_bits(l_mcs, &l_attrs_bank_bits[0][0]) );
- FAPI_TRY( iv_pDecoder->banks(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 <fapi2.H>
+// std lib
#include <cstdint>
-#include <lib/spd/spd_decoder.H>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <lib/spd/common/spd_decoder.H>
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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::shared_ptr<spd::decoder>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::shared_ptr<spd::decoder>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::shared_ptr<spd::decoder>& 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 <limits.h>
#include <algorithm>
+// fapi2
#include <fapi2.H>
-#include <mss.H>
+
+// mss lib
+#include <lib/spd/common/spd_decoder.H>
#include <lib/freq/cas_latency.H>
#include <lib/freq/cycle_time.H>
#include <lib/utils/conversions.H>
#include <lib/eff_config/timing.H>
#include <lib/utils/find.H>
+#include <lib/utils/checker.H>
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 <map>
#include <memory>
#include <cstdint>
+// fapi2
#include <fapi2.H>
-#include <lib/spd/spd_decoder.H>
+
+// mss lib
+#include <lib/spd/common/spd_decoder.H>
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 <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// std lib
+#include <map>
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <lib/spd/common/spd_decoder.H>
+#include <lib/spd/rdimm/rdimm_decoder.H>
+#include <lib/utils/checker.H>
+#include <lib/utils/c_str.H>
+#include <lib/utils/find.H>
+
+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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ const std::shared_ptr<dimm_module_decoder>& 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint16_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint16_t> > 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint32_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint32_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, int64_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, int64_t> > 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<uint64_t> l_buffer;
+
+ l_buffer.insertFromRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(first_raw_byte)
+ .insertFromRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(sec_raw_byte)
+ .insertFromRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(third_raw_byte)
+ .insertFromRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRASmin_MSN )
+ .insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRCmin_MSN )
+ .insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC1min_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC2min_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC4min_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tFAWmin_MSN ).
+ insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<uint16_t> l_buffer;
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( crc_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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 <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_SPD_DECODER_H_
+#define _MSS_SPD_DECODER_H_
+
+// std lib
+#include <cstdint>
+#include <map>
+#include <memory>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <lib/spd/rdimm/rdimm_decoder.H>
+#include <lib/utils/c_str.H>
+
+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<uint8_t I, uint8_t S, uint8_t L>
+inline uint8_t extract_spd_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_spd_data[I]);
+
+ // Extracting desired bits
+ uint8_t l_field_bits = 0;
+ l_buffer.extractToRight<S, L>(l_field_bits);
+
+ return l_field_bits;
+}
+
+///
+/// @class decoder
+/// @brief Base SPD DRAM decoder
+///
+class decoder
+{
+ public:
+ std::shared_ptr<dimm_module_decoder> iv_module_decoder;
+ std::vector<uint8_t> 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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ const std::shared_ptr<dimm_module_decoder>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ uint8_t& o_logical_rank_per_dimm) ;
+
+ protected:
+ // TODO RTC:159362
+ const fapi2::Target<fapi2::TARGET_TYPE_DIMM> 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ const std::shared_ptr<dimm_module_decoder>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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 <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <lib/spd/common/spd_decoder.H>
+#include <lib/utils/checker.H>
+#include <lib/utils/c_str.H>
+#include <lib/utils/conversions.H>
+#include <lib/utils/find.H>
+
+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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ const std::shared_ptr<dimm_module_decoder>& 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<TARGET_TYPE_DIMM>& 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<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<std::pair<uint8_t, uint8_t> > 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<uint64_t> l_buffer;
+
+ l_buffer.insertFromRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(first_raw_byte)
+ .insertFromRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(sec_raw_byte)
+ .insertFromRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(third_raw_byte)
+ .insertFromRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(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<BIT_START, BIT_LEN>()),
+ 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<TARGET_TYPE_DIMM>& 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<int64_t> l_buffer;
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRmin_MSN ).
+ insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRT_Smin_MSN )
+ .insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRT_Lmin_MSN )
+ .insertFromRight<LSB_START, LSB_LEN>( 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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 <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_RDIMM_DECODER_H_
+#define _MSS_RDIMM_DECODER_H_
+
+#include <fapi2.H>
+#include <cstdint>
+
+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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM> iv_target;
+ const std::vector<uint8_t> 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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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 <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// std lib
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <lib/spd/rdimm/rdimm_decoder.H>
+#include <lib/spd/common/spd_decoder.H>
+#include <lib/utils/checker.H>
+#include <lib/utils/c_str.H>
+#include <lib/utils/find.H>
+
+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<BYTE_INDEX, MODULE_NOM_HEIGHT_START, MODULE_NOM_HEIGHT_LEN>(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<BYTE_INDEX, FRONT_MODULE_THICKNESS_START, FRONT_MODULE_THICKNESS_LEN>
+ (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<BYTE_INDEX, BACK_MODULE_THICKNESS_START, BACK_MODULE_THICKNESS_LEN>(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<BYTE_INDEX, RAW_CARD_EXT_START, RAW_CARD_EXT_LEN>(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<BYTE_INDEX, REF_RAW_CARD_START, REF_RAW_CARD_LEN>(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<BYTE_INDEX, REF_RAW_CARD_REV_START, REF_RAW_CARD_REV_LEN>(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<BYTE_INDEX, REF_RAW_CARD_EXT_START, REF_RAW_CARD_EXT_LEN>(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<BYTE_INDEX, REGS_USED_START, REGS_USED_LEN>(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<BYTE_INDEX, ROWS_OF_DRAMS_START, ROWS_OF_DRAMS_LEN>(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<BYTE_INDEX, HEAT_SPREADER_CHAR_START, HEAT_SPREADER_CHAR_LEN>(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<BYTE_INDEX, HEAT_SPREADER_SOL_START, HEAT_SPREADER_SOL_LEN>(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<BYTE_INDEX, CONTINUATION_CODES_START, CONTINUATION_CODES_LEN>(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<BYTE_INDEX, ADDR_MAPPING_START, ADDR_MAPPING_LEN>(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<BYTE_INDEX, CKE_DRIVER_START, CKE_DRIVER_LEN>(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<BYTE_INDEX, ODT_DRIVER_START, ODT_DRIVER_LEN>(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<BYTE_INDEX, CA_DRIVER_START, CA_DRIVER_LEN>(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<BYTE_INDEX, CS_DRIVER_START, CS_DRIVER_LEN>(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<BYTE_INDEX, YO_Y2_DRIVER_START, YO_Y2_DRIVER_LEN>(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<BYTE_INDEX, Y1_Y3_DRIVER_START, Y1_Y3_DRIVER_LEN>(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 <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <lib/spd/rdimm/rdimm_decoder.H>
+#include <lib/spd/common/spd_decoder.H>
+#include <lib/utils/checker.H>
+#include <lib/utils/c_str.H>
+#include <lib/utils/find.H>
+
+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<BYTE, CKE_DRIVER_START, CKE_DRIVER_LEN>(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<BYTE, ODT_DRIVER_START, ODT_DRIVER_LEN>(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<BYTE, CS_DRIVER_START, CS_DRIVER_LEN>(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<BYTE, YO_Y2_DRIVER_START, YO_Y2_DRIVER_LEN>(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<BYTE, Y1_Y3_DRIVER_START, Y1_Y3_DRIVER_LEN>(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 <aamarin@us.ibm.com>
-// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
-// *HWP Team: Memory
-// *HWP Level: 2
-// *HWP Consumed by: HB:FSP
-#include <map>
-#include <vector>
-
-#include <fapi2.H>
-#include <fapi2_spd_access.H>
-
-#include <lib/utils/checker.H>
-#include <lib/utils/c_str.H>
-#include <lib/spd/spd_decoder.H>
-#include <lib/utils/conversions.H>
-#include <lib/utils/find.H>
-
-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<std::pair<uint8_t, uint16_t> > BYTES_USED_MAP =
-{
- //{key byte, number of used bytes}
- {1, 128},
- {2, 256},
- {3, 384},
- {4, 512}
-};
-
-
-static const std::vector<std::pair<uint8_t, uint16_t> > 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<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > BANK_ADDR_BITS_MAP =
-{
- // {key byte, number of bank address bits}
- {0, 2},
- {1, 3}
-};
-
-static const std::vector<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > COLUMN_ADDRESS_BITS_MAP =
-{
- //{key byte,col address bits}
- {0, 9},
- {1, 10},
- {2, 11},
- {3, 12}
-};
-
-static const std::vector<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > PRIM_SIGNAL_LOADING_MAP =
-{
- // {key byte, signal loading}
- {0, UNSPECIFIED},
- {1, MULTI_LOAD_STACK},
- {2, SINGLE_LOAD_STACK}
-};
-
-static const std::vector<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint32_t> > 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<std::pair<uint8_t, uint32_t> > 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<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > SEC_SIGNAL_LOADING_MAP =
-{
- // {key byte, signal loading}
- {0, UNSPECIFIED},
- {1, MULTI_LOAD_STACK},
- {2, SINGLE_LOAD_STACK}
-};
-
-static const std::vector<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > ENDURANT_MAP =
-{
- // {key byte, value }
- {0, NOT_ENDURANT},
- {1, ENDURANT}
-};
-
-static const std::vector<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > DEVICE_WIDTH_MAP =
-{
- // {key byte, device width (bits)}
- {0, 4},
- {1, 8},
- {2, 16},
- {3, 32},
- // All others reserved
-};
-
-static const std::vector<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, uint8_t> > BUS_WIDTH_MAP =
-{
- // {key byte, bus width (in bits)
- {0, 8},
- {1, 16},
- {2, 32},
- {3, 64}
- // All others reserved
-};
-
-static const std::vector<std::pair<uint8_t, uint8_t> > 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<std::pair<uint8_t, int64_t> > MEDIUM_TIMEBASE_MAP =
-{
- // {key byte, medium timebase (in picoseconds)
- {0, 125}
- // All others reserved
-};
-
-static const std::vector<std::pair<uint8_t, int64_t> > 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> 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<ENCODING_LEVEL_START, ENCODING_LEVEL_LEN>(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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> 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<ADDITIONS_LEVEL_START, ADDITIONS_LEVEL_LEN>(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<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> 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<BASE_MODULE_START, BASE_MODULE_LEN>(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<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& i_spd_data,
- std::shared_ptr<decoder>& 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<TARGET_TYPE_MCS>(i_target);
- const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(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<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
-
- // 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<TARGET_TYPE_MCS>& i_target,
- std::map<uint32_t, std::shared_ptr<decoder> >& o_factory_caches,
- const std::shared_ptr<decoder>& i_pDecoder)
-{
- // Input decoder for this version of populating cache would get overriden
- // so I don't bother with it here
- std::shared_ptr<decoder> l_pDecoder;
-
- for( const auto& l_mca : i_target.getChildren<TARGET_TYPE_MCA>() )
- {
- for( const auto& l_dimm : l_mca.getChildren<TARGET_TYPE_DIMM>() )
- {
- size_t l_size = 0;
- FAPI_TRY( fapi2::getSPD(l_dimm, nullptr, l_size) );
-
- {
- // "Container" for SPD data
- std::vector<uint8_t> 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<TARGET_TYPE_DIMM>& i_target,
- std::map<uint32_t, std::shared_ptr<decoder> >& o_factory_caches,
- const std::shared_ptr<decoder>& 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<decoder> 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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<BYTES_USED_START, BYTES_USED_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<BYTES_TOTAL_START, BYTES_TOTAL_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<HYBRID_MEDIA_START, HYBRID_MEDIA_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<HYBRID_START, HYBRID_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(iv_spd_data[BYTE_INDEX]);
- l_spd_buffer.extractToRight<SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(iv_spd_data[BYTE_INDEX]);
- l_spd_buffer.extractToRight<SDRAM_BANKS_START, SDRAM_BANKS_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(iv_spd_data[BYTE_INDEX]);
- l_spd_buffer.extractToRight<BANK_GROUP_START, BANK_GROUP_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(iv_spd_data[BYTE_INDEX]);
- l_spd_buffer.extractToRight<COL_ADDRESS_START, COL_ADDRESS_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(iv_spd_data[BYTE_INDEX]);
- l_spd_buffer.extractToRight<ROW_ADDRESS_START, ROW_ADDRESS_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<PRIM_SIGNAL_LOAD_START, PRIM_SIGNAL_LOAD_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<PRIM_DIE_COUNT_START, PRIM_DIE_COUNT_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<PRIM_PACKAGE_TYPE_START, PRIM_PACKAGE_TYPE_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<MAC_START, MAC_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<TMAW_START, TMAW_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<SOFT_PPR_START, SOFT_PPR_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> 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<PPR_START, PPR_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<SEC_SIGNAL_LOAD_START, SEC_SIGNAL_LOAD_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<DENSITY_RATIO_START, DENSITY_RATIO_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> 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<SEC_DIE_COUNT_START, SEC_DIE_COUNT_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<SEC_PACKAGE_TYPE_START, SEC_PACKAGE_TYPE_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<OPERABLE_START, OPERABLE_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<ENDURANT_START, ENDURANT_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- uint8_t l_field_bits = 0;
- l_spd_buffer.extractToRight<SDRAM_WIDTH_START, SDRAM_WIDTH_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- uint8_t l_field_bits = 0;
- l_spd_buffer.extractToRight<PACKAGE_RANKS_START, PACKAGE_RANKS_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<RANK_MIX_START, RANK_MIX_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- uint8_t l_field_bits = 0;
- l_spd_buffer.extractToRight<BUS_WIDTH_START, BUS_WIDTH_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<BUS_EXT_WIDTH_START, BUS_EXT_WIDTH_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<THERM_SENSOR_START, THERM_SENSOR_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
-
- l_spd_buffer.extractToRight<EXT_MOD_TYPE_START, EXT_MOD_TYPE_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<FINE_TIMEBASE_START, FINE_TIMEBASE_LEN>(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<TARGET_TYPE_DIMM>& 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<uint8_t> l_spd_buffer(l_raw_byte);
- l_spd_buffer.extractToRight<MED_TIMEBASE_START, MED_TIMEBASE_LEN>(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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<uint64_t> l_buffer;
-
- l_buffer.insertFromRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(first_raw_byte)
- .insertFromRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(sec_raw_byte)
- .insertFromRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(third_raw_byte)
- .insertFromRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(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<BIT_START, BIT_LEN>()),
- FOURTH_BYTE,
- fourth_raw_byte,
- "Failed check on CAS latencies supported") );
-
- // Update output value only if range check passes
- l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& i_target,
- int64_t& o_value)
-{
- // Lambda expression to retrieve tRASmin's most significant nibble (MSN)
- auto tRASmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- l_buffer.extractToRight<TRASMIN_MSN_START, TRASMIN_MSN_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve tRASmin's least significant byte (LSB)
- auto tRASmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- l_buffer.extractToRight<TRASMIN_LSB_START, TRASMIN_LSB_LEN>(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<int64_t> l_buffer;
-
- l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRASmin_MSN(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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<TARGET_TYPE_DIMM>& i_target,
- int64_t& o_value)
-{
- // Lambda expression to retrieve tRCmin's most significant nibble (MSN)
- auto tRCmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TRCMIN_MSN_START, TRCMIN_MSN_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve tRCmin's least significant byte (LSB)
- auto tRCmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- l_buffer.extractToRight<TRCMIN_LSB_START, TRCMIN_LSB_LEN>(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<int64_t> l_buffer;
-
- l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRCmin_MSN(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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<TARGET_TYPE_DIMM>& i_target,
- int64_t& o_value)
-{
- // Lambda expression to retrieve tRFC1min's most significant byte (MSB)
- auto tRFC1min_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TRFC1MIN_MSB_START, TRFC1MIN_MSB_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve tRFC1min's least significant byte (LSB)
- auto tRFC1min_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TRFC1MIN_LSB_START, TRFC1MIN_LSB_LEN>(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<int64_t> l_buffer;
-
- l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC1min_MSB(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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<TARGET_TYPE_DIMM>& i_target,
- int64_t& o_value)
-{
- // Lambda expression to retrieve tRFC2min's most significant byte (MSB)
- auto tRFC2min_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- l_buffer.extractToRight<TRFC2MIN_MSB_START, TRFC2MIN_MSB_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve tRFC2min's least significant byte (LSB)
- auto tRFC2min_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TRFC2MIN_LSB_START, TRFC2MIN_LSB_LEN>(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<int64_t> l_buffer;
-
- l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC2min_MSB(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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<TARGET_TYPE_DIMM>& i_target,
- int64_t& o_value)
-{
- // Lambda expression to retrieve tRFC4min's most significant byte (MSB)
- auto tRFC4min_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TRFC4MIN_MSB_START, TRFC4MIN_MSB_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve tRFC4min's least significant byte (LSB)
- auto tRFC4min_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TRFC4MIN_LSB_START, TRFC4MIN_LSB_LEN>(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<int64_t> l_buffer;
-
- l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC4min_MSB(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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<TARGET_TYPE_DIMM>& i_target,
- int64_t& o_value)
-{
- // Lambda expression to retrieve tFAWmin's most significant nibble (MSN)
- auto tFAWmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TFAWMIN_MSN_START, TFAWMIN_MSN_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve tFAWmin's least significant byte (LSB)
- auto tFAWmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TFAWMIN_LSB_START, TFAWMIN_LSB_LEN>(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<int64_t> l_buffer;
-
- l_buffer.insertFromRight<MSN_START, MSN_LEN>( tFAWmin_MSN(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& i_target,
- int64_t& o_value)
-{
- // Lambda expression to retrieve tWRmin's most nibble byte (MSN)
- auto tWRmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TWRMIN_MSN_START, TWRMIN_MSN_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve tWRmin's least significant byte (LSB)
- auto tWRmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TWRMIN_LSB_START, TWRMIN_LSB_LEN>(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<int64_t> l_buffer;
- l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRmin_MSN(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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<TARGET_TYPE_DIMM>& i_target,
- int64_t& o_value)
-{
- // Lambda expression to retrieve tWRT_Smin's most nibble byte (MSN)
- auto tWRT_Smin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TWTRMIN_S_MSN_START, TWTRMIN_S_MSN_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve tWRT_Smin's least significant byte (LSB)
- auto tWRT_Smin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TWTRMIN_S_LSB_START, TWTRMIN_S_LSB_LEN>(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<int64_t> l_buffer;
-
- l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRT_Smin_MSN(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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<TARGET_TYPE_DIMM>& i_target,
- int64_t& o_value)
-{
- // Lambda expression to retrieve tWRT_Lmin's most nibble byte (MSN)
- auto tWRT_Lmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TWTRMIN_L_MSN_START, TWTRMIN_L_MSN_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve tWRT_Lmin's least significant byte (LSB)
- auto tWRT_Lmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- l_buffer.extractToRight<TWTRMIN_L_LSB_START, TWTRMIN_L_LSB_LEN>(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<int64_t> l_buffer;
-
- l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRT_Lmin_MSN(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- uint16_t& o_value)
-{
- // Lambda expression to retrieve crc's most significant byte (MSB)
- auto crc_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- // Extracting desired bits
- l_buffer.extractToRight<CRC_MSB_START, CRC_MSB_LEN>(l_out);
-
- return l_out;
- };
-
- // Lambda expression to retrieve crc's least significant byte (LSB)
- auto crc_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<uint8_t> l_buffer(i_data[BYTE_INDEX]);
-
- // Extracting desired bits
- l_buffer.extractToRight<CRC_LSB_START, CRC_LSB_LEN>(l_out);
-
- return l_out;
- };
-
- fapi2::buffer<uint16_t> 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<MSN_START, MSN_LEN>( crc_MSB(i_target, iv_spd_data) ).
- insertFromRight<LSB_START, LSB_LEN>( 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<OUTPUT_START, OUTPUT_LEN>(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 <aamarin@us.ibm.com>
-// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
-// *HWP Team: Memory
-// *HWP Level: 2
-// *HWP Consumed by: HB:FSP
-
-#ifndef _MSS_SPD_DECODER_H_
-#define _MSS_SPD_DECODER_H_
-
-#include <fapi2.H>
-#include <cstdint>
-#include <map>
-#include <memory>
-
-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<uint8_t> 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<uint8_t>& i_spd_data,
- std::shared_ptr<decoder>& 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::TargetType T>
-fapi2::ReturnCode populate_decoder_caches(const fapi2::Target<T>& i_target,
- std::map<uint32_t, std::shared_ptr<decoder> >& o_factory_caches,
- const std::shared_ptr<decoder>& 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 <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// std lib
+#include <map>
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+#include <fapi2_spd_access.H>
+
+// mss lib
+#include <lib/spd/spd_factory.H>
+#include <lib/spd/common/spd_decoder.H>
+
+#include <lib/utils/checker.H>
+#include <lib/utils/c_str.H>
+#include <lib/utils/conversions.H>
+#include <lib/utils/find.H>
+
+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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<uint8_t> l_buffer(l_raw_byte);
+ l_buffer.extractToRight<ENCODING_LEVEL_START, ENCODING_LEVEL_LEN>(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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<uint8_t> l_buffer(l_raw_byte);
+ uint8_t l_field_bits = 0;
+ l_buffer.extractToRight<ADDITIONS_LEVEL_START, ADDITIONS_LEVEL_LEN>(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<TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<std::pair<uint8_t, uint8_t> > 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<uint8_t> l_spd_buffer(l_raw_byte);
+ uint8_t l_field_bits = 0;
+ l_spd_buffer.extractToRight<BASE_MODULE_START, BASE_MODULE_LEN>(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<TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<std::pair<uint8_t, uint8_t> > 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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ std::shared_ptr<decoder>& 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<TARGET_TYPE_MCS>(i_target);
+ const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(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<dimm_module_decoder> 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<rdimm_decoder_v1_0>(i_target, i_spd_data);
+ o_fact_obj = std::make_shared<decoder>( 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<rdimm_decoder_v1_1>(i_target, i_spd_data);
+ o_fact_obj = std::make_shared<decoder_v1_1>( 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<TARGET_TYPE_MCS>& i_target,
+ std::map<uint32_t, std::shared_ptr<decoder> >& o_factory_caches,
+ const std::shared_ptr<decoder>& i_pDecoder)
+{
+ // Input decoder for this version of populating cache would get overriden
+ // so I don't bother with it here
+ std::shared_ptr<decoder> l_pDecoder;
+
+ for( const auto& l_dimm : find_targets<TARGET_TYPE_DIMM>(i_target) )
+ {
+ size_t l_size = 0;
+ FAPI_TRY( fapi2::getSPD(l_dimm, nullptr, l_size) );
+
+ {
+ // "Container" for SPD data
+ std::vector<uint8_t> 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<TARGET_TYPE_DIMM>& i_target,
+ std::map<uint32_t, std::shared_ptr<decoder> >& o_factory_caches,
+ const std::shared_ptr<decoder>& 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<decoder> 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 <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_SPD_FACTORY_H_
+#define _MSS_SPD_FACTORY_H_
+
+// std lib
+#include <cstdint>
+#include <map>
+#include <memory>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <lib/spd/common/spd_decoder.H>
+
+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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ std::shared_ptr<decoder>& 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::TargetType T>
+fapi2::ReturnCode populate_decoder_caches(const fapi2::Target<T>& i_target,
+ std::map< uint32_t, std::shared_ptr<decoder> >& o_factory_caches,
+ const std::shared_ptr<decoder>& 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<fapi2::TARGET_TYPE_DIMM>&
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 <p9_mss_eff_config.H>
+
+// std
#include <map>
-#include <vector>
+// fapi2
#include <fapi2.H>
-#include <p9_mss_eff_config.H>
-#include <lib/utils/pos.H>
-#include <lib/spd/spd_decoder.H>
+
+// mss lib
+#include <lib/spd/common/spd_decoder.H>
+#include <lib/spd/spd_factory.H>
#include <lib/eff_config/eff_config.H>
+#include <lib/utils/pos.H>
#include <lib/utils/checker.H>
#include <lib/utils/find.H>
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 <cstring>
-#include <cstdint>
+#include <p9_mss_freq.H>
+
+// std lib
+#include <map>
+// fapi2
#include <fapi2.H>
-#include <mss.H>
-#include <p9_mss_freq.H>
-#include <lib/spd/spd_decoder.H>
+
+// mss lib
+#include <lib/spd/common/spd_decoder.H>
+#include <lib/spd/spd_factory.H>
#include <lib/freq/cas_latency.H>
#include <lib/utils/c_str.H>
#include <lib/freq/cycle_time.H>
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 <p9_mss_volt.H>
+// std lib
+#include <vector>
+#include <map>
+// fapi2
#include <fapi2.H>
-#include <mss.H>
-#include <p9_mss_volt.H>
-#include <vector>
+// mss lib
+#include <lib/spd/spd_factory.H>
+#include <lib/spd/common/spd_decoder.H>
+#include <lib/eff_config/attr_setters.H>
+#include <lib/utils/c_str.H>
+#include <lib/utils/pos.H>
+#include <lib/utils/find.H>
+#include <lib/utils/checker.H>
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 <fapi2.H>
#include <vector>
-#include <lib/spd/spd_decoder.H>
-#include <lib/eff_config/attr_setters.H>
typedef fapi2::ReturnCode (*p9_mss_volt_FP_t) (const std::vector <fapi2::Target<fapi2::TARGET_TYPE_MCS>>&);
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 <aamarin@us.ibm.com>
+// *HWP FW Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 4
+// *HWP Consumed by: CI
+
+#include <cstdarg>
+#include <fapi2.H>
+
+#include <mss.H>
+#include <catch.hpp>
+
+#include <tests/target_fixture.H>
+#include <lib/utils/fake_spd.H>
+#include <lib/spd/spd_factory.H>
+#include <lib/spd/common/spd_decoder.H>
+
+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<fapi2::TARGET_TYPE_MCBIST>& i_target)
+ {
+ for( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(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<uint8_t> 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<fapi2::TARGET_TYPE_MCBIST>& i_target)
+ {
+ for( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) )
+ {
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+ uint8_t l_decoder_output = 0;
+ std::vector<uint8_t> 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<fapi2::TARGET_TYPE_MCBIST>& i_target)
+ {
+ for( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(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<uint8_t> 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 */
OpenPOWER on IntegriCloud