summaryrefslogtreecommitdiffstats
path: root/src/import
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2016-02-09 13:16:51 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-04-01 21:25:50 -0400
commit27d51dd4709eab460d8bffe0099da545b00cd84a (patch)
tree43a1eed324656c0aec65e403712448ae7fdff35c /src/import
parent28bdcea7bf26e2df9bac602e65f006c007f6ac59 (diff)
downloadtalos-hostboot-27d51dd4709eab460d8bffe0099da545b00cd84a.tar.gz
talos-hostboot-27d51dd4709eab460d8bffe0099da545b00cd84a.zip
Modify spd_decoder, eff_config, unit tests. Modify dependent files
Change-Id: I8280ac1f6c66f822725ae6a4446ce7a23453aec6 Original-Change-Id: Ifa4fbf9d452a3e77075bee9ab72b2bde2afe90a5 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/20861 Tested-by: Jenkins Server Tested-by: Auto Mirror Reviewed-by: Brian R. Silver <bsilver@us.ibm.com> Tested-by: Hostboot CI Reviewed-by: CRAIG C. HAMILTON <cchamilt@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22776 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H2
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C271
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H112
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H293
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C5713
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.H1230
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/utils/checker.H136
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H93
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H39
9 files changed, 5036 insertions, 2853 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H
index 6dc0c5c45..4e43b5ca0 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H
@@ -57,7 +57,7 @@ class kind
FAPI_TRY( mss::eff_dram_density(i_target, iv_dram_density) );
FAPI_TRY( mss::eff_dram_width(i_target, iv_dram_width) );
FAPI_TRY( mss::eff_num_master_ranks_per_dimm(i_target, iv_master_ranks) );
- FAPI_TRY( mss::eff_dram_rows(i_target, iv_rows) );
+ FAPI_TRY( mss::eff_dram_row_bits(i_target, iv_rows) );
FAPI_TRY( mss::eff_dimm_size(i_target, iv_size) );
// TK: Attribute for slave ranks.
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
new file mode 100644
index 000000000..ce3e1200c
--- /dev/null
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C
@@ -0,0 +1,271 @@
+
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* EKB Project */
+/* */
+/* COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* IBM_PROLOG_END_TAG */
+///
+/// @file eff_config.C
+/// @brief Determine effective config for mss settings
+///
+// *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: FSP:HB
+
+#include <fapi2.H>
+#include <mss.H>
+#include "../spd/spd_decoder.H"
+#include "eff_config.H"
+#include "timing.H"
+
+using fapi2::TARGET_TYPE_MCA;
+using fapi2::TARGET_TYPE_MCS;
+using fapi2::TARGET_TYPE_DIMM;
+using fapi2::TARGET_TYPE_MCBIST;
+
+namespace mss
+{
+
+///
+/// @brief Determines & sets effective config for DRAM generation from SPD
+/// @param[in] i_target FAPI2 target
+/// @param[in] i_spd_data SPD blob
+/// @param[in] i_pDecoder shared pointer to decoder factory
+/// @return fapi2::ReturnCode
+///
+fapi2::ReturnCode eff_config::dram_gen(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ std::shared_ptr<spd::decoder>& i_pDecoder)
+{
+ uint8_t l_decoder_val = 0;
+ uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+
+ // Targets
+ const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target);
+ const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target);
+
+ // Current index
+ const auto l_port_num = index(l_target_port);
+ const auto l_dimm_num = index(i_target);
+
+ // factory selects correct SPD method dependent on rev & dimm type
+ FAPI_TRY( spd::decoder::factory(i_target, i_spd_data, i_pDecoder) );
+
+ FAPI_TRY( i_pDecoder->dram_device_type(i_target, i_spd_data, l_decoder_val) );
+
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dram_gen(l_target_mcs, &l_mcs_attrs[0][0]) );
+ l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, l_target_mcs, l_mcs_attrs) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}// dram_gen
+
+
+///
+/// @brief Determines & sets effective config for DIMM type from SPD
+/// @param[in] i_target FAPI2 target
+/// @param[in] i_spd_data SPD blob
+/// @return fapi2::ReturnCode
+///
+fapi2::ReturnCode eff_config::dimm_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data)
+{
+ uint8_t l_decoder_val = 0;
+ uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+
+ // Targets
+ const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target);
+ const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target);
+
+ // Current index
+ const auto l_port_num = index(l_target_port);
+ const auto l_dimm_num = index(i_target);
+
+ FAPI_TRY( spd::decoder::base_module_type(i_target, i_spd_data, l_decoder_val) );
+
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dimm_type(l_target_mcs, &l_mcs_attrs[0][0]) );
+ l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_TYPE, l_target_mcs, l_mcs_attrs) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}// dimm_type
+
+///
+/// @brief Determines & sets effective config for Hybrid memory type from SPD
+/// @param[in] i_target FAPI2 target
+/// @param[in] i_spd_data SPD blob
+/// @param[in] i_pDecoder shared pointer to decoder factory
+/// @return fapi2::ReturnCode
+///
+fapi2::ReturnCode eff_config::hybrid_memory_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ std::shared_ptr<spd::decoder>& i_pDecoder)
+{
+ uint8_t l_decoder_val = 0;
+ uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+
+ // Targets
+ const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target);
+ const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target);
+
+ // Current index
+ const auto l_port_num = index(l_target_port);
+ const auto l_dimm_num = index(i_target);
+
+ // Factory selects correct SPD method dependent on rev & dimm type
+ FAPI_TRY( spd::decoder::factory(i_target, i_spd_data, i_pDecoder) );
+
+ FAPI_TRY(i_pDecoder->hybrid_media(i_target, i_spd_data, l_decoder_val));
+
+ // Get & update MCS attribute
+ FAPI_TRY( eff_hybrid_memory_type(l_target_mcs, &l_mcs_attrs[0][0]) );
+ l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, l_target_mcs, l_mcs_attrs) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}// dimm_type
+
+///
+/// @brief Sets effective config for temperature controlled refresh mode
+/// @param[in] i_target FAPI2 target
+/// @return fapi2::ReturnCode
+/// @note Proposed DDR4 Full spec update(79-4A)
+/// @note Committee: JC42.3C
+/// @note Committee Item Number: 1716.78C
+/// @note 4.8.2 Extended temperature mode (pg. 44)
+fapi2::ReturnCode eff_config::temp_ref_range(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+{
+ uint8_t l_mcs_attrs[PORTS_PER_MCS] = {0};
+
+ // Targets
+ const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target);
+ const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target);
+
+ // Current index
+ const auto l_port_num = index(l_target_port);
+
+ FAPI_TRY( mss::eff_temp_ref_range(l_target_mcs, &l_mcs_attrs[0]) );
+
+ // TK - I think this will become a platform attribute so this function
+ // will eventuall get removed - AAM
+
+ // This is defaulted to Extended temperature mode
+ l_mcs_attrs[l_port_num] = fapi2::ENUM_ATTR_EFF_TEMP_REF_RANGE_EXTEND;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_TEMP_REF_RANGE, l_target_mcs, l_mcs_attrs) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}// temp_ref_range
+
+///
+/// @brief Determines & sets effective config for Refresh Mode
+/// @param[in] i_target FAPI2 target
+/// @return fapi2::ReturnCode
+///
+fapi2::ReturnCode eff_config::fine_refresh_mode(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+{
+ uint8_t l_mcs_attrs[PORTS_PER_MCS] = {0};
+ // Targets
+ const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target);
+ const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target);
+
+ // Current index
+ const auto l_port_num = index(l_target_port);
+
+ // Per Warren - should be in Normal mode, might change based on lab test results - AAM
+ // Get & update MCS attribute
+ FAPI_TRY( mss::eff_fine_refresh_mode(l_target_mcs, &l_mcs_attrs[0])) ;
+ l_mcs_attrs[l_port_num] = fapi2::ENUM_ATTR_EFF_FINE_REFRESH_MODE_NORMAL;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_FINE_REFRESH_MODE, l_target_mcs, l_mcs_attrs) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}// refresh_mode
+
+
+/// @brief Determines & sets effective config for refresh interval time (tREFI)
+/// @param[in] i_target FAPI2 target
+/// @return fapi2::ReturnCode
+///
+fapi2::ReturnCode eff_config::refresh_interval_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+{
+ uint8_t l_mcs_attrs_refresh[PORTS_PER_MCS] = {0};
+ uint8_t l_refresh_mode = 0;
+
+ uint8_t l_mcs_attrs_trefi[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ uint64_t l_trefi_in_ps = 0;
+ uint8_t l_trefi_in_nck = 0;
+
+ uint64_t l_mss_freq = 0;
+ uint64_t l_tCK_in_ps = 0;
+
+ // Targets
+ const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target);
+ const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target);
+ const auto l_target_mcbist = find_target<TARGET_TYPE_MCBIST>(i_target);
+
+ // Current index
+ const auto l_port_num = index(l_target_port);
+ const auto l_dimm_num = index(i_target);
+
+ // Retrieve attributes values
+ FAPI_TRY( mss::freq(l_target_mcbist, l_mss_freq) );
+ FAPI_TRY ( mss::eff_fine_refresh_mode(l_target_mcs, &l_mcs_attrs_refresh[0]) );
+
+ l_refresh_mode = l_mcs_attrs_refresh[l_port_num];
+
+ switch(l_refresh_mode)
+ {
+ case fapi2::ENUM_ATTR_EFF_FINE_REFRESH_MODE_NORMAL:
+ calc_trefi1(i_target, l_trefi_in_ps);
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_FINE_REFRESH_MODE_FIXED_2X:
+ case fapi2::ENUM_ATTR_EFF_FINE_REFRESH_MODE_FLY_2X:
+ calc_trefi2(i_target, l_trefi_in_ps);
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_FINE_REFRESH_MODE_FIXED_4X:
+ case fapi2::ENUM_ATTR_EFF_FINE_REFRESH_MODE_FLY_4X:
+ calc_trefi4(i_target, l_trefi_in_ps);
+ break;
+ }
+
+ // Calculate clock period (tCK) from selected freq from mss_freq
+ l_tCK_in_ps = freq_to_ps(l_mss_freq);
+
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dram_trefi(l_target_mcs, &l_mcs_attrs_trefi[0][0]) );
+
+ l_trefi_in_nck = calc_nck(l_trefi_in_ps, l_tCK_in_ps, uint64_t(INVERSE_DDR4_CORRECTION_FACTOR));
+ l_mcs_attrs_trefi[l_port_num][l_dimm_num] = uint8_t(l_trefi_in_nck);
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TREFI, l_target_mcs, l_mcs_attrs_trefi) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}// refresh_interval
+
+
+
+}// mss
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
new file mode 100644
index 000000000..1ddb006bc
--- /dev/null
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H
@@ -0,0 +1,112 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* EKB Project */
+/* */
+/* COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* IBM_PROLOG_END_TAG */
+///
+/// @file eff_config.H
+/// @brief Determine effective config for mss settings
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP FW Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_EFF_CONFIG_H_
+#define _MSS_EFF_CONFIG_H_
+
+#include <fapi2.H>
+#include <cstdint>
+#include "../spd/spd_decoder.H"
+
+namespace mss
+{
+
+///
+/// @class eff_config
+/// @brief Determine effective config for mss settings
+///
+class eff_config
+{
+ // constructor
+ eff_config() = default;
+
+ // destructor
+ ~eff_config() = default;
+
+ public:
+ ////////////////////////
+ // Methods
+ ///////////////////////
+
+ ///
+ /// @brief Determines & sets effective config for DRAM generation from SPD
+ /// @param[in] i_target FAPI2 target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[in] i_pDecoder shared pointer to decoder factory
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode dram_gen(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ std::shared_ptr<spd::decoder>& i_pDecoder);
+
+ ///
+ /// @brief Determines & sets effective config for DIMM type
+ /// @param[in] i_target FAPI2 target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode dimm_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data);
+ ///
+ /// @brief Determines & sets effective config for Hybrid memory type from SPD
+ /// @param[in] i_target FAPI2 target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[in] i_pDecoder shared pointer to decoder factory
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode hybrid_memory_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ std::shared_ptr<spd::decoder>& i_pDecoder);
+ ///
+ /// @brief Sets effective config for temperature controlled refresh mode
+ /// @param[in] i_target FAPI2 target
+ /// @return fapi2::ReturnCode
+ /// @note Proposed DDR4 Full spec update(79-4A)
+ /// @note Committee: JC42.3C
+ /// @note Committee Item Number: 1716.78C
+ /// @note 4.8.2 Extended temperature mode (pg. 44)
+ fapi2::ReturnCode temp_ref_range(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+
+ ///
+ /// @brief Determines & sets effective config for Refresh Mode
+ /// @param[in] i_target FAPI2 target
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode fine_refresh_mode(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+
+ /// @brief Determines & sets effective config for refresh interval time (tREFI)
+ /// @param[in] i_target FAPI2 target
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode refresh_interval_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+
+};// eff_config
+
+} // mss
+
+#endif // _MSS_EFF_CONFIG_H_
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H
new file mode 100644
index 000000000..5c921fa5c
--- /dev/null
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H
@@ -0,0 +1,293 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: chips/p9/procedures/hwp/memory/lib/eff_config/timing.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* EKB Project */
+/* */
+/* COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* IBM_PROLOG_END_TAG */
+///
+/// @file timing.H
+/// @brief Determine effective config for mss settings
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP FW Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_TIMING_H_
+#define _MSS_TIMING_H_
+
+#include <mss.H>
+#include <fapi2.H>
+#include <cstdint>
+#include "../utils/find.H"
+
+using fapi2::TARGET_TYPE_DIMM;
+
+namespace mss
+{
+
+// { density in GBs, tREFI(base) in picoseconds }
+static const std::vector<std::pair<uint8_t, uint64_t> > TREFI_BASE =
+{
+ {2, 7800},
+ {4, 7800},
+ {8, 7800},
+ // 16Gb - TBD
+};
+
+// { density in GBs, tRFC1(min) in picoseconds }
+static const std::vector<std::pair<uint8_t, uint64_t> > TRFC1_MIN =
+{
+ {2, 160},
+ {4, 260},
+ {8, 350},
+ // 16Gb - TBD
+};
+
+
+// { density in GBs, tRFC2(min) in picoseconds }
+static const std::vector<std::pair<uint8_t, uint64_t> > TRFC2_MIN =
+{
+ {2, 110},
+ {4, 160},
+ {8, 260},
+ // 16Gb - TBD
+};
+
+
+// { density in GBs, tRFC4(min) in picoseconds }
+static const std::vector<std::pair<uint8_t, uint64_t> > TRFC4_MIN =
+{
+ {2, 90},
+ {4, 110},
+ {8, 160},
+ // 16Gb - TBD
+};
+
+enum GUARD_BAND
+{
+ // Used for caclulating spd timing values - from JEDEC rounding algorithm
+ // Correction factor is 1% (for DDR3) or 2.5% (for DDR4)
+ // when doing integer math, we add-in the inverse correction factor
+ // Formula used for derivation:
+ // Guardband = 1000 * (1000* correction_factor) - 1
+ INVERSE_DDR3_CORRECTION_FACTOR = 989,
+ INVERSE_DDR4_CORRECTION_FACTOR = 974,
+};
+
+
+///
+/// @brief Calculates timing value
+/// @tparam T input and output type
+/// @param[in] i_timing_mtb timing value in MTB units
+/// @param[in] i_mtb_multiplier SPD medium timebase
+/// @param[in] i_timing_ftb fine offset of timing value
+/// @param[in] i_ftb_multiplier SPD fine timebase
+/// @return the timing value in picoseconds
+///
+template<typename T>
+inline T calc_timing_from_timebase(const T i_timing_mtb,
+ const T i_mtb_multiplier,
+ const T i_timing_ftb,
+ const T i_ftb_multiplier)
+{
+ // JEDEC algorithm
+ T l_timing_val = i_timing_mtb * i_mtb_multiplier;
+ T l_fine_offset = i_timing_ftb * i_ftb_multiplier;
+
+ // Needed to do integer math but attribute is uint64
+ return l_timing_val + l_fine_offset;
+}
+
+
+///
+/// @brief Returns clock cycles
+/// @tparam T input and output type
+/// @param[in] timing_in_ps timing parameter in ps
+/// @param[in] tck_in_ps clock period in ps
+/// @param[in] inverse_corr_factor inverse correction factor (defined by JEDEC)
+/// @return the clock cycles of timing parameter (provided in ps)
+/// @note DDR4 SPD Contents Rounding Algorithm
+/// @note Item 2220.46
+///
+template<typename T>
+inline T calc_nck(T timing_in_ps, T tck_in_ps, T inverse_corr_factor)
+{
+ // Preliminary nCK calculation, scaled by 1000
+ T temp_nck = timing_in_ps * 1000 / tck_in_ps;
+
+ // Apply inverse of correction factor percentage
+ temp_nck += inverse_corr_factor;
+
+ return temp_nck / 1000;
+}
+
+
+//
+// TK - AAM
+// These are only used in eff_config, make them non-member non-friend functions in eff_config.C?
+//
+
+/// @brief Calculates refresh interval time 1 (tREFI 1)
+/// @param[in] i_target FAPI2 target
+/// @param[out] o_value timing val in ps
+/// @return fapi2::ReturnCode
+///
+inline fapi2::ReturnCode calc_trefi1(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, uint64_t& o_value)
+{
+ uint8_t l_quotient = 0;
+ uint8_t l_remainder = 0;
+ uint64_t l_output = 0;
+ uint8_t l_temp_ref_range = 0;
+ uint8_t l_dram_density = 0;
+
+
+ FAPI_TRY(mss::eff_dram_density(i_target, l_dram_density));
+
+ switch(l_temp_ref_range)
+ {
+ case fapi2::ENUM_ATTR_EFF_TEMP_REF_RANGE_NORMAL:
+ mss::find_value_from_key(TREFI_BASE, l_dram_density, o_value);
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_TEMP_REF_RANGE_EXTEND:
+ mss::find_value_from_key(TREFI_BASE, l_dram_density, l_output);
+ l_quotient = l_output / 2;
+ l_remainder = l_output % 2;
+ o_value = l_quotient + (l_remainder == 0 ? 0 : 1);
+ break;
+
+ default:
+ // l_temp_ref_range will be a platform attribute set by the MRW,
+ // which they "shouldn't" mess up as long as use "attribute" enums.
+ // if openpower messes this up we can at least catch it
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_TEMP_REF_RANGE().
+ set_TEMP_REF_RANGE(l_temp_ref_range),
+ "%s Incorrect Temperature Ref. Range received: %d ",
+ mss::c_str(i_target),
+ l_temp_ref_range);
+
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+/// @brief Calculates refresh interval time 2 (tREFI 2)
+/// @param[in] i_target FAPI2 target
+/// @param[out] o_value timing val in ps
+/// @return fapi2::ReturnCode
+///
+inline fapi2::ReturnCode calc_trefi2(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, uint64_t& o_value)
+{
+ uint8_t l_quotient = 0;
+ uint8_t l_remainder = 0;
+ uint64_t l_output = 0;
+ uint8_t l_temp_ref_range = 0;
+ uint8_t l_dram_density = 0;
+
+ FAPI_TRY(mss::eff_temp_ref_range(i_target, l_temp_ref_range));
+ FAPI_TRY(mss::eff_dram_density(i_target, l_dram_density));
+
+ switch(l_temp_ref_range)
+ {
+ case fapi2::ENUM_ATTR_EFF_TEMP_REF_RANGE_NORMAL:
+ mss::find_value_from_key(TREFI_BASE, l_dram_density, l_output);
+ l_quotient = l_output / 2;
+ l_remainder = l_output % 2;
+ o_value = l_quotient + (l_remainder == 0 ? 0 : 1);
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_TEMP_REF_RANGE_EXTEND:
+ mss::find_value_from_key(TREFI_BASE, l_dram_density, l_output);
+ l_quotient = l_output / 4;
+ l_remainder = l_output % 4;
+ o_value = l_quotient + (l_remainder == 0 ? 0 : 1);
+ break;
+
+ default:
+ // l_temp_ref_range will be a platform attribute set by the MRW,
+ // which they "shouldn't" mess up as long as use "attribute" enums.
+ // if openpower messes this up we can at least catch it
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_TEMP_REF_RANGE().
+ set_TEMP_REF_RANGE(l_temp_ref_range),
+ "%s Incorrect Temperature Ref. Range received: %d ",
+ mss::c_str(i_target),
+ l_temp_ref_range);
+
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+/// @brief Calculates refresh interval time 4 (tREFI 4)
+/// @param[in] i_target FAPI2 target
+/// @param[out] o_value timing val in ps
+/// @return fapi2::ReturnCode
+///
+inline fapi2::ReturnCode calc_trefi4( const fapi2::Target<TARGET_TYPE_DIMM>& i_target, uint64_t& o_value)
+{
+ uint8_t l_quotient = 0;
+ uint8_t l_remainder = 0;
+ uint64_t l_output = 0;
+ uint8_t l_temp_ref_range = 0;
+ uint8_t l_dram_density = 0;
+
+ FAPI_TRY(mss::eff_temp_ref_range(i_target, l_temp_ref_range));
+ FAPI_TRY(mss::eff_dram_density(i_target, l_dram_density));
+
+ switch(l_temp_ref_range)
+ {
+ case fapi2::ENUM_ATTR_EFF_TEMP_REF_RANGE_NORMAL:
+ mss::find_value_from_key(TREFI_BASE, l_dram_density, l_output);
+ l_quotient = l_output / 4;
+ l_remainder = l_output % 4;
+ o_value = l_quotient + (l_remainder == 0 ? 0 : 1);
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_TEMP_REF_RANGE_EXTEND:
+ mss::find_value_from_key(TREFI_BASE, l_dram_density, l_output);
+ l_quotient = l_output / 8;
+ l_remainder = l_output % 8;
+ o_value = l_quotient + (l_remainder == 0 ? 0 : 1);
+ break;
+
+ default:
+ // l_temp_ref_range will be a platform attribute set by the MRW,
+ // which they "shouldn't" mess up as long as use "attribute" enums.
+ // if openpower messes this up we can at least catch it
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_TEMP_REF_RANGE().
+ set_TEMP_REF_RANGE(l_temp_ref_range),
+ "%s Incorrect Temperature Ref. Range received: %d ",
+ mss::c_str(i_target),
+ l_temp_ref_range);
+
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // mss
+
+#endif
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
index d215773a0..00c4c6419 100644
--- 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
@@ -7,7 +7,7 @@
/* */
/* EKB Project */
/* */
-/* COPYRIGHT 2015 */
+/* COPYRIGHT 2015,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -17,6 +17,7 @@
/* */
/* IBM_PROLOG_END_TAG */
+
///
/// @file spd_decoder.C
/// @brief SPD decoder definitions
@@ -28,8 +29,9 @@
// *HWP Consumed by: HB:FSP
#include <fapi2.H>
-#include "../mss.H"
+#include <mss.H>
#include "../utils/conversions.H"
+#include "../utils/find.H"
#include "spd_decoder.H"
using fapi2::TARGET_TYPE_MCBIST;
@@ -43,7 +45,7 @@ namespace mss
namespace spd
{
-// Note: IBM's implementation of std::maps are not thread safe
+// Note: IBM's implementation of std::map is not thread safe
// =========================================================
// Byte 0 maps
@@ -51,31 +53,22 @@ namespace spd
// Page 14
// DDR4 SPD Document Release 3
// Byte 0 (0x000): Number of Bytes Used / Number of Bytes in SPD Device
-
-static const uint16_t bytes_used_map[] =
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint16_t> > BYTES_USED_MAP =
{
- // Shifting index by 1 first since first key value is undefined
- // Key values < 1 and > 3 aren't supported or reserved
-
- // Undefined
- 128,
- 256,
- 384,
- 512,
- //...
- // All other bits reserved
+ //{key byte, number of used bytes}
+ {1, 128},
+ {2, 256},
+ {3, 384},
+ {4, 512}
};
-static const uint16_t bytes_total_map[] =
-{
- // Shifting index by 1 first since first key value is undefined
- // Key values < 1 and > 2 aren't supported or reserved
- // Undefined
- 256,
- 512,
- //...
- // All other bits reserved
+static const std::vector<std::pair<uint8_t, uint16_t> > BYTES_TOTAL_MAP =
+{
+ //{key byte, number of total bytes}
+ {1, 256},
+ {2, 512}
};
// =========================================================
@@ -84,28 +77,13 @@ static const uint16_t bytes_total_map[] =
// Page 16
// DDR4 SPD Document Release 3
// Byte 2 (0x002): Key Byte / DRAM Device Type
-
-static const uint8_t dram_gen_map[] =
-{
- // Initial and ending index values are not supported or reserved
- // Shifting index by 11 since initial dram gen types aren't supported (by IBM)
- // Key values < 12 and > 13 are not supported or reserved
-
- // Reserved
- // Fast page mode is not supported
- // EDO is not supported
- // Pipelined Nibbleis not supported
- // SDRAM
- // ROM is not supported
- // DDR SGRAM is not supported
- // DDR SDRAM is not supported
- // DDR2 SDRAM is not supported
- // DDR2 SDRAM FB-DIMM is not supported
- // DDR2 SDRAM FB-DIMM PROBE is not supported
- fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR3,
- fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4,
- //...
- // All other bits reserved
+// =========================================================
+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
};
// =========================================================
@@ -114,30 +92,27 @@ static const uint8_t dram_gen_map[] =
// 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 uint8_t base_module_type_map[] =
-{
-
- // Initial and ending index values are not supported or reserved
- // Index shifted by 1 since first module type isn't supported (by IBM)
- // Key values < 1 and > 4 are not supported or reserved
-
- // Extending DIMM not supported
- fapi2::ENUM_ATTR_SPD_MODULE_TYPE_RDIMM,
- fapi2::ENUM_ATTR_SPD_MODULE_TYPE_UDIMM,
- fapi2::ENUM_ATTR_SPD_MODULE_TYPE_SO_DIMM,
- fapi2::ENUM_ATTR_SPD_MODULE_TYPE_LRDIMM,
- // Mini-RDIMM not supported
- // Mini-UDIMM not supported
- // Reserved
- // 72b-SO-RDIMM not supported
- // 72b-SO-UDIMM not supported
- // Reserved
- // Reserved
- // 16b-SO-DIMM
- // 32b-SO-DIMM
- // Reserved
- // Reserved
+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}
};
// =========================================================
@@ -146,74 +121,62 @@ static const uint8_t base_module_type_map[] =
// Page 18
// DDR4 SPD Document Release 3
// Byte 4 (0x004): SDRAM Density and Banks
-
-static const uint8_t sdram_capacity_map[] =
-{
- // Initial and ending index values are not supported or reserved
- // Index shifted by 2 since first module type isn't supported (by IBM)
- // Key values < 2 and > 9 are not supported or reserved
-
- // 256 Mbs is not supported
- // 512 Mbs is not supported
- // // Units (Gigabits)
- 1, // Gb
- 2, // Gb
- 4, // Gb
- 8, // Gb
- 16, // Gb
- 32, // Gb
- 12, // Gb
- 24, // Gb
- //...
- //All others reserved
+// =========================================================
+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 uint8_t sdram_banks_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > BANK_ADDR_BITS_MAP =
{
- // Key values > 1 are not supported or reserved
-
- 4, // banks address bits (2 address bits)
- 8, // banks address bits (3 address bits)
- //...
- // All others Reserved
+ // {key byte, number of bank address bits}
+ {0, 2},
+ {1, 3}
};
-static const uint8_t sdram_bankgroups_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > BANK_GROUP_BITS_MAP =
{
- // Key values > 2 are not supported or reserved
-
- 0, // No bank groups (0 bank group bits)
- 2, // 2 bank groups (1 bank group bit)
- 4, // 4 bank groups (2 bank group bits)
- //Reserved
+ // {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 uint8_t column_address_map[] =
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > COLUMN_ADDRESS_BITS_MAP =
{
- 9, // Column address bits 000
- 10, // Column address bits 001
- 11, // Column address bits 010
- 12, // Column address bits 011
- // All others reserved
+ //{key byte,col address bits}
+ {0, 9},
+ {1, 10},
+ {2, 11},
+ {3, 12}
};
-static const uint8_t row_address_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > ROW_ADDRESS_BITS_MAP =
{
- 12, // Row address bits 000
- 13, // Row address bits 001
- 14, // Row address bits 010
- 15, // Row address bits 011
- 16, // Row address bits 100
- 17, // Row address bits 101
- 18, // Row address bits 110
- // All others reserved
+ //{key byte,row address bits}
+ {0, 12},
+ {1, 13},
+ {2, 14},
+ {3, 15},
+ {4, 16},
+ {5, 17},
+ {6, 18}
};
// =========================================================
@@ -222,28 +185,34 @@ static const uint8_t row_address_map[] =
// 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 uint8_t die_count_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_DIE_COUNT_MAP =
{
- 1, // 000 = Single die
- 2, // 001 = 2 die
- 3, // 010 = 3 die
- 4, // 011 = 4 die
- 5, // 100 = 5 die
- 6, // 101 = 6 die
- 7, // 110 = 7 die
- 8, // 111 = 8 die
+ // {key byte, number of die}
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {3, 4},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 8}
+
};
-static const uint8_t package_type_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_PACKAGE_TYPE_MAP =
{
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_SDP,
- uint8_t(~0),
- uint8_t(~0),
- uint8_t(~0),
- uint8_t(~0),
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_DDP_QDP,
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_3DS,
+ // {key byte, value}
+ {0, MONOLITHIC},
+ {1, NON_MONOLITHIC}
};
// =========================================================
@@ -252,26 +221,27 @@ static const uint8_t package_type_map[] =
// Page 20
// DDR4 SPD Document Release 3
// Byte 7 (0x007): SDRAM Optional Features
-
-uint16_t static const MAC_map[] =
-{
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNTESTED, // Untested MAC
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_700K, // 700K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_600K, // 600K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_500K, // 500K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_400K, // 400K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_300K, // 300K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_200K, // 200K
- uint16_t(~0), // Reserved
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNLIMITED,// Unlimited MAC
- // All others reserved
+// =========================================================
+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}
};
-uint16_t static const tMAW_map[] =
+// Multiplier with tREFI is not taken into account here
+static const std::vector<std::pair<uint8_t, uint32_t> > TMAW_MAP =
{
- 8192,
- 4096,
- 2048,
+ // {key byte, tMAW multiplier}
+ {0, 8192},
+ {1, 4096},
+ {2, 2048}
};
// =========================================================
@@ -280,48 +250,77 @@ uint16_t static const tMAW_map[] =
// Page 21
// DDR4 SPD Document Release 3
// Byte 9 (0x009): Other SDRAM Optional Features
-static const uint8_t ppr_map[]
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > SOFT_PPR_MAP =
{
- fapi2::ENUM_ATTR_EFF_DRAM_PPR_NOT_SUPPORTED,
- fapi2::ENUM_ATTR_EFF_DRAM_PPR_SUPPORTED,
- //...
- // Reserved
+ // {key byte, value }
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED}
};
-static const uint8_t soft_ppr_map[]
+static const std::vector<std::pair<uint8_t, uint8_t> > PPR_MAP =
{
- fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED,
- fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED,
+ // {key byte, value }
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_PPR_NOT_SUPPORTED},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_PPR_SUPPORTED}
};
// =========================================================
-// Byte 6 maps
+// Byte 10 maps
// Item JC-45-2220.01x
-// Page 19
+// Page 21-22
// DDR4 SPD Document Release 3
-// Byte 6 (0x006): Primary SDRAM Package Type
+// 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}
+};
+
-static const uint8_t sec_die_count_map[] =
+// =========================================================
+// 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 =
{
- 1, // 000 = Single die
- 2, // 001 = 2 die
- 3, // 010 = 3 die
- 4, // 011 = 4 die
- 5, // 100 = 5 die
- 6, // 101 = 6 die
- 7, // 110 = 7 die
- 8, // 111 = 8 die
+ // {key byte, value }
+ {0, NOT_ENDURANT},
+ {1, ENDURANT}
};
-static const uint8_t sec_package_type_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > OPERABLE_MAP =
{
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_SDP,
- uint8_t(~0),
- uint8_t(~0),
- uint8_t(~0),
- uint8_t(~0),
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_DDP_QDP,
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_3DS,
+ // {key byte, value }
+ {0, NOT_OPERABLE },
+ {1, OPERABLE}
};
// =========================================================
@@ -330,51 +329,51 @@ static const uint8_t sec_package_type_map[] =
// Page 23
// DDR4 SPD Document Release 3
// Byte 12 (0x00C): Module Organization
-static const uint8_t device_type_map[] =
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > DEVICE_WIDTH_MAP =
{
- // // Units
- 4, // bits
- 8, // bits
- 16, // bits
- 32, // bits
+ // {key byte, device width (bits)}
+ {0, 4},
+ {1, 8},
+ {2, 16},
+ {3, 32},
// All others reserved
};
-static const uint8_t num_pkgs_ranks_per_dimm_map[] =
-{
- // // Units
- 1, // package rank
- 2, // package ranks
- 3, // package ranks
- 4, // package ranks
- 5, // package ranks
- 6, // package ranks
- 7, // package ranks
- 8 // package ranks
- // 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 12 maps
+// Byte 13 maps
// Item JC-45-2220.01x
-// Page 23
+// Page 27
// DDR4 SPD Document Release 3
// Byte 13 (0x00D): Module Memory Bus Width
-static const uint8_t prim_bus_width_map[] =
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_MAP =
{
- // // Units
- 8, // bits
- 16, // bits
- 32, // bits
- 64, // bits
+ // {key byte, bus width (in bits)
+ {0, 8},
+ {1, 16},
+ {2, 32},
+ {3, 64}
// All others reserved
};
-static const uint8_t bus_width_ext_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_EXT_MAP =
{
- // // Units
- 0, // bits
- 8, // bits
+ {0, 0},
+ {1, 8}
// All others reserved
};
@@ -384,3165 +383,3733 @@ static const uint8_t bus_width_ext_map[] =
// 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 uint8_t medium_timebase_map[] =
+static const std::vector<std::pair<uint8_t, int64_t> > MEDIUM_TIMEBASE_MAP =
{
- // // Units
- 125, // ps
+ // {key byte, medium timebase (in picoseconds)
+ {0, 125}
// All others reserved
};
-static const uint8_t fine_timebase_map[] =
+static const std::vector<std::pair<uint8_t, int64_t> > FINE_TIMEBASE_MAP =
{
- // // Units
- 1, // ps
+ // {key byte, fine timebase (in picoseconds)
+ {0, 1}
// All others reserved
};
-// =========================================================
-// Function implementations
-// =========================================================
-namespace check
-{
+/////////////////////////
+// Static member functions implementation
+/////////////////////////
+
///
-/// @brief Checks that stack type conforms to JEDEC table
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// @return fapi2::ReturnCode
-/// @note Consumed in (Byte 7) sdram_package_type(...)
-/// Item JC-45-2220.01x
-/// Page 20 (Terminology table)
-/// DDR4 SPD Document Release 3
-bool stack_type(const uint8_t i_stack_type, const uint8_t i_die_count)
+/// @brief Decodes SPD Revision encoding level
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value revision number
+/// @return fapi2::ReturnCode
+/// @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 decoder::rev_encoding_level(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- const size_t STACK_SDP = 0;
- const size_t STACK_DDP_QDP = 5;
- const size_t STACK_3DS = 6;
+ constexpr size_t BYTE_INDEX = 1;
+ constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_bit_fields = 0;
- const size_t SINGLE_DIE_PACKAGE = 1;
- const size_t DUAL_DIE_PACKAGE = 2;
- const size_t QUAD_DIE_PACKAGE = 4;
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_buffer(l_raw_byte);
- const size_t TWO_SDRAM_DIE = 2;
- const size_t EIGHT_SDRAM_DIE = 8;
+ // 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);
- // Use const or enums
- switch(i_stack_type)
- {
- case STACK_SDP:
- //SDP has single die
- return i_die_count == SINGLE_DIE_PACKAGE;
- break;
+ // Extracting desired bits
+ l_buffer.extractToRight<ENCODING_LEVEL_START, ENCODING_LEVEL_LEN>(l_bit_fields);
- case STACK_DDP_QDP:
- //DDP has 2 die, QDP has 4 die
- return (i_die_count == DUAL_DIE_PACKAGE) || (i_die_count == QUAD_DIE_PACKAGE);
- break;
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_bit_fields != UNDEFINED),
+ BYTE_INDEX,
+ l_raw_byte,
+ "Failed check on SPD rev encoding level") );
- case STACK_3DS:
- //3DS has 2 - 8 dies
- return (i_die_count >= TWO_SDRAM_DIE) && (i_die_count <= EIGHT_SDRAM_DIE);
- break;
+ // Update output only after check passes
+ o_value = l_bit_fields;
- default:
- return false; // Doesn't meet JEDEC spec
- }
-}// stack_type()
+ // Print decoded info
+ FAPI_DBG("%s. Rev - Encoding Level : %d",
+ c_str(i_target),
+ o_value);
-} // check namespace
+fapi_try_exit:
+ return fapi2::current_err;
+}
///
-/// @brief Calculates timing value
-/// @param[in] const int64_t& i_spd_timing_mtb,
-/// const int64_t& i_spd_timing_ftb,
-/// const int64_t& multiplier_mtb,
-/// const int64_t& multiplier_ftb
-/// @return int64_t, (timing value)
-inline int64_t calc_timing(const int64_t& i_spd_timing_mtb,
- const int64_t& i_spd_timing_ftb,
- const int64_t& multiplier_mtb,
- const int64_t& multiplier_ftb)
+/// @brief Decodes SPD Revision additions level
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value revision number
+/// @return fapi2::ReturnCode
+/// @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 decoder::rev_additions_level(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- int64_t timing_val = i_spd_timing_mtb * multiplier_mtb;
- int64_t offset = (i_spd_timing_ftb * multiplier_ftb);
- int64_t remainder_val = timing_val % multiplier_mtb;
+ constexpr size_t BYTE_INDEX = 1;
+ constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_bit_fields = 0;
- if( remainder_val == 0)
- {
- // If the timing value can be expressed as an integer number
- // of MTB units, return that
- return timing_val;
- }
- else
- {
- // Else round up and incorporate correction factor
- return (++timing_val) + offset;
- }
+ // Buffer used for bit manipulation
+ 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
+ l_buffer.extractToRight<ADDITIONS_LEVEL_START, ADDITIONS_LEVEL_LEN>(l_bit_fields);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_bit_fields != UNDEFINED),
+ BYTE_INDEX,
+ l_raw_byte,
+ "Failed check on SPD rev encoding level") );
+
+ // Update output only after check passes
+ o_value = l_bit_fields;
+
+ // Print decoded info
+ FAPI_DBG("%s. Rev - Additions Level : %d",
+ c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Decodes SPD number of bytes
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// size_t i_read_spd_size
+/// @brief Decodes base module type (DIMM type) from SPD
+/// @param[in] i_target
+/// @param[in] i_spd_data PD blob
+/// @param[out] o_value
/// @return fapi2::ReturnCode
-/// @note Decodes SPD Byte 0
+/// @note Decodes SPD Byte 3 (bits 0~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::number_of_bytes(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
+fapi2::ReturnCode decoder::base_module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
const uint8_t* i_spd_data,
- const size_t i_read_spd_size)
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 0;
+ constexpr size_t BYTE_INDEX = 3;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // SPD Bytes used mapping limits
- const size_t BYTES_USED_MAP_OFFSET = 1;
- const size_t BYTES_USED_MIN_VALID_KEY = 1; // All previous keys are not supported or reserved
- const size_t BYTES_USED_MAX_VALID_KEY = 4; // The rest are not supported or reserved
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Total SPD bytes mapping limits
- const size_t BYTES_TOTAL_MAP_OFFSET = 1;
- const size_t BYTES_TOTAL_MIN_VALID_KEY = 1; // All previous keys are not supported or reserved
- const size_t BYTES_TOTAL_MAX_VALID_KEY = 2; // The rest are not supported or reserved
+ // 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);
- // Byte variables used for decoding
- uint8_t l_spd_bytes_used = 0;
- uint8_t l_spd_bytes_total = 0;
- uint8_t l_reserved = 0;
- uint16_t l_total_bytes_map_val = 0;
- uint16_t l_used_bytes_map_val = 0;
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BASE_MODULE_START, BASE_MODULE_LEN>(l_field_bits);
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
- // Trace in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte 0: 0x%llX.",
- mss::c_str(i_target_dimm),
- i_spd_data[BYTE_INDEX]);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BASE_MODULE_TYPE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check on Base Module Type") );
- // Decoding 1st nibble, bits 3~0 (SPD Bytes Used)
- l_spd_buffer.extractToRight<BYTES_USED_START, BYTES_USED_LEN>(l_spd_bytes_used);
-
- // Check to assure SPD Bytes Used (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_spd_bytes_used >= BYTES_USED_MIN_VALID_KEY) &&
- (l_spd_bytes_used <= BYTES_USED_MAX_VALID_KEY),
- BYTE_INDEX,
- l_spd_bytes_used,
- "Failed check on Used SPD bytes") );
-
- // Decoding bits 6~4 (SPD Bytes Total)
- l_spd_buffer.extractToRight<BYTES_TOTAL_START, BYTES_TOTAL_LEN>(l_spd_bytes_total);
-
- // Check to assure SPD Bytes Total (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_spd_bytes_total >= BYTES_TOTAL_MIN_VALID_KEY) &&
- (l_spd_bytes_total <= BYTES_TOTAL_MAX_VALID_KEY),
- BYTE_INDEX,
- l_spd_bytes_total,
- "Failed check on total SPD bytes" ) );
-
- // Decoding bit 7 (Reserved bit)
- l_spd_buffer.extractToRight<BYTES_RESERVED_START, BYTES_RESERVED_LEN>(l_reserved);
-
- // Hold map values in temp variables
- l_used_bytes_map_val = bytes_used_map[l_spd_bytes_used - BYTES_USED_MAP_OFFSET];
- l_total_bytes_map_val = bytes_total_map[l_spd_bytes_total - BYTES_TOTAL_MAP_OFFSET];
-
- // Size of input SPD read should match size it claims to be based on the SPD spec
- // "Used SPD bytes" wasn't used since manufacturers may not use all available bytes
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_total_bytes_map_val == i_read_spd_size,
- BYTE_INDEX,
- l_total_bytes_map_val,
- "Failed SPD size check") );
-
- FAPI_INF("%s. Bytes Used: %d, Total Bytes: %d, Reserved : %d",
- mss::c_str(i_target_dimm),
- l_used_bytes_map_val,
- l_total_bytes_map_val,
- l_reserved);
+ FAPI_DBG("%s. Base Module Type: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Decodes SPD Revision
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// @param[in, out] uint8_t io_revision_num
-/// @return fapi2::ReturnCode
-/// @note Decodes SPD Byte 1
+/// @brief Object factory to select correct decoder based on SPD revision & dimm type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value shared pointer to the factory object
+/// @return fapi2::ReturnCode
///
-fapi2::ReturnCode decoder::revision(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::factory(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ std::shared_ptr<decoder>& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 1;
- const size_t UNDEFINED = 0xFF; // per JEDEC spec
+ uint8_t l_dimm_type = 0;
+ uint8_t l_encoding_rev = 0;
+ uint8_t l_additions_rev = 0;
- // Byte variables used for decoding
- uint8_t l_revision_num = 0;
+ // Get dimm type & revision levels
+ FAPI_TRY(base_module_type(i_target, i_spd_data, l_dimm_type));
+ FAPI_TRY(rev_encoding_level(i_target, i_spd_data, l_encoding_rev));
+ FAPI_TRY(rev_additions_level(i_target, i_spd_data, l_additions_rev));
- // Verify SPD revision is not undefined. Value is defined by the JEDEC spec
- l_revision_num = i_spd_data[BYTE_INDEX];
+ // 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:
+ o_value = 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
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_revision_num != UNDEFINED),
- BYTE_INDEX,
- l_revision_num,
- "Failed check on SPD revision") );
- // Print decoded info
- FAPI_INF("%s. SPD data at Byte %d: 0x%llX, Revision number : %d",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX],
- l_revision_num);
+ 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_try_exit:
return fapi2::current_err;
+
}
+
+/////////////////////////
+// Member Method implementation
+/////////////////////////
+
///
-/// @brief Decodes DRAM Device Type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes number of used SPD bytes
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of SPD bytes used
/// @return fapi2::ReturnCode
-/// @note Decodes SPD Byte 2
+/// @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::dram_device_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::number_of_used_bytes(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint16_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 2;
+ constexpr size_t BYTE_INDEX = 0;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+ uint16_t l_map_value = 0;
- // dram generation mapping limits
- const size_t MIN_VALID_KEY = 12; // All previous keys are not supported or reserved
- const size_t MAX_VALID_KEY = 13; // The rest are not supported or reserved
- const size_t MAP_OFFSET = 11; // SPD DRAM device type map has an index offset of 11 (simplifies array)
- // //since initial map values are not supported or reserved (ignored for now)
+ // Buffers used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BYTES_USED_START, BYTES_USED_LEN>(l_field_bits);
- // Byte variables used for decoding
- uint8_t l_device_type = 0;
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
- // Attribute variables used to set decoded vals
- uint8_t l_device_gen[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BYTES_USED_MAP, l_field_bits, l_map_value),
+ BYTE_INDEX,
+ l_map_value,
+ "Failed check on SPD total bytes") );
- // Check to assure SPD DRAM device type (map) wont be at invalid values
- l_device_type = i_spd_data[BYTE_INDEX];
+ // Don't update output with garbage data until until all tests pass
+ o_value = l_map_value;
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_device_type >= MIN_VALID_KEY) &&
- (l_device_type <= MAX_VALID_KEY),
- BYTE_INDEX,
- l_device_type,
- "Unsupported/reserved key value retried from SPD") );
+ FAPI_DBG("%s. Bytes Used: %d",
+ mss::c_str(i_target),
+ o_value);
- // Retrive entire MCS level attribute
- FAPI_TRY(eff_dram_gen(l_target_mcs, &l_device_gen[0][0]));
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Update attribute to decoded byte values
- l_device_gen[PORT_NUM][DIMM_NUM] = dram_gen_map[l_device_type - MAP_OFFSET];
+///
+/// @brief Decodes total number of SPD bytes
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of total SPD bytes
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint16_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 0;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, l_target_mcs, l_device_gen));
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Print decoded info
- FAPI_INF("%s SPD data at Byte %d: 0x%llX. Device type : %d",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX],
- l_device_gen[PORT_NUM][DIMM_NUM]);
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BYTES_TOTAL_START, BYTES_TOTAL_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(BYTES_TOTAL_MAP, l_field_bits, o_value),
+ 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 SPD module type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// @return fapi2::ReturnCode
-/// @note Decodes SPD Byte 3
+/// @brief Decodes DRAM Device Type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value dram device type enumeration
+/// @return fapi2::ReturnCode
+/// @note Decodes SPD Byte 2
+/// @note Item JC-45-2220.01x
+/// @note Page 16
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::dram_device_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 3;
- // Base module mapping limits // since first index is not supported
- const size_t BASE_MODULE_MAP_OFFSET = 1; // base_module_type_map has an index offset of 1
- const size_t MIN_VALID_KEY = 1; // All previous keys are not supported or reserved
- const size_t MAX_VALID_KEY = 4; // The rest are not supported or reserved
+ constexpr size_t BYTE_INDEX = 2;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
- // Hybrid Media limit
- const size_t MAX_HYBRID_MEDIA_KEY = 1; // All other key values reserved
+ // 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);
- // Hybrid
- const size_t MAX_HYBRID_KEY = 1; // Nothing else exits afterwards
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(DRAM_GEN_MAP, l_raw_byte, o_value),
+ BYTE_INDEX,
+ l_raw_byte,
+ "Failed check on SPD dram device type") );
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Print decoded info
+ FAPI_DBG("%s Device type : %d",
+ c_str(i_target),
+ o_value);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Byte variables used for decoding
- uint8_t l_base_module_type = 0;
- uint8_t l_hybrid_media = 0;
- uint8_t l_hybrid = 0;
+///
+/// @brief Decodes hybrid media field from SPD
+/// @param[in] i_target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing hybrid memory type
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
- // Attribute variables used to set decoded vals
- uint8_t l_module_type[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+{
+ constexpr size_t BYTE_INDEX = 3;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
// Trace in the front assists w/ debug
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<HYBRID_MEDIA_START, HYBRID_MEDIA_LEN>(l_field_bits);
- // Decoding bits 3~0
- l_spd_buffer.extractToRight<BASE_MODULE_START, BASE_MODULE_LEN>(l_base_module_type);
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
- // Check to assure SPD DRAM base module type (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_base_module_type >= MIN_VALID_KEY) &&
- (l_base_module_type <= MAX_VALID_KEY),
- BYTE_INDEX,
- l_base_module_type,
- "Failed check for SPD DRAM base module type") );
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(HYBRID_MEDIA_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check on Hybrid Media type") );
- // Decoding bits 6~4
- l_spd_buffer.extractToRight<HYBRID_MEDIA_START, HYBRID_MEDIA_LEN>(l_hybrid_media);
+ FAPI_DBG("%s. Hybrid Media: %d",
+ mss::c_str(i_target),
+ o_value);
- // Check to assure SPD DRAM hybrid media is valid
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_hybrid_media <= MAX_HYBRID_MEDIA_KEY,
- BYTE_INDEX,
- l_hybrid_media,
- "Failed check for SPD DRAM hybrid media") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Decoding bit 7
- l_spd_buffer.extractToRight<HYBRID_START, HYBRID_LEN>(l_hybrid);
+///
+/// @brief Decodes hybrid field from SPD
+/// @param[in] i_target
+/// @param[in] i_spd_data SPD blob
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 3;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+ // Buffer used for bit manipulation
+ 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);
- // Check to assure SPD DRAM hybrid media is valid
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_hybrid_media <= MAX_HYBRID_KEY,
- BYTE_INDEX,
- l_hybrid,
- "Failed check for SPD DRAM hybrid media") );
- // Retrive entire MCS level attribute
- FAPI_TRY(spd_module_type(l_target_mcs, &l_module_type[0][0]));
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<HYBRID_START, HYBRID_LEN>(l_field_bits);
- // Update attribute to decoded byte values
- l_module_type[PORT_NUM][DIMM_NUM] = base_module_type_map[l_base_module_type - BASE_MODULE_MAP_OFFSET];
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_SPD_MODULE_TYPE, l_target_mcs, l_module_type));
+ 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_INF("%s. Base Module Type: %d, Hybrid Media: %d, Hybrid: %d",
- c_str(i_target_dimm),
- l_module_type[PORT_NUM][DIMM_NUM],
- l_hybrid_media,
- l_hybrid);
+ FAPI_DBG("%s. Hybrid: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Decode SDRAM density
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM density from SPD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value SDRAM density in GBs
/// @return fapi2::ReturnCode
-/// @note SPD Byte 4
+/// @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_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::sdram_density(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+
{
- // Immutable constants
- const size_t BYTE_INDEX = 4;
- // DRAM capacity mapping limits
- const size_t CAPACITY_MAP_OFFSET = 1; // base_module_type_map has an index offset of 1
- const size_t CAPACITY_MIN_VALID_KEY = 2; // All previous keys are not supported or reserved
- const size_t CAPACITY_MAX_VALID_KEY = 9; // The rest are not supported or reserved
+ constexpr size_t BYTE_INDEX = 4;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // DRAM banks mapping limits
- const size_t BANKS_MAX_VALID_KEY = 1; // The rest are not supported or reserved
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(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);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN>(l_field_bits);
- // DRAM bank groups mapping limits
- const size_t BANK_GRP_MAX_VALID_KEY = 2; // The rest are not supported or reserved
+ // 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(SDRAM_DENSITY_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SPD DRAM capacity") );
+
+ FAPI_DBG("%s. SDRAM density: %d",
+ mss::c_str(i_target),
+ o_value);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+///
+/// @brief Decodes number of SDRAM banks from SPD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value Number of SDRAM banks
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
- // Byte variables used for decoding
- uint8_t l_sdram_capacity = 0;
- uint8_t l_sdram_banks = 0;
- uint8_t l_sdram_bank_group = 0;
+{
- // Attribute variables used to set decoded vals
- uint8_t l_capacities[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_banks[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_bank_groups[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ constexpr size_t BYTE_INDEX = 4;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
// Trace in the front assists w/ debug
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Decoding bits 3~0
- l_spd_buffer.extractToRight<SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN>(l_sdram_capacity);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SDRAM_BANKS_START, SDRAM_BANKS_LEN>(l_field_bits);
// Check to assure SPD DRAM capacity (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sdram_capacity >= CAPACITY_MIN_VALID_KEY) &&
- (l_sdram_capacity <= CAPACITY_MAX_VALID_KEY),
- BYTE_INDEX,
- l_sdram_capacity,
- "Failed check for SPD DRAM capacity") );
- // Decoding bits 5~4
- l_spd_buffer.extractToRight<SDRAM_BANKS_START, SDRAM_BANKS_LEN>(l_sdram_banks);
-
- // Check to assure SPD DRAM banks (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sdram_banks <= BANKS_MAX_VALID_KEY),
- BYTE_INDEX,
- l_sdram_banks,
- "Failed check for SPD DRAM banks") );
-
- // Decoding bits 7~6
- l_spd_buffer.extractToRight<BANK_GROUP_START, BANK_GROUP_LEN>(l_sdram_bank_group);
-
- // Check to assure SPD DRAM banks groups (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sdram_bank_group <= BANK_GRP_MAX_VALID_KEY),
- BYTE_INDEX,
- l_sdram_bank_group,
- "Failed check for SPD DRAM bank groups") );
-
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_density(l_target_mcs, &l_capacities[0][0]) );
- FAPI_TRY( eff_dram_banks(l_target_mcs, &l_banks[0][0]) );
- FAPI_TRY( eff_dram_bank_groups(l_target_mcs, &l_bank_groups[0][0]) );
-
- // Update attribute to decoded byte values
- l_capacities[PORT_NUM][DIMM_NUM] = sdram_capacity_map[l_sdram_capacity - CAPACITY_MAP_OFFSET];
- l_banks[PORT_NUM][DIMM_NUM] = sdram_banks_map[l_sdram_banks];
- l_bank_groups[PORT_NUM][DIMM_NUM] = sdram_bankgroups_map[l_sdram_bank_group];
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DENSITY, l_target_mcs, l_capacities));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_BANKS, l_target_mcs, l_banks));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_BANK_GROUPS, l_target_mcs, l_bank_groups));
-
- FAPI_INF("%s. SDRAM capacity: %d, banks: %d, bank groups: %d",
- c_str(i_target_dimm),
- sdram_capacity_map[l_sdram_capacity],
- sdram_banks_map[l_sdram_banks],
- sdram_bankgroups_map[l_sdram_bank_group]);
+ 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 Decode SDRAM addressing
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes number of SDRAM bank groups from SPD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value Number of SDRAM bank groups
/// @return fapi2::ReturnCode
-/// @note SPD Byte 5
+/// @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::sdram_addressing(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::bank_groups(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 5;
- // DRAM column address mapping limits
- const size_t COLUMN_MAX_VALID_KEY = 3; // The rest are not supported or reserved
- // DRAM row address mapping limits
- const size_t ROW_MAX_VALID_KEY = 6; // The rest are not supported or reserved
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Byte variables used for decoding
- uint8_t l_column_addr = 0;
- uint8_t l_row_addr = 0;
- uint8_t l_reserved = 0;
-
- // Attribute variables used to set decoded vals
- uint8_t l_columns[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_rows[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ constexpr size_t BYTE_INDEX = 4;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
// Trace in the front assists w/ debug
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Decoding bits 2~0 (Column Address bits)
- l_spd_buffer.extractToRight<COL_ADDRESS_START, COL_ADDRESS_LEN>(l_column_addr);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BANK_GROUP_START, BANK_GROUP_LEN>(l_field_bits);
- // Check to assure SPD DRAM Column Address bits (map) wont be indexed at invalid values
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_column_addr <= COLUMN_MAX_VALID_KEY),
- BYTE_INDEX,
- l_column_addr,
- "Failed check for SPD DRAM bank groups") );
-
- // Decoding bits 3~0 (Row address bits)
- l_spd_buffer.extractToRight<ROW_ADDRESS_START, ROW_ADDRESS_LEN>(l_row_addr);
-
- // Check to assure SPD DRAM Row address bits (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_row_addr <= ROW_MAX_VALID_KEY),
- BYTE_INDEX,
- l_row_addr,
- "Failed check for SPD DRAM bank groups") );
-
- // Decoding bits 7~6
- l_spd_buffer.extractToRight<ADDRESS_RESERVED_START, ADDRESS_RESERVED_LEN>(l_reserved);
-
- // Check to assure SPD reserved bits are 0 as defined in JEDEC SPD spec
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_reserved == 0),
- BYTE_INDEX,
- l_reserved,
- "Failed check for SPD DRAM bank groups") );
-
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_cols(l_target_mcs, &l_columns[0][0]) );
- FAPI_TRY( eff_dram_rows(l_target_mcs, &l_rows[0][0]) );
-
- // Update attribute to decoded byte values
- l_columns[PORT_NUM][DIMM_NUM] = column_address_map[l_column_addr];
- l_rows[PORT_NUM][DIMM_NUM] = row_address_map[l_row_addr];
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_COLS, l_target_mcs, l_columns));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_ROWS, l_target_mcs, l_rows));
-
- FAPI_INF("%s. Columns: %d, Rows: %d",
- c_str(i_target_dimm),
- l_columns[PORT_NUM][DIMM_NUM],
- l_rows[PORT_NUM][DIMM_NUM]);
+ // 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_GROUP_BITS_MAP, l_field_bits, o_value),
+ 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 Decode SDRAM Package Type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes number of SDRAM column address bits
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of column address bits
/// @return fapi2::ReturnCode
-/// @note SPD Byte 6
+/// @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::primary_package_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::column_address_bits(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 6;
- const size_t INVALID_VALUE = 0x11; //per JEDEC spec
- const size_t RESERVED = 0;
- // DRAM die count mapping limits
- const size_t DIE_COUNT_MAX_VALID_KEY = 7; // Nothing greater doesn't exist
- const size_t INVALID_PACKAGE_TYPE = ~0;
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<COL_ADDRESS_START, COL_ADDRESS_LEN>(l_field_bits);
- // Byte variables used for decoding
- uint8_t l_prim_signal_loading = 0;
- uint8_t l_reserved = 0;
- uint8_t l_prim_die_count = 0;
- uint8_t l_prim_package_type = 0;
+ // 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(COLUMN_ADDRESS_BITS_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SDRAM Column Address Bits") );
- // Attribute variables used to set decoded vals
- uint8_t l_stack_type = 0;
- uint8_t l_sdram_package_type[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_sdram_die_count[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ 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 FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of row address bits
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<ROW_ADDRESS_START, ROW_ADDRESS_LEN>(l_field_bits);
- // Decoding bits 1~0 (Signal loading)
- l_spd_buffer.extractToRight<PRIM_PRIM_SIGNAL_LOAD_START, PRIM_PRIM_SIGNAL_LOAD_LEN>(l_prim_signal_loading);
-
- // Check to assure SPD DRAM signal loading conforms to JEDEC SPEC
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_prim_signal_loading != INVALID_VALUE),
- BYTE_INDEX,
- l_prim_signal_loading,
- "Failed check for SPD DRAM signal loading") );
- // Decoding bits 3~2 (Reserved)
- l_spd_buffer.extractToRight<PACKAGE_RESERVE_START, PACKAGE_RESERVE_LEN>(l_reserved);
-
- // Check to assure SPD reserved bits are 0 as defined in JEDEC SPD spec
- mss::check::spd::valid_value_warn(i_target_dimm,
- (l_reserved == RESERVED),
- BYTE_INDEX,
- l_reserved,
- "Failed check for SPD DRAM reserved bits");
-
- // Decoding bits 6~4 (Die Count)
- l_spd_buffer.extractToRight<PRIM_DIE_COUNT_START, PRIM_DIE_COUNT_LEN>(l_prim_die_count);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_prim_die_count <= DIE_COUNT_MAX_VALID_KEY),
- BYTE_INDEX,
- l_prim_die_count,
- "Failed check for SPD DRAM die count") );
- // Decoding bit 7
- l_spd_buffer.extractToRight<PRIM_PACKAGE_TYPE_START, PRIM_PACKAGE_TYPE_LEN>(l_prim_package_type);
-
- // Manipulating and combining l_prim_package_type and l_prim_signal_loading to produce the following
- // table for indexing the package_type_map[].
- // 0000 0000 = SDP (monolithic device)
- // 0000 0101 = DDP/QDP (non-monolithic device)
- // 0000 0110 = 3DS (non-monolithic device)
- // What this essentially does is remove reserved bits.
- // This was done to avoid having large gaps (of 0's) in the package_type_map (sparsed array)
- // since we can't use std::map due to thread saftey issues
- l_stack_type = (l_prim_package_type >> 5) | l_prim_signal_loading;
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- check::stack_type(l_stack_type, die_count_map[l_prim_die_count]) &&
- (package_type_map[l_stack_type] != INVALID_PACKAGE_TYPE),
- BYTE_INDEX,
- package_type_map[l_stack_type],
- "Failed check for SPD DRAM stack type") );
-
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_stack_type(l_target_mcs, &l_sdram_package_type[0][0]) );
- FAPI_TRY( eff_prim_die_count(l_target_mcs, &l_sdram_die_count[0][0]) );
-
- // Update attribute to decoded byte values
- l_sdram_die_count[PORT_NUM][DIMM_NUM] = die_count_map[l_prim_die_count];
- l_sdram_package_type[PORT_NUM][DIMM_NUM] = package_type_map[l_stack_type];
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_STACK_TYPE, l_target_mcs, l_sdram_package_type));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_PRIM_DIE_COUNT, l_target_mcs, l_sdram_die_count));
-
- FAPI_INF("%s. Signal loading: %d, Die count: %d, Stack type: %d",
- c_str(i_target_dimm),
- l_prim_signal_loading,
- die_count_map[l_prim_die_count],
- l_sdram_package_type[PORT_NUM][DIMM_NUM]);
+ // 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(ROW_ADDRESS_BITS_MAP, l_field_bits, o_value),
+ 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;
}
-//TODO
-// Need to complete this function, map need tREF1 calculations
///
-/// @brief Decode SDRAM Optional Features
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Primary SDRAM signal loading
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing signal loading type
/// @return fapi2::ReturnCode
-/// @note SPD Byte 7
+/// @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::sdram_optional_features(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::prim_sdram_signal_loading(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 7;
- const size_t RESERVED = 0;
- // MAC mapping limits
- const size_t MAC_RESERVED = 7; //per JEDEC spec
- const size_t MAC_MAX_VALID_KEY = 8;
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+
+ // Buffer used for bit manipulation
+ 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
+ l_spd_buffer.extractToRight<PRIM_SIGNAL_LOAD_START, PRIM_SIGNAL_LOAD_LEN>(l_field_bits);
- // TMAW mappint limits
- const size_t TMAW_MAX_VALID_KEY = 2;
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(PRIM_SIGNAL_LOADING_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Primary SDRAM Signal Loading") );
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ FAPI_DBG("%s. Primary SDRAM Signal Loading: %d",
+ mss::c_str(i_target),
+ o_value);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Byte variables used for decoding
- uint16_t l_MAC = 0; // Maximum Active Count
- uint16_t l_tMAW = 0; // Maximum Active Window
- uint8_t l_reserved = 0;
+///
+/// @brief Decodes Primary SDRAM die count
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value die count
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- // Attribute variables used to set decoded vals
- uint16_t l_mac[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint16_t l_tmaw[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Decoding bits 3~0 (MAC)
- l_spd_buffer.extractToRight<MAC_START, MAC_LEN>(l_MAC);
- // Check to assure SPD DRAM signal loading conforms to JEDEC SPEC
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_MAC <= MAC_MAX_VALID_KEY) &&
- l_MAC != MAC_RESERVED,
- BYTE_INDEX,
- l_MAC,
- "Failed check for Maximum Active Count (MAC)") );
-
- // Decoding bits 5~4 (tMAW)
- l_spd_buffer.extractToRight<TMAW_START, TMAW_LEN>(l_tMAW);
-
- // Check to assure SPD DRAM signal loading conforms to JEDEC SPEC
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tMAW <= TMAW_MAX_VALID_KEY),
- BYTE_INDEX,
- l_tMAW,
- "Failed check for Maximum Active Window (tMAW)") );
-
- // Decoding bits 7~6 (Reserved)
- l_spd_buffer.extractToRight<OPT_FEAT_RESERVED_START, OPT_FEAT_RESERVED_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- (l_reserved == RESERVED),
- BYTE_INDEX,
- l_reserved,
- "Failed check for Reserved bits") ;
-
- // Retrive entire MCS level attribute
- FAPI_TRY(eff_dram_mac(l_target_mcs, &l_mac[0][0]));
- FAPI_TRY(eff_dram_tmaw(l_target_mcs, &l_tmaw[0][0]));
-
- // Update attribute to decoded byte values
- l_mac[PORT_NUM][DIMM_NUM] = MAC_map[l_MAC];
- l_tmaw[PORT_NUM][DIMM_NUM] = tMAW_map[l_tMAW];
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_MAC, l_target_mcs, l_mac));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TMAW, l_target_mcs, l_tmaw));
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<PRIM_DIE_COUNT_START, PRIM_DIE_COUNT_LEN>(l_field_bits);
- // Print decoded info
- FAPI_INF("%s. MAC: %d, tMAW: %d",
- c_str(i_target_dimm),
- l_tmaw[PORT_NUM][DIMM_NUM],
- l_mac[PORT_NUM][DIMM_NUM]);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(PRIM_DIE_COUNT_MAP, l_field_bits, o_value),
+ 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;
-}// decode_sdram_optional_features()
+}
///
-/// @brief Decode SDRAM Thermal and Refresh Options
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Primary SDRAM package type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing package type
/// @return fapi2::ReturnCode
-/// @note SPD Byte 8, currently reserved
+/// @note SPD Byte 6 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 19
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::thermal_and_refresh_options(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::prim_sdram_package_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 8;
- const size_t RESERVED_BYTE = 0; // per JEDEC spec
- // Byte variable
- uint8_t l_reserved = i_spd_data[BYTE_INDEX];
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Check to assure SPD reserved byte is 0 per JEDEC spec
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_reserved == RESERVED_BYTE),
- BYTE_INDEX,
- l_reserved,
- "Failed check for SPD DRAM reserved byte") );
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Print decoded info
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<PRIM_PACKAGE_TYPE_START, PRIM_PACKAGE_TYPE_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(PRIM_PACKAGE_TYPE_MAP, l_field_bits, o_value),
+ 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;
-}// decode_thermal_and_refresh_options()
+}
///
-/// @brief Decode Other SDRAM Optional Features
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode SDRAM Maximum activate count
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing max activate count
/// @return fapi2::ReturnCode
-/// @note SPD Byte 9
+/// @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::other_optional_features(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::maximum_activate_count(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint32_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 9;
- const size_t RESERVED = 0;
- // Soft PPR mapping limits
- const size_t SOFT_PPR_MAX_VALID_KEY = 2; // Nothing greater doesn't exist
+ constexpr size_t BYTE_INDEX = 7;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // PPR mapping limits
- const size_t PPR_MAX_VALID_KEY = 2; // Nothing greater doesn't exist
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<MAC_START, MAC_LEN>(l_field_bits);
- // Byte variables used for decoding
- uint8_t l_reserved = 0;
- uint8_t l_soft_ppr = 0;// Soft Post Package Repair
- uint8_t l_ppr = 0; // Post Package Repair
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(MAC_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SDRAM Maximum Active Count (MAC)") );
- // Attribute variables used to set decoded vals
- uint8_t l_soft_PPRs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_PPRs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_DBG("%s. Maximum Active Count (MAC): %d",
+ mss::c_str(i_target),
+ o_value);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value max activate window multiplier
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint32_t& o_value)
+{
+
+ constexpr size_t BYTE_INDEX = 7;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Decoding bits 4~0
- l_spd_buffer.extractToRight<PPR_RESERVED_START, PPR_RESERVED_LEN>(l_reserved);
+ // 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
+ l_spd_buffer.extractToRight<TMAW_START, TMAW_LEN>(l_field_bits);
- mss::check::spd::valid_value_warn(i_target_dimm,
- (l_reserved == RESERVED),
- BYTE_INDEX,
- l_reserved,
- "Failed check for reserved bits");
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(TMAW_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Maximum Active Window (tMAW)") );
- // Decoding bit 5
- l_spd_buffer.extractToRight<SOFT_PPR_START, SOFT_PPR_LEN>(l_soft_ppr);
+ FAPI_DBG("%s. Maximum Active Window multiplier: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_soft_ppr < SOFT_PPR_MAX_VALID_KEY),
- BYTE_INDEX,
- l_soft_ppr,
- "Failed check for SOFT PPR") );
+///
+/// @brief Decode Soft post package repair (soft PPR)
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing if soft PPR is supported
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- // Decoding bits 7~6
- l_spd_buffer.extractToRight<PPR_START, PPR_LEN>(l_ppr);
+ constexpr size_t BYTE_INDEX = 9;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_ppr < PPR_MAX_VALID_KEY),
- BYTE_INDEX,
- l_ppr,
- "Failed check for PPR") );
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Retrive entire MCS level attribute
- FAPI_TRY(eff_dram_soft_ppr(l_target_mcs, &l_soft_PPRs[0][0]));
- FAPI_TRY(eff_dram_ppr(l_target_mcs, &l_PPRs[0][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,
+ l_raw_byte);
- // Update attribute to decoded byte values
- l_soft_PPRs[PORT_NUM][DIMM_NUM] = soft_ppr_map[l_soft_ppr];
- l_PPRs[PORT_NUM][DIMM_NUM] = ppr_map[l_ppr];
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SOFT_PPR_START, SOFT_PPR_LEN>(l_field_bits);
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_SOFT_PPR, l_target_mcs, l_soft_PPRs));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_PPR, l_target_mcs, l_PPRs));
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(SOFT_PPR_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Soft PPR") );
- // Printed decoded info
- FAPI_INF("%s. Soft PPR: %d, PPR: %d, Reserved: %d",
- c_str(i_target_dimm),
- l_soft_PPRs[PORT_NUM][DIMM_NUM],
- l_PPRs[PORT_NUM][DIMM_NUM],
- l_reserved);
+ 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 Secondary SDRAM Package Type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode Post package repair (PPR)
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing if (hard) PPR is supported
/// @return fapi2::ReturnCode
-/// @note SPD Byte 10
+/// @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::secondary_package_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::post_package_repair(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 10;
- const size_t SUPPORTED_VALUE = 0;
- // Byte variables used for decoding
- uint8_t l_sec_signal_loading = 0;
- uint8_t l_density_ratio = 0;
- uint8_t l_sec_die_count = 0;
- uint8_t l_sec_package_type = 0;
+ constexpr size_t BYTE_INDEX = 9;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Buffer used for bit manipulation
+ 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,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Currently we do not support asymmetrical assembly of multiple SDRAM package types
- // According to the JEDEC spec, for modules with symmetrical assembly (which we do support),
- // this byte must be coded as 0x00. Additional checks were added to isolate any corrupt data failure
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<PPR_START, PPR_LEN>(l_field_bits);
- // Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(PPR_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for PPR") );
- // Decoding bits 1~0 (Signal loading)
- l_spd_buffer.extractToRight<SEC_SIGNAL_LOAD_START, SEC_SIGNAL_LOAD_LEN>(l_sec_signal_loading);
-
- // Check to assure SPD DRAM signal loading conforms to JEDEC SPEC
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sec_signal_loading == SUPPORTED_VALUE),
- BYTE_INDEX,
- l_sec_signal_loading,
- "Failed check for SPD DRAM signal loading") );
-
- // Decoding bits 3~2 (Density Ratio)
- l_spd_buffer.extractToRight<DENSITY_RATIO_START, DENSITY_RATIO_LEN>(l_density_ratio);
-
- // Check to assure SPD density ratio bits are 0 to assure symmetical package
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_density_ratio == SUPPORTED_VALUE),
- BYTE_INDEX,
- l_density_ratio,
- "Failed check for SPD DRAM density ratio") );
-
- // Decoding bits 6~4 (Die Count)
- l_spd_buffer.extractToRight<SEC_DIE_COUNT_START, SEC_DIE_COUNT_LEN>(l_sec_die_count);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sec_die_count == SUPPORTED_VALUE),
- BYTE_INDEX,
- l_sec_die_count,
- "Failed check for SPD DRAM secondary die count") );
-
- // Decoding bit 7
- l_spd_buffer.extractToRight<SEC_PACKAGE_TYPE_START, SEC_PACKAGE_TYPE_LEN>(l_sec_package_type);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sec_package_type == SUPPORTED_VALUE),
- BYTE_INDEX,
- l_sec_package_type,
- "Failed check for SPD DRAM secondary package type") );
-
- // Printed decoded info
- FAPI_INF("Signal Loading: %d, DRAM Density Ratio: %d, Die Count: %d, SDRAM Package Type: %d",
- l_sec_signal_loading,
- l_density_ratio,
- l_sec_die_count,
- l_sec_package_type);
+ FAPI_DBG("%s. Post Package Repair (PPR): %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
+
///
-/// @brief Decode Module Nominal Voltage, VDD
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Secondary SDRAM signal loading
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing signal loading type
/// @return fapi2::ReturnCode
-/// @note SPD Byte 11
+/// @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::module_nominal_voltage(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::sec_sdram_signal_loading(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 11;
- const size_t RESERVED = 0; // per JEDEC sepc
- const size_t SUPPORTED = 1; // per JEDEC sepc
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
- // Byte variables used for decoding
- uint8_t l_operable = 0;
- uint8_t l_endurant = 0;
- uint8_t l_reserved = 0;
+ constexpr size_t BYTE_INDEX = 10;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Attribute variables used to set decoded vals
- uint64_t l_operable_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SEC_SIGNAL_LOAD_START, SEC_SIGNAL_LOAD_LEN>(l_field_bits);
- // Decoding bits 0 (Operable)
- l_spd_buffer.extractToRight<OPERABLE_START, OPERABLE_LEN>(l_operable);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(SEC_SIGNAL_LOADING_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SDRAM Row Address Bits") );
- // DDR4 only supports 1.2 V, if not OPERABLE at this voltage than fail IPL
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_operable == SUPPORTED,
- BYTE_INDEX,
- l_operable,
- "Failed check for OPERABLE module nominal voltage") );
- // Decoding bits 1 (Endurant)
- l_spd_buffer.extractToRight<ENDURANT_START, ENDURANT_LEN>(l_endurant);
+ FAPI_DBG("%s. Number of Row Address Bits: %d",
+ mss::c_str(i_target),
+ o_value);
- // OPERABLE at 1.2V implies ENDURANT at 1.2V
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_endurant == SUPPORTED,
- BYTE_INDEX,
- l_endurant,
- "Failed check for ENDURABLE module nominal voltage") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Decoding bits 7~2 (Reserved)
- l_spd_buffer.extractToRight<NOM_VOLT_START, NOM_VOLT_LEN>(l_reserved);
+///
+/// @brief Decodes Secondary DRAM Density Ratio
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value raw bits from SPD
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for module nominal voltage RESERVED bits");
+ constexpr size_t BYTE_INDEX = 10;
+ constexpr size_t UNDEFINED = 3; // JEDEC map doesn't go beyond 3
- // Retrive entire MCS level attribute
- FAPI_TRY(spd_module_nominal_voltage(l_target_mcs, &l_operable_attrs[0][0]));
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Update attribute to decoded byte values
- l_operable_attrs[PORT_NUM][DIMM_NUM] = l_operable;
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_SPD_MODULE_NOMINAL_VOLTAGE, l_target_mcs, l_operable_attrs) );
+ // 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);
- // Printed decoded info
- FAPI_INF( "%s Operable: %d, Endurant: %d, Reserved: %d",
- c_str(i_target_dimm),
- l_operable,
- l_endurant,
- l_reserved );
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<DENSITY_RATIO_START, DENSITY_RATIO_LEN>(l_field_bits);
+ 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 Decode Module Organization
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Secondary SDRAM die count
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value die count
/// @return fapi2::ReturnCode
-/// @note SPD Byte 12
+/// @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::module_organization(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::sec_sdram_die_count(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 12;
- const size_t RESERVED = 0;
- // SDRAM device width mapping limits
- const size_t MAX_DEV_WIDTH_VALID_KEY = 3; // All others reserved
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Number of package ranks per DIMM mapping limits
- const size_t MAX_PKG_RANKS_VALID_KEY = 7; // max supported packages
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Rank mix limits
- const size_t SYMMETRICAL = 0; // asymmetical not supported
+ // 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);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SEC_DIE_COUNT_START, SEC_DIE_COUNT_LEN>(l_field_bits);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(SEC_DIE_COUNT_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Secondary Die Count") );
- // Byte variables used for decoding
- uint8_t l_device_width = 0;
- uint8_t l_num_pkgs_ranks = 0;
- uint8_t l_rank_mix = 0;
- uint8_t l_reserved = 0;
+ FAPI_DBG("%s. Secondary Die Count: %d",
+ mss::c_str(i_target),
+ o_value);
- // Attribute variables used to set decoded vals
- uint8_t l_sdram_device_widths[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_num_pkg_ranks_per_dimm[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_rank_mixes[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+fapi_try_exit:
+ return fapi2::current_err;
+}
+///
+/// @brief Decodes Secondary SDRAM package type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing package type
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Decoding Bits 2~0
- l_spd_buffer.extractToRight<SDRAM_WIDTH_START, SDRAM_WIDTH_LEN>(l_device_width);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_device_width <= MAX_DEV_WIDTH_VALID_KEY,
- BYTE_INDEX,
- l_device_width,
- "Failed check for SDRAM device width") );
- // Decoding Bits 5~3
- l_spd_buffer.extractToRight<PACKAGE_RANKS_START, PACKAGE_RANKS_LEN>(l_num_pkgs_ranks);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_num_pkgs_ranks <= MAX_PKG_RANKS_VALID_KEY,
- BYTE_INDEX,
- l_num_pkgs_ranks,
- "Failed check for number of packages per DIMM") );
- // Decoding Bit 6
- l_spd_buffer.extractToRight<RANK_MIX_START, RANK_MIX_LEN>(l_rank_mix);
-
- // We only support symmetrical rank mix
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_rank_mix == SYMMETRICAL,
- BYTE_INDEX,
- l_rank_mix,
- "Failed check for number of packages per DIMM") );
- // Decoding Bit 7
- l_spd_buffer.extractToRight<MODULE_ORG_RESERVED_START, MODULE_ORG_RESERVED_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for number of packages per DIMM");
-
- // Retrive entire MCS level attribute
- FAPI_TRY(eff_dram_width(l_target_mcs, &l_sdram_device_widths[0][0]));
- FAPI_TRY(eff_num_packages_per_rank(l_target_mcs, &l_num_pkg_ranks_per_dimm[0][0]));
- FAPI_TRY(eff_dram_rank_mix(l_target_mcs, &l_rank_mixes[0][0]));
-
- // Update attribute to decoded byte values
- l_sdram_device_widths[PORT_NUM][DIMM_NUM] = device_type_map[l_device_width];
- l_num_pkg_ranks_per_dimm[PORT_NUM][DIMM_NUM] = num_pkgs_ranks_per_dimm_map[l_num_pkgs_ranks];
- l_rank_mixes[PORT_NUM][DIMM_NUM] = l_rank_mix;
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_WIDTH, l_target_mcs, l_sdram_device_widths) );
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_PACKAGES_PER_RANK, l_target_mcs, l_num_pkg_ranks_per_dimm) );
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RANK_MIX, l_target_mcs, l_rank_mixes) );
-
- // Printed decoded info
- FAPI_INF( "%s. Device Width: %d, Number of rank packages per DIMM: %d, Rank Mix: %d",
- c_str(i_target_dimm),
- l_sdram_device_widths[PORT_NUM][DIMM_NUM],
- l_num_pkg_ranks_per_dimm[PORT_NUM][DIMM_NUM],
- l_rank_mixes[PORT_NUM][DIMM_NUM] );
+ // 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
+ l_spd_buffer.extractToRight<SEC_PACKAGE_TYPE_START, SEC_PACKAGE_TYPE_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(SEC_PACKAGE_TYPE_MAP, l_field_bits, o_value),
+ 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;
}
-//TODO
-// Returning correct stuff (bits) ?? Or am I supposed to calc "Module DRAM Capacity" pg 27
///
-/// @brief Decode Module Memory Bus Width
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode Module Nominal Voltage, VDD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing if 1.2V is operable
/// @return fapi2::ReturnCode
-/// @note SPD Byte 13
+/// @note SPD Byte 11 (bit 0)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::module_memory_bus_width(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::operable_nominal_voltage(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 13;
- const size_t RESERVED = 0;
- // Primary bus width mapping limits
- const size_t MAX_PRIM_BUS_WIDTH_KEY = 3; // All others reserved
+ constexpr size_t BYTE_INDEX = 11;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Bus width extention mapping limits
- const size_t MAX_VALID_BUS_WIDTH_EXT_KEY = 1; // All others reserved
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<OPERABLE_START, OPERABLE_LEN>(l_field_bits);
- // Byte variables used for decoding
- uint8_t l_bus_width = 0;
- uint8_t l_bus_width_ext = 0;
- uint8_t l_reserved = 0;
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(OPERABLE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Endur") );
- // Attribute variables used to set decoded vals
- uint8_t l_module_bus_widths[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_DBG("%s. Operable: %d",
+ mss::c_str(i_target),
+ o_value);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode Module Nominal Voltage, VDD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing if 1.2V is endurant
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+
+ constexpr size_t BYTE_INDEX = 11;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Decoding Bits 2~0
- l_spd_buffer.extractToRight<BUS_WIDTH_START, BUS_WIDTH_LEN>(l_bus_width);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_bus_width <= MAX_PRIM_BUS_WIDTH_KEY,
- BYTE_INDEX,
- l_bus_width,
- "Failed check on primary bus width") );
- // Decoding Bits 4~3
- l_spd_buffer.extractToRight<BUS_EXT_WIDTH_START, BUS_EXT_WIDTH_LEN>(l_bus_width_ext);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_bus_width_ext <= MAX_VALID_BUS_WIDTH_EXT_KEY,
- BYTE_INDEX,
- l_bus_width_ext,
- "Failed check for bus width extension") );
- // Decoding bits Bits 7~5
- l_spd_buffer.extractToRight<BUS_WIDTH_RESERVED_START, BUS_WIDTH_RESERVED_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for bus width reserved bits");
-
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_module_bus_width(l_target_mcs, &l_module_bus_widths[0][0]) );
-
- // Update attribute to decoded byte values
- l_module_bus_widths[PORT_NUM][DIMM_NUM] = prim_bus_width_map[l_bus_width] + bus_width_ext_map[l_bus_width_ext];
-
- // Update MCS level attribute
- FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_MODULE_BUS_WIDTH, l_target_mcs, l_module_bus_widths);
-
- // Printed decoded info
- FAPI_INF( "%s Module Memory Bus Width (in bits): %d, Primary bus width: %d, Bus width extension: %d",
- c_str(i_target_dimm),
- l_module_bus_widths[PORT_NUM][DIMM_NUM],
- prim_bus_width_map[l_bus_width],
- bus_width_ext_map[l_bus_width_ext] );
+ // 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
+ l_spd_buffer.extractToRight<ENDURANT_START, ENDURANT_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(ENDURANT_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Endurant") );
+
+ FAPI_DBG("%s. Endurant: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
-
///
-/// @brief Decode Module Thermal Sensor
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM device width
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value device width in bits
/// @return fapi2::ReturnCode
-/// @note SPD Byte 14, no attribute found for this
+/// @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::module_thermal_sensor(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::device_width(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 14;
- const size_t VALID_VALUE = 1;
- const size_t RESERVED = 0;
- // Byte variables used for decoding
- uint8_t l_reserved = 0;
- uint8_t l_thermal_sensor = 0;
+ constexpr size_t BYTE_INDEX = 12;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Attribute variables used to set decoded vals
- uint8_t l_therm_sensors[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SDRAM_WIDTH_START, SDRAM_WIDTH_LEN>(l_field_bits);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(DEVICE_WIDTH_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Device Width") );
- // Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ FAPI_DBG("%s. Device Width: %d",
+ mss::c_str(i_target),
+ o_value);
- // Decoding Bits 6~0
- l_spd_buffer.extractToRight<THERM_SENSOR_RESERV_START, THERM_SENSOR_RESERV_LEN>(l_reserved);
+fapi_try_exit:
+ return fapi2::current_err;
+}
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for thermal sensor reserved bits");
- // Decoding bits Bit 7
- l_spd_buffer.extractToRight<THERM_SENSOR_START, THERM_SENSOR_LEN>(l_thermal_sensor);
- // Length is a single bit (0 or 1), anything larger means corrupt data
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_thermal_sensor <= VALID_VALUE,
- BYTE_INDEX,
- l_thermal_sensor,
- "Failed check for thermal sensor") );
+///
+/// @brief Decodes number of package ranks per DIMM
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of package ranks per DIMM
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- // Retrive entire MCS level attribute
- FAPI_TRY( spd_module_thermal_sensor(l_target_mcs, &l_therm_sensors[0][0]) );
+ constexpr size_t BYTE_INDEX = 12;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Update attribute to decoded byte values
- l_therm_sensors[PORT_NUM][DIMM_NUM] = l_thermal_sensor;
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Update MCS level attribute
- FAPI_ATTR_SET(fapi2::ATTR_SPD_MODULE_THERMAL_SENSOR, l_target_mcs, l_therm_sensors);
+ // 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
+ l_spd_buffer.extractToRight<PACKAGE_RANKS_START, PACKAGE_RANKS_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(NUM_PACKAGE_RANKS_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Num Package Ranks Per DIMM") );
- // Printed decoded info
- FAPI_INF("%s. Thermal sensor: %d, Reserved: %d",
- c_str(i_target_dimm),
- l_thermal_sensor,
- l_reserved );
+ FAPI_DBG("%s. Num Package Ranks per DIMM: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Decode Extended Module Type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Rank Mix
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value rank mix value from SPD
/// @return fapi2::ReturnCode
-/// @note SPD Byte 15, no attribute for this byte
+/// @note SPD Byte 12 (bit 6)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::extended_module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::rank_mix(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 15;
- const size_t RESERVED = 0;
- // Byte variables used for decoding
- uint8_t l_ext_module_type = 0;
- uint8_t l_reserved = 0;
+ constexpr size_t BYTE_INDEX = 12;
+ constexpr size_t INVALID_VALUE = 2;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Buffer used for bit manipulation
+ 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,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<RANK_MIX_START, RANK_MIX_LEN>(l_field_bits);
- // Decoding Bits 3~0
- l_spd_buffer.extractToRight<EXT_MOD_TYPE_START, EXT_MOD_TYPE_LEN>(l_ext_module_type);
+ 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") );
- // According to JEDEC spec this value should be coded as 0000 which is the value as the reserved bits
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- l_ext_module_type == RESERVED,
- BYTE_INDEX,
- l_ext_module_type,
- "Failed check for extended base module type") );
- // Decoding Bit 7~4
- l_spd_buffer.extractToRight<EXT_MOD_TYPE_RESERV_START, EXT_MOD_TYPE_RESERV_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for extended module type reserved bits");
-
- // Printed decoded info
- FAPI_INF("%s. Extended Base Module Type: %d, Reserved: %d",
- c_str(i_target_dimm),
- l_ext_module_type,
- l_reserved );
+ 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 Decode Timebases
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes primary bus width
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value primary bus width in bits
/// @return fapi2::ReturnCode
-/// @note SPD Byte 17
+/// @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::timebases(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::prim_bus_width(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 17;
- const size_t RESERVED = 0;
+ constexpr size_t BYTE_INDEX = 13;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Medium timebase mapping limits
- const int64_t MAX_VALID_MTB_KEY = 1; // All others reserved
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Fine timebase mapping limits
- const int64_t MAX_VALID_FTB_KEY = 1; // All others reserved
+ // 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);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BUS_WIDTH_START, BUS_WIDTH_LEN>(l_field_bits);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BUS_WIDTH_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Primary Bus Width") );
- // Byte variables used for decoding
- int64_t l_fine_timebase = 0;
- int64_t l_medium_timebase = 0;
- int64_t l_reserved = 0;
+ FAPI_DBG("%s. Primary Bus Width: %d",
+ mss::c_str(i_target),
+ o_value);
- // Attribute variables used to set decoded vals
- int64_t l_FTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_MTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+///
+/// @brief Decodes bus width extension
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value bus width extension in bits
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 13;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
-
- // TODO - update ENUMS to take account to int64_t
- // Decoding Bits 1~0
- l_spd_buffer.extractToRight<FINE_TIMEBASE_START, FINE_TIMEBASE_LEN>(l_fine_timebase);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- l_fine_timebase < MAX_VALID_FTB_KEY,
+ // 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_fine_timebase,
- "Failed check for fine timebase") );
- // Decoding Bits 3~2
- l_spd_buffer.extractToRight<MED_TIMEBASE_START, MED_TIMEBASE_LEN>(l_medium_timebase);
+ l_raw_byte);
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- l_medium_timebase < MAX_VALID_MTB_KEY,
- BYTE_INDEX,
- l_medium_timebase,
- "Failed check for medium timebase") );
- // Decoding bits Bits 7~4
- l_spd_buffer.extractToRight<TIMEBASE_RESERV_START, TIMEBASE_RESERV_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for timebases reserved bits");
-
- // Retrive entire MCS level attribute
- FAPI_TRY( spd_fine_timebase(l_target_mcs, &l_FTBs[0][0]) );
- FAPI_TRY( spd_medium_timebase(l_target_mcs, &l_MTBs[0][0]) );
-
- // Update attribute to decoded byte values
- l_FTBs[PORT_NUM][DIMM_NUM] = fine_timebase_map[l_fine_timebase];
- l_MTBs[PORT_NUM][DIMM_NUM] = medium_timebase_map[l_medium_timebase];
-
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_SPD_FINE_TIMEBASE, l_target_mcs, l_FTBs );
- FAPI_ATTR_SET( fapi2::ATTR_SPD_MEDIUM_TIMEBASE, l_target_mcs, l_MTBs );
-
- // Printed decoded info
- FAPI_INF( "%s. Fine Timebase: %d, Medium Timebase: %d",
- c_str(i_target_dimm),
- l_FTBs[PORT_NUM][DIMM_NUM],
- l_MTBs[PORT_NUM][DIMM_NUM] );
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BUS_EXT_WIDTH_START, BUS_EXT_WIDTH_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BUS_WIDTH_EXT_MAP, l_field_bits, o_value),
+ 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 SDRAM Minimum Cycle Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode Module Thermal Sensor
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value thermal sensor value from SPD
/// @return fapi2::ReturnCode
-/// @note SPD Byte 18 & Byte 125
-/// This byte depends on the fine & medium timebase values
-/// obtained from Byte 17
+/// @note SPD Byte 14 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 28
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::min_cycle_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::thermal_sensor(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MTB = 18; // min cycle medium timebase (mtb)
- const size_t BYTE_INDEX_FTB = 125; // min cycle fine timebase (ftb)
- const int64_t MIN_CYCLE_TIME_MTB = 1; // from JEDEC
- const int64_t MAX_CYCLE_TIME_MTB = 255; // from JEDEC
+ constexpr size_t BYTE_INDEX = 14;
+ constexpr size_t INVALID_VALUE = 2; // single bit value 0 or 1
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- const int64_t MIN_CYCLE_TIME_FTB = -128; // from JEDEC
- const int64_t MAX_CYCLE_TIME_FTB = 127; // from JEDEC
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<THERM_SENSOR_START, THERM_SENSOR_LEN>(l_field_bits);
- // Byte variables used for decoding
- int64_t l_tCKmin_mtb = 0;
- int64_t l_tCKmin_ftb = 0;
+ 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") );
+ o_value = l_field_bits;
- // Attribute variables
- int64_t l_min_cycle_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_MTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_FTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_DBG("%s. Thermal Sensor: %d",
+ mss::c_str(i_target),
+ o_value);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_MTB,
- i_spd_data[BYTE_INDEX_MTB]);
-
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_FTB,
- i_spd_data[BYTE_INDEX_FTB]);
-
- // Retrieve SDRAM Maximum Cycle Time
- l_tCKmin_mtb = i_spd_data[BYTE_INDEX_MTB];
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tCKmin_mtb <= MAX_CYCLE_TIME_MTB) &&
- (l_tCKmin_mtb >= MIN_CYCLE_TIME_MTB),
- BYTE_INDEX_MTB,
- l_tCKmin_mtb,
- "Failed check for tCKmin (min cycle time) in MTB units") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Retrieve Fine Offset for SDRAM Minimum Cycle Time
- // casted int8_t undoes 2's complement on the uint8_t spd data
- l_tCKmin_ftb = int8_t(i_spd_data[BYTE_INDEX_FTB]);
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tCKmin_ftb <= MAX_CYCLE_TIME_FTB) &&
- (l_tCKmin_ftb >= MIN_CYCLE_TIME_FTB),
- BYTE_INDEX_FTB,
- l_tCKmin_ftb,
- "Failed check for tCKmin (min cycle time) in FTB units") );
-
-
- // Retrieving medium timebase (MTB) multiplier used for timing calculation
- FAPI_TRY( spd_medium_timebase(l_target_mcs, &l_MTBs[0][0]) );
- FAPI_TRY( spd_fine_timebase(l_target_mcs, &l_FTBs[0][0]) );
-
- // Retrive entire MCS level attribute
- FAPI_TRY( spd_timing_tckmin(l_target_mcs, &l_min_cycle_times[0][0]) );
-
- // Update attribute to decoded byte values
- // Calculating minimum cycle time in picosconds
- l_min_cycle_times[PORT_NUM][DIMM_NUM] = calc_timing(l_tCKmin_mtb,
- l_tCKmin_ftb,
- l_MTBs[PORT_NUM][DIMM_NUM],
- l_FTBs[PORT_NUM][DIMM_NUM]);
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_TIMING_TCKMIN, l_target_mcs, l_min_cycle_times );
-
- // Printed decoded info
- FAPI_INF("%s. tCKmin (min cycle time): %d (ps)",
- c_str(i_target_dimm),
- l_min_cycle_times[PORT_NUM][DIMM_NUM] );
+///
+/// @brief Decode Extended Base Module Type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value raw data from SPD
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+
+ constexpr size_t BYTE_INDEX = 15;
+ constexpr size_t RESERVED = 0;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+
+ // Buffer used for bit manipulation
+ 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
+ l_spd_buffer.extractToRight<EXT_MOD_TYPE_START, EXT_MOD_TYPE_LEN>(l_field_bits);
+
+ // Currently reserved to 0b000
+ 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") );
+ 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 SDRAM Maximum Cycle Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode Fine Timebase
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value fine_timebase from SPD in picoseconds
/// @return fapi2::ReturnCode
-/// @note SPD Byte 19 and 124
+/// @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::max_cycle_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_timebase(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MTB = 19; // min cycle medium timebase (mtb)
- const size_t BYTE_INDEX_FTB = 124; // min cycle fine timebase (ftb)
- const int64_t MIN_CYCLE_TIME_MTB = 1; // from JEDEC
- const int64_t MAX_CYCLE_TIME_MTB = 255; // from JEDEC
+ constexpr size_t BYTE_INDEX = 17;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- const int64_t MIN_CYCLE_TIME_FTB = -128; // from JEDEC
- const int64_t MAX_CYCLE_TIME_FTB = 127; // from JEDEC
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<FINE_TIMEBASE_START, FINE_TIMEBASE_LEN>(l_field_bits);
- // Byte variables used for decoding
- int64_t l_tCKmax_mtb = 0;
- int64_t l_tCKmax_ftb = 0;
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(FINE_TIMEBASE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Fine Timebase") );
- // Attribute variable
- int64_t l_max_cycle_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_MTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_FTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_DBG("%s. Fine Timebase: %d",
+ mss::c_str(i_target),
+ o_value);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_MTB,
- i_spd_data[BYTE_INDEX_MTB]);
-
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_FTB,
- i_spd_data[BYTE_INDEX_FTB]);
-
- // Retrieve SDRAM Maximum Cycle Time
- l_tCKmax_mtb = i_spd_data[BYTE_INDEX_MTB];
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tCKmax_mtb <= MAX_CYCLE_TIME_MTB) &&
- (l_tCKmax_mtb >= MIN_CYCLE_TIME_MTB),
- BYTE_INDEX_MTB,
- l_tCKmax_mtb,
- "Failed check for tCKmin (min cycle time) in MTB units") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Retrieve Fine Offset for SDRAM Maximum Cycle Time
- // casted int8_t undoes 2's complement on the uint8_t spd data
- l_tCKmax_ftb = int8_t(i_spd_data[BYTE_INDEX_FTB]);
+///
+/// @brief Decode Medium Timebase
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value medium timebase from SPD in picoseconds
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
+{
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tCKmax_ftb <= MAX_CYCLE_TIME_FTB) &&
- (l_tCKmax_ftb >= MIN_CYCLE_TIME_FTB),
- BYTE_INDEX_FTB,
- l_tCKmax_ftb,
- "Failed check for tCKmin (min cycle time) in FTB units") );
+ constexpr size_t BYTE_INDEX = 17;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Retrieving medium timebase (MTB) multiplier used for timing calculation
- FAPI_TRY( spd_medium_timebase(l_target_mcs, &l_MTBs[0][0]) );
- FAPI_TRY( spd_fine_timebase(l_target_mcs, &l_FTBs[0][0]) );
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Retrive entire MCS level attribute
- FAPI_TRY(spd_timing_tckmax(l_target_mcs, &l_max_cycle_times[0][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,
+ l_raw_byte);
- // Update attribute to decoded byte values
- l_max_cycle_times[PORT_NUM][DIMM_NUM] = calc_timing(l_tCKmax_mtb,
- l_tCKmax_ftb,
- l_MTBs[PORT_NUM][DIMM_NUM],
- l_FTBs[PORT_NUM][DIMM_NUM]);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<MED_TIMEBASE_START, MED_TIMEBASE_LEN>(l_field_bits);
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_TIMING_TCKMAX, l_target_mcs, l_max_cycle_times );
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(MEDIUM_TIMEBASE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Medium Timebase") );
- // Printed decoded info
- FAPI_INF("%s. tCKmax (max cycle time): %d (ps)",
- c_str(i_target_dimm),
- l_max_cycle_times[PORT_NUM][DIMM_NUM] );
+ FAPI_DBG("%s. Medium Timebase: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
+
///
-/// @brief Decode Minimum CAS Latency Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Cycle Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCKmin in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte 24 & 123
+/// @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_cas_latency_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_cycle_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MTB = 24; // min cycle medium timebase (mtb)
- const size_t BYTE_INDEX_FTB = 123; // min cycle fine timebase (ftb)
+ constexpr size_t BYTE_INDEX = 18;
- const int64_t MIN_CYCLE_TIME_MTB = 1; // from JEDEC
- const int64_t MAX_CYCLE_TIME_MTB = 255; // from JEDEC
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- const int64_t MIN_CYCLE_TIME_FTB = -128; // from JEDEC
- const int64_t MAX_CYCLE_TIME_FTB = 127; // from JEDEC
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ 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") );
- // Byte variables used for decoding
- int64_t l_tAAmin_mtb = 0;
- int64_t l_tAAmin_ftb = 0;
+ FAPI_DBG("%s. Minimum Cycle Time (tCKmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Attribute variable
- int64_t l_min_cas_latency_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_MTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_FTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_MTB,
- i_spd_data[BYTE_INDEX_MTB]);
-
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_FTB,
- i_spd_data[BYTE_INDEX_FTB]);
-
- // Retrieve SDRAM Minimum CAS Latency Time
- l_tAAmin_mtb = i_spd_data[BYTE_INDEX_MTB];
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tAAmin_mtb <= MAX_CYCLE_TIME_MTB) &&
- (l_tAAmin_mtb >= MIN_CYCLE_TIME_MTB),
- BYTE_INDEX_MTB,
- l_tAAmin_mtb,
- "Failed check for min CAS latency time (tAAmin) in MTB units") );
-
- // Retrieve Fine Offset for Minimum CAS Latency Time
- // casted int8_t undoes 2's complement on the uint8_t spd data
- l_tAAmin_ftb = int8_t(i_spd_data[BYTE_INDEX_FTB]);
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tAAmin_ftb <= MAX_CYCLE_TIME_FTB) &&
- (l_tAAmin_ftb >= MIN_CYCLE_TIME_FTB),
- BYTE_INDEX_FTB,
- l_tAAmin_ftb,
- "Failed check for min CAS latency time (tAAmin) in FTB units") );
-
- // Retrieving medium timebase (MTB) multiplier used for timing calculation
- FAPI_TRY( spd_medium_timebase(l_target_mcs, &l_MTBs[0][0]) );
- FAPI_TRY( spd_fine_timebase(l_target_mcs, &l_FTBs[0][0]) );
-
- // Retrive entire MCS level attribute
- FAPI_TRY(spd_timing_taamin(l_target_mcs, &l_min_cas_latency_times[0][0]))
-
- // Update attribute to decoded byte values
- l_min_cas_latency_times[PORT_NUM][DIMM_NUM] = calc_timing(l_tAAmin_mtb,
- l_tAAmin_ftb,
- l_MTBs[PORT_NUM][DIMM_NUM],
- l_FTBs[PORT_NUM][DIMM_NUM]);
-
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_TIMING_TAAMIN, l_target_mcs, l_min_cas_latency_times );
-
- // Printed decoded info
- FAPI_INF("%s. tAAmin (min cycle time): %d (ps)",
- c_str(i_target_dimm),
- l_min_cas_latency_times[PORT_NUM][DIMM_NUM] );
+///
+/// @brief Decodes SDRAM Maximum Cycle Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCKmax in MTB units
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 19;
+
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_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);
+
+ 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") );
+
+ 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;
}
-#if 0
///
/// @brief Decode CAS Latencies Supported
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value bitmap of supported CAS latencies
/// @return fapi2::ReturnCode
-/// @note SPD Byte 20-23
+/// @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_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::supported_cas_latencies(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint64_t& o_value)
{
- // Immutable constants
- const size_t FIRST_BYTE = 20;
- const size_t SEC_BYTE = 21;
- const size_t THIRD_BYTE = 22;
- const size_t FORTH_BYTE = 23;
+ constexpr size_t FIRST_BYTE = 20;
+ constexpr size_t SEC_BYTE = 21;
+ constexpr size_t THIRD_BYTE = 22;
+ constexpr size_t FOURTH_BYTE = 23;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Buffers used for bit manipulation
+ fapi2::buffer<uint64_t> l_buffer;
- // Byte variables used for decoding
- uint64_t l_supported_cas_lat = 0;
+ // Trace print in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ c_str(i_target),
+ FIRST_BYTE,
+ i_spd_data[FIRST_BYTE]);
+
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ c_str(i_target),
+ SEC_BYTE,
+ i_spd_data[SEC_BYTE]);
+
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ c_str(i_target),
+ THIRD_BYTE,
+ i_spd_data[THIRD_BYTE])
+
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ c_str(i_target),
+ FOURTH_BYTE,
+ i_spd_data[FOURTH_BYTE]);
+
+ // Combine Bytes to create bitmap - right aligned
+ l_buffer.insertFromRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(i_spd_data[FIRST_BYTE]).
+ insertFromRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(i_spd_data[SEC_BYTE]).
+ insertFromRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(i_spd_data[THIRD_BYTE]).
+ insertFromRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(i_spd_data[FOURTH_BYTE]);
+
+ // According to the JEDEC spec:
+ // Byte 23 bit 6 is reserved and must be coded as 0.
+ // 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;
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ !(l_buffer.getBit<BIT_START, BIT_LEN>()),
+ FOURTH_BYTE,
+ i_spd_data[FOURTH_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);
- // Attribute variables used to set decoded vals
- uint64_t l_supported_CLs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+fapi_try_exit:
+ return fapi2::current_err;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_first_byte_buff(i_spd_data[FIRST_BYTE]);
- fapi2::buffer<uint8_t> l_second_byte_buff(i_spd_data[SEC_BYTE]);
- fapi2::buffer<uint8_t> l_third_byte_buff(i_spd_data[THIRD_BYTE]);
- fapi2::buffer<uint8_t> l_forth_byte_buff(i_spd_data[FORTH_BYTE]);
+}
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+///
+/// @brief Decodes SDRAM Minimum CAS Latency Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tAAmin in MTB units
+/// @return fapi2::ReturnCode
+/// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 24;
- // TODO - update ENUMS to take account to int64_t
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Combine Bytes 20 - 23 to create bitmap
- l_first_byte_buff.extractToRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(l_supported_cas_lat).
- l_second_byte_buff.extractToRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(l_supported_cas_lat).
- l_third_byte_buff.extractToRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(l_supported_cas_lat).
- l_forth_byte_buff.extractToRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(l_supported_cas_lat);
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( cas_latencies_supported(l_target_mcs, &l_supported_CLs[0][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,
+ l_timing_val);
- // Update attribute to decoded byte values
- l_supported_CLs[PORT_NUM][DIMM_NUM] = l_supported_cas_lat;
+ 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") );
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_SPD_CAS_LATENCIES_SUPPORTED, l_target_mcs, l_supported_CLs );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
-}
+ // 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 Decode Minimum RAS to CAS Delay Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRCDmin in MTB units
/// @return fapi2::ReturnCode
/// @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<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_ras_to_cas_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 25;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 25;
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Attribute variable (rcd = ras to cas delay)
- int64_t l_min_rcd_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
+ l_timing_val);
+
+ 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") );
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trcd(l_target_mcs, &l_min_rcd_times[0][0]) );
+ // Only update output if it passes check
+ o_value = l_timing_val;
- // Update attribute to decoded byte values
- l_min_rcd_times[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ FAPI_DBG("%s. Minimum RAS to CAS Delay Time (tRCDmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRCD, l_target_mcs, l_min_rcd_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Decode Minimum Row Precharge Delay Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRPmin in MTB units
/// @return fapi2::ReturnCode
/// @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<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_row_precharge_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 26;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 26;
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Attribute variable (rp = row to precharge)
- int64_t l_min_rp_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
+ l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trp(l_target_mcs, &l_min_rp_times[0][0]) );
+ 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") );
- // Update attribute to decoded byte values
- l_min_rp_times[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Only update output if it passes check
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRP, l_target_mcs, l_min_rp_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ 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 Decode Minimum Active to Precharge Delay Time (tRASmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRASmin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 27 Bits 3~0 along with Byte 28 Bits 7~0
+/// @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_activate_to_precharge_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_active_to_precharge_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 27; // MSN = most significant byte
- const size_t BYTE_INDEX_LSB = 28; // LSB = least significant byte
+ // Lambda expression to retrieve tRASmin's most significant nibble (MSN)
+ auto tRASmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 27;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (tRAS = Active to Precharge Delay Time)
- int64_t l_tRASmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRASMIN_MSN_START, TRASMIN_MSN_LEN>(l_out);
- // Attribute variable
- int64_t l_min_ras_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSB]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // Lambda expression to retrieve tRASmin's least significant byte (LSB)
+ auto tRASmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 28;
+ uint8_t l_out = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- 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,
+ i_data[BYTE_INDEX]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TRASMIN_LSB_START, TRASMIN_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // 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;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRASmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRASmin_LSB(i_target, i_spd_data) );
- // TODO - update ENUMS to take account to int64_t
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Combining bits to create timing value
- l_buffer_upper_nibble.extractToRight<TRASMIN_MSN_START, TRASMIN_MSN_LEN>(l_tRASmin);
- l_buffer_lower_byte.extractToRight<TRASMIN_LSB_START, TRASMIN_LSB_LEN>(l_tRASmin);
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_tras(l_target_mcs, &l_min_ras_times[0][0]) );
+ // 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
- // Update attribute to decoded byte values (returning picoseconds)
- l_min_ras_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRASmin);
+ // 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;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRAS, l_target_mcs, l_min_ras_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ 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 Minimum Active to Active/Refresh Delay Time (tRCmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRCmin in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte Byte 27 Bits 7~4 along with Byte 29 Bits 7~0
+/// @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_activate_to_activate_refresh_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_active_to_active_refresh_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 27; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 28; // LSB = least significant byte
+ // Lambda expression to retrieve tRCmin's most significant nibble (MSN)
+ auto tRCmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 27;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (RC = Activate to Activate/Refresh Delay)
- uint16_t l_tRCmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRCMIN_MSN_START, TRCMIN_MSN_LEN>(l_out);
- // Attribute variable
- uint16_t l_min_rc_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tRCmin's least significant byte (LSB)
+ auto tRCmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 29;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // 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]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Combining bits to create timing value
- l_buffer_upper_nibble.extractToRight<TRCMIN_MSN_START, TRCMIN_MSN_LEN>(l_tRCmin);
- l_buffer_lower_byte.extractToRight<TRCMIN_LSB_START, TRCMIN_LSB_LEN>(l_tRCmin);
+ // Extracting desired bits
+ l_buffer.extractToRight<TRCMIN_LSB_START, TRCMIN_LSB_LEN>(l_out);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_rc_times[0][0]) );
+ return l_out;
+ };
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_rc_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRCmin);
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRC, l_target_mcs, l_min_rc_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // 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;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRCmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRCmin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
+
+ 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 Minimum Refresh Recovery Delay Time 1 (tRFC1min)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRFC1min in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte Byte 30 (LSB) along with Byte 31 (MSB)
+/// @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_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_1(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 31; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 30; // LSB = least significant byte
+ // Lambda expression to retrieve tRFC1min's most significant byte (MSB)
+ auto tRFC1min_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 31;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (RFC1 = Minimum Refresh Recovery Delay Time)
- uint32_t l_tRFC1min = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC1MIN_MSB_START, TRFC1MIN_MSB_LEN>(l_out);
- // Attribute variable
- uint32_t l_min_rfc1_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_MSB(i_spd_data[BYTE_INDEX_MSB]);
- fapi2::buffer<uint8_t> l_buffer_LSB(i_spd_data[BYTE_INDEX_LSB]);
+ // Lambda expression to retrieve tRFC1min's least significant byte (LSB)
+ auto tRFC1min_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 30;
+ uint8_t l_out = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- 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,
+ i_data[BYTE_INDEX]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC1MIN_LSB_START, TRFC1MIN_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // 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;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC1min_MSB(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRFC1min_LSB(i_target, i_spd_data) );
- // Combining bits to create timing value
- l_buffer_MSB.extractToRight<, >();
- l_buffer_LSB.extractToRight<, >();
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_rfc1_times[0][0]) );
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_rfc1_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRFC1min);
+ // 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
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRFC1, l_target_mcs, l_min_rfc1_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // 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 Minimum Refresh Recovery Delay Time 2 (tRFC2min)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRFC2min in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte Byte 32 (LSB) along with Byte 33 (MSB)
+/// @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_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_2(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 33; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 32; // LSB = least significant byte
+ // Lambda expression to retrieve tRFC2min's most significant byte (MSB)
+ auto tRFC2min_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 33;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (RFC1 = Minimum Refresh Recovery Delay 2)
- uint32_t l_tRFC2min = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC2MIN_MSB_START, TRFC2MIN_MSB_LEN>(l_out);
- // Attribute variable
- uint32_t l_min_rfc2_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_MSB(i_spd_data[BYTE_INDEX_MSB]);
- fapi2::buffer<uint8_t> l_buffer_LSB(i_spd_data[BYTE_INDEX_LSB]);
+ // Lambda expression to retrieve tRFC2min's least significant byte (LSB)
+ auto tRFC2min_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 32;
+ uint8_t l_out = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- 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,
+ i_data[BYTE_INDEX]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC2MIN_LSB_START, TRFC2MIN_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // 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;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC2min_MSB(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRFC2min_LSB(i_target, i_spd_data) );
- // Combining bits to create timing value
- l_buffer_MSB.extractToRight<, >();
- l_buffer_LSB.extractToRight<, >();
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_rfc2_times[0][0]) );
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_rfc1_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRFC2min);
+ // 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
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRFC2, l_target_mcs, l_min_rfc2_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // 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 Minimum Refresh Recovery Delay Time 4 (tRFC4min)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRFC4min in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte Byte 34 (LSB) along with Byte 5 (MSB)
+/// @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_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_4(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 35; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 34; // LSB = least significant byte
+ // Lambda expression to retrieve tRFC4min's most significant byte (MSB)
+ auto tRFC4min_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 35;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (RFC4 = Minimum Refresh Recovery Delay 4)
- uint32_t l_tRFC4min = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC4MIN_MSB_START, TRFC4MIN_MSB_LEN>(l_out);
- // Attribute variable
- uint32_t l_min_rfc4_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_MSB(i_spd_data[BYTE_INDEX_MSB]);
- fapi2::buffer<uint8_t> l_buffer_LSB(i_spd_data[BYTE_INDEX_LSB]);
+ // Lambda expression to retrieve tRFC4min's least significant byte (LSB)
+ auto tRFC4min_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 34;
+ uint8_t l_out = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- 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,
+ i_data[BYTE_INDEX]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC4MIN_LSB_START, TRFC4MIN_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // 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;
- // Combining bits to create timing value
- l_buffer_MSB.extractToRight<, >();
- l_buffer_LSB.extractToRight<, >();
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC4min_MSB(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRFC4min_LSB(i_target, i_spd_data) );
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_rfc4_times[0][0]) );
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_rfc1_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRFC4min);
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRFC2, l_target_mcs, l_min_rfc4_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // 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 Minimum Four Activate Window Delay Time (t FAW min)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Four Activate Window Delay Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tFAWmin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 36 Bits 3 ~ 0 along with Byte 37 Bits 7 ~ 0
+/// @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_four_activate_window_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_tfaw(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 36; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 37; // LSB = least significant byte
+ // Lambda expression to retrieve tFAWmin's most significant nibble (MSN)
+ auto tFAWmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 36;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (FAW = Four Activate Window Delay)
- uint16_t l_tFAW = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TFAWMIN_MSN_START, TFAWMIN_MSN_LEN>(l_out);
- // Attribute variable
- uint16_t l_min_faw_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tFAWmin's least significant byte (LSB)
+ auto tFAWmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 37;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // 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]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Combining bits to create timing value
- l_buffer_upper_nibble.extractToRight<TRCMIN_MSN_START, TRCMIN_MSN_LEN>(l_tFAW);
- l_buffer_lower_byte.extractToRight<TRCMIN_LSB_START, TRCMIN_LSB_LEN>(l_tFAW);
+ // Extracting desired bits
+ l_buffer.extractToRight<TFAWMIN_LSB_START, TFAWMIN_LSB_LEN>(l_out);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_faw_times[0][0]) );
+ return l_out;
+ };
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_faw_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tFAW);
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRC, l_target_mcs, l_min_faw_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // 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;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tFAWmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tFAWmin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
+
+ 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 Minimum Activate to Activate Delay Time (tRRD_Smin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRRD_Smin MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 38
+/// @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_act_to_act_delay_time_diff_bank_group(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_trrd_s(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 38;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 38;
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
- // Attribute variable (rrd_s = Activate to Activate Delay)
- int64_t l_min_tRRD_S[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Retrieve Minimum Activate to Activate Delay Time - Different Bank Group
+ // explicit conversion to int64_t
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
+ l_timing_val);
+
+ 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") );
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_tRRD_S[0][0]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update attribute to decoded byte values
- l_min_tRRD_S[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ 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);
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRRD_S, l_target_mcs, l_min_tRRD_S );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum Activate to Activate Delay Time (tRRD_Lmin), samebank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRRD_Lmin MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 39
+/// @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_act_to_act_delay_time_same_bank_group(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_trrd_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 39;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 39;
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
- // Attribute variable (rrd_s = Activate to Activate Delay)
- int64_t l_min_tRRD_S[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Retrieve Minimum Activate to Activate Delay Time - Same Bank Group
+ // explicit conversion to int64_t
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
+ l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_tRRD_S[0][0]) );
+ 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 attribute to decoded byte values
- l_min_tRRD_S[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRRD_L, l_target_mcs, l_min_tRRD_S );
+ 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);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum CAS to CAS Delay Time (tCCD_Lmin), same bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCCD_Lmin MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 40
+/// @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_cas_to_cas_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_tccd_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 40;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 40;
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Retrieve Minimum CAS to CAS Delay Time - Same Bank Group
+ // explicit conversion to int64_t
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
+ l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_tCCD_L[0][0]) );
+ 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 attribute to decoded byte values
- l_min_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TCCD_L, l_target_mcs, l_min_tCCD_L );
+ 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);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum Write Recovery Time (tWRmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Write Recovery Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tWRmin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 41 Bits 3~0, Byte 42 Bits 7~0
+/// @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_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_write_recovery_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 41; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 42; // LSB = least significant byte
+ // Lambda expression to retrieve tWRmin's most nibble byte (MSN)
+ auto tWRmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 41;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (FAW = Four Activate Window Delay)
- uint16_t l_tWRmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TWRMIN_MSN_START, TWRMIN_MSN_LEN>(l_out);
- // Attribute variable
- int64_t l_min_wr_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tWRmin's least significant byte (LSB)
+ auto tWRmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 42;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // 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]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Combining bits to create timing value
- l_buffer_upper_nibble.insert<, >(l_tWRmin);
- l_buffer_lower_byte.insert<, >(l_tWRmin);
+ // Extracting desired bits
+ l_buffer.extractToRight<TWRMIN_LSB_START, TWRMIN_LSB_LEN>(l_out);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_twr(l_target_mcs, &l_min_wr_times[0][0]) );
+ return l_out;
+ };
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_wr_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tWRmin);
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TWR, l_target_mcs, l_min_wr_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // 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;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tWRmin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
+
+ 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 Minimum Write to Read Time (tWTR_Smin), different bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Write to Read Time - Different Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tWRT_Smin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 43 Bits 3~0, Byte 44 Bits 7~0
+/// @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_write_to_read_time_diff_bank_group(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_twtr_s(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 43; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 44; // LSB = least significant byte
+ // Lambda expression to retrieve tWRT_Smin's most nibble byte (MSN)
+ auto tWRT_Smin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 43;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (WRT = Write to Read Time)
- int64_t l_tWRTmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TWTRMIN_S_MSN_START, TWTRMIN_S_MSN_LEN>(l_out);
- // Attribute variable
- int64_t l_min_wrt_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tWRT_Smin's least significant byte (LSB)
+ auto tWRT_Smin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 44;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // 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]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TWTRMIN_S_LSB_START, TWTRMIN_S_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // 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;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRT_Smin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tWRT_Smin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Combining bits to create timing value
- l_buffer_upper_nibble.insert<, >(l_tWRTmin);
- l_buffer_lower_byte.insert<, >(l_tWRTmin);
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_twrt(l_target_mcs, &l_min_wrt_times[0][0]) );
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_wrt_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tWRTmin);
+ // JEDEC spec limits for this timing value
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TWRT, l_target_mcs, l_min_wrt_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // 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 Minimum Write to Read Time (tWTR_Lmin), same bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Write to Read Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tWRT_Lmin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 43 Bits 7~4, Byte 45 Bits 7~0
+/// @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_write_to_read_time_same_bank_group(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_twtr_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 43; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 45; // LSB = least significant byte
+ // Lambda expression to retrieve tWRT_Lmin's most nibble byte (MSN)
+ auto tWRT_Lmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 43;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (WRT = Write to Read Time)
- int64_t l_tWRTmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TWTRMIN_L_MSN_START, TWTRMIN_L_MSN_LEN>(l_out);
- // Attribute variable
- int64_t l_min_wrt_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tWRT_Lmin's least significant byte (LSB)
+ auto tWRT_Lmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 45;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // 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]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Combining bits to create timing value
- l_buffer_upper_nibble.insert<, >(l_tWRTmin);
- l_buffer_lower_byte.insert<, >(l_tWRTmin);
+ // Extracting desired bits
+ l_buffer.extractToRight<TWTRMIN_L_LSB_START, TWTRMIN_L_LSB_LEN>(l_out);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_twrt(l_target_mcs, &l_min_wrt_times[0][0]) );
+ return l_out;
+ };
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_wrt_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tWRTmin);
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TWRT, l_target_mcs, l_min_wrt_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
-}
+ // 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;
-///
-/// @brief Connector to SDRAM Bit Mapping
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// @return fapi2::ReturnCode
-/// @note Bytes 60~77
-///
-fapi2::ReturnCode decoder::connector_to_sdram_bit_mapping(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
-{
-// Retrive entire MCS level attribute
-// Update attribute to decoded byte values
-// Update MCS level attribute
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRT_Lmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tWRT_Lmin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
+
+ 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 Fine Offset for Minimum CAS to CAS Delay Time (tCCD_Lmin), same bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCCD_Lmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 117
+/// @note SPD Byte 117
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_min_cas_to_cas_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_tccd_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 117;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ constexpr size_t BYTE_INDEX = 117;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // 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(i_spd_data[BYTE_INDEX]);
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ 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 MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
-}
+ // Update output value only if range check passes
+ o_value = l_timing_val;
-// Retrive entire MCS level attribute
-// Update attribute to decoded byte values
-// Update MCS level attribute
+ 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;
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for Minimum Activate to Activate Delay Time(tRRD_Lmin), same bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRRD_Lmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 118
+/// @note SPD Byte 118
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode
-decoder::offset_min_act_to_act_delay_time_diff_bank_gp(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trrd_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 118;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 118;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // 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(i_spd_data[BYTE_INDEX]);
+
+ 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 attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ 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 Fine Offset for Minimum Activate to Activate Delay Time (tRRD_Smin), different bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRRD_Smin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 119
+/// @note SPD Byte 119
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode
-decoder::offset_min_act_to_act_delay_time_same_bank_gp(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trrd_s(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 119;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 119;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // 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(i_spd_data[BYTE_INDEX]);
+
+ 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 attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ 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 Fine Offset for Minimum Active to Active/Refresh Delay Time (tRCmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRCmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 120
+/// @note SPD Byte 120
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode
-decoder::offset_for_min_act_to_act_refresh_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trc(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 120;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 120;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // 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(i_spd_data[BYTE_INDEX]);
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ 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 MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // Update output value only if range check passes
+ o_value = l_timing_val;
-// Retrive entire MCS level attribute
-// Update attribute to decoded byte values
-// Update MCS level attribute
+ 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;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for Minimum Row Precharge Delay Time (tRPmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRPmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 121
+/// @note SPD Byte 121
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode
-decoder::offset_for_min_row_precharge_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trp(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 121;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 121;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // 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(i_spd_data[BYTE_INDEX]);
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ 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 MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
-
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
-}
+ // 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 Fine Offset for Minimum RAS to CAS Delay Time (tRCDmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRCDmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 122
+/// @note SPD Byte 122
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_min_ras_to_cas_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trcd(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 122;
+ constexpr size_t BYTE_INDEX = 122;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // 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(i_spd_data[BYTE_INDEX]);
+
+ 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 attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
+ FAPI_DBG("%s. Fine offset for Minimum RAS to CAS Delay Time (tRCDmin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for Minimum CAS Latency Time (tAAmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tAAmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 123
+/// @note SPD Byte 123
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_min_cas_latency_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_taa(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 123;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 125;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // 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(i_spd_data[BYTE_INDEX]);
+
+ 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 attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
+ FAPI_DBG("%s. Fine offset for Minimum CAS Latency Time (tAAmin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for SDRAM Maximum Cycle Time (tCKAVGmax)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCKmax offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 124
+/// @note SPD Byte 124
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_max_cycle_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_max_tck(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 124;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 124;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // 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(i_spd_data[BYTE_INDEX]);
+
+ 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 attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
+ FAPI_DBG("%s. Fine offset for Maximum Cycle Time (tCKmax) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Fine Offset for SDRAM Minimum Cycle Time (tCKAVGmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCKmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 125
+/// @note SPD Byte 125
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_min_cycle_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_tck(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 125;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 125;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // 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_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // 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(i_spd_data[BYTE_INDEX]);
+
+ 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 attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
+ 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;
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Cyclical Redundancy Code (CRC) for Base Configuration Section
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value crc value from SPD
/// @return fapi2::ReturnCode
-/// @note Byte 126 (LSB) along with Byte 127 (MSB)
+/// @note SPD Byte 127 & Byte 126
+/// @note Item JC-45-2220.01x
+/// @note Page 53
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::crc_for_base_config_section(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::cyclical_redundancy_code(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint16_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 127; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 126; // LSB = least significant byte
+ // Lambda expression to retrieve crc's most significant byte (MSB)
+ auto crc_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 127;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // 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]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (WRT = Write to Read Time)
- int64_t l_tWRTmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<CRC_MSB_START, CRC_MSB_LEN>(l_out);
- // Attribute variable
- int64_t l_min_wrt_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve crc's least significant byte (LSB)
+ auto crc_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 126;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // 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]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_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;
- // Combining bits to create timing value
- l_buffer_upper_nibble.insert<, >(l_tWRTmin);
- l_buffer_lower_byte.insert<, >(l_tWRTmin);
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( crc_MSB(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( crc_LSB(i_target, i_spd_data) );
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_twrt(l_target_mcs, &l_min_wrt_times[0][0]) );
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 16;
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_wrt_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tWRTmin);
+ // This value isn't bounded in the SPD document
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(o_value);
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TWRT, l_target_mcs, l_min_wrt_times );
+ FAPI_DBG("%s. Cyclical Redundancy Code (CRC): %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // Returns "happy" until we can figure out a way to test this - AAM
+ return fapi2::FAPI2_RC_SUCCESS;
}
-#endif
}//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
index c86dc8816..390850032 100644
--- 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
@@ -7,7 +7,7 @@
/* */
/* EKB Project */
/* */
-/* COPYRIGHT 2015 */
+/* COPYRIGHT 2015,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -38,8 +38,9 @@ namespace mss
namespace spd
{
+using fapi2::TARGET_TYPE_DIMM;
-enum constants : uint64_t
+enum BYTE_EXTRACT : uint64_t
{
// Byte 0
BYTES_USED_START = 4,
@@ -51,7 +52,14 @@ enum constants : uint64_t
BYTES_RESERVED_START = 0,
BYTES_RESERVED_LEN = 1,
- // Byte 1 & 2 not used now
+ // 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,
@@ -84,8 +92,8 @@ enum constants : uint64_t
ADDRESS_RESERVED_LEN = 2,
// Byte 6
- PRIM_PRIM_SIGNAL_LOAD_START = 5,
- PRIM_PRIM_SIGNAL_LOAD_LEN = 2,
+ PRIM_SIGNAL_LOAD_START = 5,
+ PRIM_SIGNAL_LOAD_LEN = 2,
PACKAGE_RESERVE_START = 4,
PACKAGE_RESERVE_LEN = 2,
@@ -155,8 +163,8 @@ enum constants : uint64_t
MODULE_ORG_RESERVED_LEN = 1,
// Byte 13
- BUS_WIDTH_START = 6,
- BUS_WIDTH_LEN = 2,
+ BUS_WIDTH_START = 5,
+ BUS_WIDTH_LEN = 3,
BUS_EXT_WIDTH_START = 3,
BUS_EXT_WIDTH_LEN = 2,
@@ -190,233 +198,1093 @@ enum constants : uint64_t
TIMEBASE_RESERV_START = 0,
TIMEBASE_RESERV_LEN = 4,
- // Byte 18 - bits not decoded
- // Byte 19 - bits not decoded
+ // Byte 18 - Entire byte used
+ // Byte 19 - Entire byte used
// Byte 20-23
- CAS_BYTE_1_START = 55,
+ CAS_BYTE_1_START = 56,
CAS_BYTE_1_LEN = 8,
- CAS_BYTE_2_START = 47,
+ CAS_BYTE_2_START = 48,
CAS_BYTE_2_LEN = 8,
- CAS_BYTE_3_START = 39,
+ CAS_BYTE_3_START = 40,
CAS_BYTE_3_LEN = 8,
- CAS_BYTE_4_START = 31,
+ CAS_BYTE_4_START = 32,
CAS_BYTE_4_LEN = 8,
- // Byte 24 - bits not decoded
- // Byte 25 - bits not decoded
- // Byte 26 - bits not decoded
+ // Byte 24 - Entire byte used
+ // Byte 25 - Entire byte used
+ // Byte 26 - Entire byte used
// Byte 27
- TRCMIN_MSN_START = 0, // MSN = most significant nibble
- TRCMIN_MSN_LEN = 4,
-
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 = 4, // LSB = least significant byte
+ TRASMIN_LSB_START = 0, // LSB = least significant byte
TRASMIN_LSB_LEN = 8,
// Byte 29
- TRCMIN_LSB_START = 4, // LSB = least significant byte
+ TRCMIN_LSB_START = 0, // LSB = least significant byte
TRCMIN_LSB_LEN = 8,
// Byte 30
- // TRFC1MIN_LSB_START
- // TRFC1MIN_LSB_LEN
+ TRFC1MIN_LSB_START = 0,
+ TRFC1MIN_LSB_LEN = 8,
// Byte 31
-// TRFC1MIN_MSB_START
-// TRFC1MIN_MSB_LEN
-
- // Bytes 46 - 59 - reserved
-
- // Bytes 60 - 77 - Connector to SDRAM Bit Mapping ??
-
- // Bytes 78 - 116 - reserved
-
- // Bytes 117 - 125 : bits not decoded
-
- // 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 ??
-};
-
-
-class decoder
-{
-
- public:
- // Constructor
- decoder() = default;
- // Deconstructor
- virtual ~decoder() = default;
-
- // Methods
- virtual fapi2::ReturnCode number_of_bytes(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data,
- const size_t i_read_spd_size);
-
- virtual fapi2::ReturnCode revision(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode dram_device_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode module_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode sdram_density(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode sdram_addressing(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode primary_package_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode sdram_optional_features(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode thermal_and_refresh_options(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode other_optional_features(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode secondary_package_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode module_nominal_voltage(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ TRFC1MIN_MSB_START = 0,
+ TRFC1MIN_MSB_LEN = 8,
- virtual fapi2::ReturnCode module_organization(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 32
+ TRFC2MIN_LSB_START = 0,
+ TRFC2MIN_LSB_LEN = 8,
- virtual fapi2::ReturnCode module_memory_bus_width(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 33
+ TRFC2MIN_MSB_START = 0,
+ TRFC2MIN_MSB_LEN = 8,
- virtual fapi2::ReturnCode module_thermal_sensor(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 34 & Byte 35
+ TRFC4MIN_LSB_START = 0,
+ TRFC4MIN_LSB_LEN = 8,
- virtual fapi2::ReturnCode extended_module_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ TRFC4MIN_MSB_START = 0,
+ TRFC4MIN_MSB_LEN = 8,
- virtual fapi2::ReturnCode timebases(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 36
+ TFAWMIN_MSN_START = 4,
+ TFAWMIN_MSN_LEN = 4,
- virtual fapi2::ReturnCode min_cycle_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 37
+ TFAWMIN_LSB_START = 0,
+ TFAWMIN_LSB_LEN = 8,
- virtual fapi2::ReturnCode max_cycle_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 38 - Entire byte used
+ // Byte 39 - Entire byte used
+ // Byte 40 - Entire byte used
- virtual fapi2::ReturnCode min_cas_latency_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 41
+ TWRMIN_MSN_START = 4, // MSN = most significant nibble
+ TWRMIN_MSN_LEN = 4,
- // Note: Yet to be implemented methods
-#if 0
+ // Byte 42
+ TWRMIN_LSB_START = 0, // LSB = least significant nibble
+ TWRMIN_LSB_LEN = 8,
- virtual fapi2::ReturnCode supported_cas_latencies(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // 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,
- virtual fapi2::ReturnCode min_ras_to_cas_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 44
+ TWTRMIN_S_LSB_START = 0, // LSB = least significant byte
+ TWTRMIN_S_LSB_LEN = 8,
- virtual fapi2::ReturnCode min_row_precharge_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 45
+ TWTRMIN_L_LSB_START = 0,
+ TWTRMIN_L_LSB_LEN = 8,
- virtual fapi2::ReturnCode upper_nibble_tRAS_tRC(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode min_activate_to_activate_refresh_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode min_activate_to_precharge_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode min_refresh_recovery_delay_time_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode min_refresh_recovery_delay_time_2(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-
- virtual fapi2::ReturnCode min_refresh_recovery_delay_time_4(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Bytes 46 - 59 - reserved
- virtual fapi2::ReturnCode min_four_activate_window_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Bytes 60 - 77 - Connector to SDRAM Bit Mapping ??
- virtual fapi2::ReturnCode min_act_to_act_delay_time_diff_bank_group(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
+ // Bytes 78 - 116 - reserved
- virtual fapi2::ReturnCode min_act_to_act_delay_time_same_bank_group(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
+ // Bytes 117 - 125 : Entire byte used
- virtual fapi2::ReturnCode min_cas_to_cas_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 126
+ CRC_MSB_START = 0,
+ CRC_MSB_LEN = 8,
- virtual fapi2::ReturnCode min_write_recovery_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Byte 127
+ CRC_LSB_START = 0,
+ CRC_LSB_LEN = 8,
- virtual fapi2::ReturnCode min_write_to_read_time_diff_bank_group(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
+ // Bytes 128 ~ 191 Module-Specific Section ??
- virtual fapi2::ReturnCode min_write_recovery_time_same_bank_group(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
+ // Bytes 192 ~ 255 Hybrid Memory Architecture Specific Parameters ??
- virtual fapi2::ReturnCode connector_to_sdram_bit_mapping(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Bytes 256 ~ 319 Extended Function Parameter Block ??
- virtual fapi2::ReturnCode offset_for_min_cas_to_cas_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
+ // Bytes 320 ~ 383 Module Supplier’s Data ??
+};
- virtual fapi2::ReturnCode offset_min_act_to_act_delay_time_diff_bank_gp(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
+enum SDRAM_PACKAGE_TYPE : uint64_t
+{
+ // Signal loading
+ MONOLITHIC = 0,
+ NON_MONOLITHIC = 1,
+
+ // Package Type
+ UNSPECIFIED = 0,
+ MULTI_LOAD_STACK = 1,
+ SINGLE_LOAD_STACK = 2,
+};
- virtual fapi2::ReturnCode offset_min_act_to_act_delay_time_same_bank_gp(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
+enum NOMINAL_VOLTAGE : uint64_t
+{
+ NOT_OPERABLE = 0,
+ OPERABLE = 1,
- virtual fapi2::ReturnCode offset_for_min_act_to_act_refresh_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
+ NOT_ENDURANT = 0,
+ ENDURANT = 1
+};
- virtual fapi2::ReturnCode offset_for_min_row_precharge_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
- virtual fapi2::ReturnCode offset_for_min_ras_to_cas_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target_dimm,
- const uint8_t* i_spd_data);
+///
+/// @class decoder
+/// @brief Base SPD DRAM decoder
+///
+class decoder
+{
- virtual fapi2::ReturnCode offset_for_min_cas_latency_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ public:
+ // Constructor
+ decoder() = default;
- virtual fapi2::ReturnCode offset_for_min_cycle_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
+ // Deconstructor
+ virtual ~decoder() = default;
- virtual fapi2::ReturnCode offset_for_max_cycle_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
- virtual fapi2::ReturnCode crc_for_base_config_section(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data);
-#endif
-};
+ /////////////////////////
+ // Static members functions
+ /////////////////////////
+
+ ///
+ /// @brief Decodes SPD Revision encoding level
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value revision number
+ /// @return fapi2::ReturnCode
+ /// @note Decodes SPD Byte 1 (3~0).
+ /// @note Item JC-45-2220.01x
+ /// @note Page 14-15
+ /// @note DDR4 SPD Document Release 3
+ ///
+ static fapi2::ReturnCode rev_encoding_level(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes SPD Revision additions level
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value revision number
+ /// @return fapi2::ReturnCode
+ /// @note Decodes SPD Byte 1 (bits 7~4).
+ /// @note Item JC-45-2220.01x
+ /// @note Page 14-15
+ /// @note DDR4 SPD Document Release 3
+ ///
+ static fapi2::ReturnCode rev_additions_level(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+
+ ///
+ /// @brief Decodes base module type (DIMM type) from SPD
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value
+ /// @return fapi2::ReturnCode
+ /// @note Decodes SPD Byte 3 (bits 3~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 17
+ /// @note DDR4 SPD Document Release 3
+ ///
+ static fapi2::ReturnCode base_module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+
+ ///
+ /// @brief Object factory to select correct decoder based on SPD revision & dimm type
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value shared pointer to the factory object
+ /// @return fapi2::ReturnCode
+ ///
+ static fapi2::ReturnCode factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ std::shared_ptr<decoder>& o_value);
+
+ /////////////////////////
+ // Member Methods
+ /////////////////////////
+
+ ///
+ /// @brief Decodes number of used SPD bytes
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value number of SPD bytes used
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint16_t& o_value);
+
+ ///
+ /// @brief Decodes total number of SPD bytes
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value number of total SPD bytes
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint16_t& o_value);
+
+ ///
+ /// @brief Decodes DRAM Device Type
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value dram device type enumeration
+ /// @return fapi2::ReturnCode
+ /// @note Decodes SPD Byte 2
+ /// @note Item JC-45-2220.01x
+ /// @note Page 16
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode dram_device_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+
+ ///
+ /// @brief Decodes hybrid media field from SPD
+ /// @param[in] i_target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes hybrid field from SPD
+ /// @param[in] i_target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value
+ /// @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
+ ///
+ virtual fapi2::ReturnCode hybrid(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes SDRAM density from SPD
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value SDRAM density in GBs
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes number of SDRAM banks from SPD
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value Number of SDRAM banks
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+
+ ///
+ /// @brief Decodes number of SDRAM bank groups from SPD
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value Number of SDRAM bank groups
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes number of SDRAM column address bits
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes number of SDRAM row address bits
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes Primary SDRAM signal loading
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes Primary SDRAM die count
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes Primary SDRAM package type
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decode SDRAM Maximum activate count
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint32_t& o_value);
+ ///
+ /// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point
+ /// @param[in] i_target
+ /// @param[in] i_spd_data
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint32_t& o_value);
+ ///
+ /// @brief Decode Soft post package repair (soft PPR)
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decode Post package repair (PPR)
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @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
+ ///
+ virtual fapi2::ReturnCode post_package_repair(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes Secondary SDRAM signal loading
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes Secondary DRAM Density Ratio
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes Secondary SDRAM die count
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes Secondary SDRAM package type
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decode Module Nominal Voltage, VDD
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value enum representing if 1.2V is operable
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decode Module Nominal Voltage, VDD
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value enum representing if 1.2V is endurant
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes SDRAM device width
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value device width in bits
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes number of package ranks per DIMM
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value number of package ranks per DIMM
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes Rank Mix
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value rank mix value from SPD
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes primary bus width
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value primary bus width in bits
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decodes bus width extension
+ /// @param[in] i_target FAPI2 DIMM targetn
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value bus width extension in bits
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decode Module Thermal Sensor
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value thermal sensor value from SPD
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decode Extended Base Module Type
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value extended base module type value from SPD
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value);
+ ///
+ /// @brief Decode Fine Timebase
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value fine_timebase from SPD in picoseconds
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decode Medium Timebase
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value fine_timebase from SPD in picoseconds
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ ///
+ /// @brief Decodes SDRAM Minimum Cycle Time in MTB
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tCKmin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+
+ ///
+ /// @brief Decodes SDRAM Maximum Cycle Time in MTB
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tCKmax in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decode CAS Latencies Supported
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value bitmap of supported CAS latencies
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint64_t& o_value);
+ ///
+ /// @brief Decodes SDRAM Minimum CAS Latency Time in MTB
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tAAmin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRCDmin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRPmin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRASmin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRCmin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRFC1min in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRFC2min in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRFC4min in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes SDRAM Minimum Four Activate Window Delay Time
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tFAWmin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRRD_Smin MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRRD_Lmin MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tCCD_Lmin MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Minimum Write Recovery Time
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tWRmin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Minimum Write to Read Time - Different Bank Group
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tWRT_Smin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+
+ ///
+ /// @brief Decodes Minimum Write to Read Time - Same Bank Group
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tWRT_Lmin in MTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tCCD_Lmin offset in FTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRRD_Lmin offset in FTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRRD_Smin offset in FTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRCmin offset in FTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRPmin offset in FTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tRCDmin offset in FTB units
+ /// @return fapi2::ReturnCode
+ /// @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<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tAAmin offset in FTB units
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tCKmax offset in FTB units
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value tCKmin offset in FTB units
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ int64_t& o_value);
+
+ ///
+ /// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section
+ /// @param[in] i_target FAPI2 DIMM target
+ /// @param[in] i_spd_data SPD blob
+ /// @param[out] o_value crc value from SPD
+ /// @return fapi2::ReturnCode
+ /// @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,
+ const uint8_t* i_spd_data,
+ uint16_t& o_value);
+};// decoder
}// spd
}// mss
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 a91715876..f71578e82 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
@@ -48,7 +48,7 @@ inline fapi2::ReturnCode dram_type(const fapi2::Target<fapi2::TARGET_TYPE_MCS>&
uint8_t l_dram_gen[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
// Retrieve DDR4 dimm attributes
- FAPI_TRY(spd_dram_device_type(i_target_mcs, &(l_dram_gen[0][0])));
+ FAPI_TRY(eff_dram_gen(i_target_mcs, &(l_dram_gen[0][0])));
// Make sure all DRAMs are DDR4 or throw an error
// Iterate through MCA's/ports
@@ -66,7 +66,7 @@ inline fapi2::ReturnCode dram_type(const fapi2::Target<fapi2::TARGET_TYPE_MCS>&
l_dram_gen[port_num][dimm_num]);
// Nimbus supports only DDR4
- FAPI_ASSERT(l_dram_gen[port_num][dimm_num] == fapi2::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR4,
+ FAPI_ASSERT(l_dram_gen[port_num][dimm_num] == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4,
fapi2::MSS_UNSUPPORTED_DEV_TYPE().
set_DEV_TYPE(l_dram_gen[port_num][dimm_num]),
"%s Incorrect DRAM device generation, DRAM generation is %llx",
@@ -82,17 +82,14 @@ fapi_try_exit:
///
-/// @brief Check if there is DIMM mixing (and deconfigures unsupported mixing <shrug> ?? - AAM)
-/// @param[in] i_target_mcs const fapi2::Target<fapi2::TARGET_TYPE_MCS>&
-/// @param[out] o_module_type uint64_t (returns something ?? - AAM )
+/// @brief Check if there is DIMM mixing (and deconfigures unsupported mixing ?? - AAM)
/// @return FAPI2_RC_SUCCESS iff ok
/// @note Functionality currently unknown
///
-inline fapi2::ReturnCode dimm_mixing(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs,
- uint64_t& o_module_type)
+inline fapi2::ReturnCode dimm_mixing(void)
{
- //TODO
- //Need to complete - AAM
+ //FIX p8 ported code
+ //Need to complete and figure out how to implement for p9 - AAM
// Anuwat pushed Warren to say IBM systems will not support DIMM mixing
// Now DIMM deconfig rules? - AAM
@@ -137,12 +134,13 @@ inline fapi2::ReturnCode dimm_mixing(const fapi2::Target<fapi2::TARGET_TYPE_MCS>
}// dimm_mixing
///
-/// @brief Checks what type of system is configured (i.e., single drop, dual drop)
-/// @note Functionality currently unknown
+/// @brief Checks what type of system is configured (i.e., single drop, dual drop)
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @warning Functionality currently unknown. Used in mss_freq
///
inline fapi2::ReturnCode system_drop_type(void)
{
- //TODO
+
//Update for P9, how will we check if a system is single/dual drop?? - AAM
#if 0
@@ -190,12 +188,12 @@ fapi_try_exit:
///
/// @brief Checks nominal voltage is correct for all DIMMs
-/// @param[in] i_target_mcsi const fapi2::Target<fapi2::TARGET_TYPE_MCS>&,
-/// dimm_state i fapi2::TargetState
-/// @return ReturnCode
+/// @param[in] i_target_mcs the fapi2 target
+/// @param[in] i_dimm_state (i.e. functional or non-functional)
+/// @return ReturnCode
///
inline fapi2::ReturnCode module_nominal_voltage(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs,
- fapi2::TargetState dimm_state)
+ fapi2::TargetState i_dimm_state)
{
uint64_t l_module_nom_voltage[mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {0};
@@ -207,7 +205,7 @@ inline fapi2::ReturnCode module_nominal_voltage(const fapi2::Target<fapi2::TARGE
auto port_num = mss::index(p);
// Iterate through DIMM targets
- for (auto d : p.getChildren<fapi2::TARGET_TYPE_DIMM>(dimm_state))
+ for (auto d : p.getChildren<fapi2::TARGET_TYPE_DIMM>(i_dimm_state))
{
auto dimm_num = mss::index(d);
@@ -231,66 +229,98 @@ fapi_try_exit:
namespace spd
{
+
///
/// @brief Checks conditional passes and implements traces & exits if it fails
-/// @tparam T spd_data of any size
-/// @param[in] i_target const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& ,
-/// conditional bool,
-/// spd_byte_index size_t,
-// spd_data T,
-/// err_str const char*
+/// @tparam T input data of any size
+/// @param[in] i_target fapi2 dimm target
+/// @param[in] i_conditional conditional that we are testing against
+/// @param[in] i_spd_byte_index current SPD byte
+/// @param[in] i_spd_data debug data
+/// @param[in] i_err_str error string to print out when conditional fails
/// @return ReturnCode
///
template< typename T >
-inline fapi2::ReturnCode valid_value_fail(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- bool conditional,
- size_t spd_byte_index,
- T spd_data,
- const char* err_str)
+inline fapi2::ReturnCode fail_for_invalid_value(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ bool i_conditional,
+ size_t i_spd_byte_index,
+ T i_spd_data,
+ const char* i_err_str)
{
- FAPI_ASSERT(conditional,
- fapi2::MSS_SPD_DECODE_INVALID_VALUE().
- set_VALUE(spd_data).
- set_BYTE(spd_byte_index).
+ FAPI_ASSERT(i_conditional,
+ fapi2::MSS_BAD_SPD().
+ set_VALUE(i_spd_data).
+ set_BYTE(i_spd_byte_index).
set_DIMM_TARGET(i_target),
"%s %s Byte %d, Data returned: %d.",
c_str(i_target),
- err_str,
- spd_byte_index,
- spd_data);
+ i_err_str,
+ i_spd_byte_index,
+ i_spd_data);
fapi_try_exit:
return fapi2::current_err;
-} // invalid_value_fail()
+} // fail_for_invalid_value()
///
-/// @brief Checks conditional passes and implements traces if it fails
-/// @tparam T spd_data of any size
-/// @param[in] i_targeti const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& ,
-/// conditional bool,
-/// spd_byte_index size_t,
-// spd_data T,
-/// err_str const char*
+/// @brief Checks conditional passes and implements traces if it fails. No FFDC collected.
+/// @tparam T input data of any size
+/// @param[in] i_target fapi2 dimm target
+/// @param[in] i_conditional that we are testing against
+/// @param[in] i_spd_byte_index
+/// @param[in] i_spd_data debug data
+/// @param[in] i_err_str string to print out when conditional fails
/// @return void
///
template< typename T >
-inline void valid_value_warn(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- bool conditional,
- size_t spd_byte_index,
- T spd_data,
- const char* err_str)
+inline void warn_for_invalid_value(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ bool i_conditional,
+ size_t i_spd_byte_index,
+ T i_spd_data,
+ const char* i_err_str)
{
// Don't print warning conditional is true
- if(!conditional)
+ if(!i_conditional)
{
FAPI_IMP("%s. %s. Byte %d, Data returned: %d.",
c_str(i_target),
- err_str,
- spd_byte_index,
- spd_data );
+ i_err_str,
+ i_spd_byte_index,
+ i_spd_data );
}
-}// valid_value_warn
+}// warn_for_invalid_value
+
+///
+/// @brief Checks if valid factory parameters are given
+/// @param[in] i_target fapi2 dimm target
+/// @param[in] i_dimm_type DIMM type enumeration
+/// @param[in] i_encoding_rev SPD encoding level rev number
+/// @param[in] i_additions_rev SPD additions level rev number
+/// @param[in] i_err_str string to print out when conditional fails
+/// @return fapi2::ReturnCode
+///
+inline fapi2::ReturnCode invalid_factory_sel(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ uint8_t i_dimm_type,
+ uint8_t i_encoding_rev,
+ uint8_t i_additions_rev,
+ const char* i_err_str)
+{
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_DIMM_REV_COMBO().
+ set_DIMM_TYPE(i_dimm_type).
+ set_ENCODING_REV(i_encoding_rev).
+ set_ADDITIONS_REV(i_additions_rev).
+ set_DIMM_TARGET(i_target),
+ "%s. %s. Invalid combination for dimm type: %d, rev: %d.%d",
+ c_str(i_target),
+ i_err_str,
+ i_dimm_type,
+ i_encoding_rev,
+ i_additions_rev);
+fapi_try_exit:
+ return fapi2::current_err;
+}// invalid_factory_sel
}// spd
}// check
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H
index c39ebf057..70c58289d 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H
@@ -42,36 +42,40 @@ static const uint64_t SIM_CYCLES_PER_CYCLE = 8;
namespace mss
{
+
+///
+/// @brief Return the number of picoseconds
+/// @tparam T input and output type
+/// @param[in] i_transfer_rate input in MegaTransfers per second (MT/s)
+/// @return timing in picoseconds
+/// @note clock periods are defined to 1 ps of accuracy, so
+/// so 1.0714 ns is defined as 1071 ps as defined by JEDEC's
+/// SPD rounding algorithm. This concept is used for this calculation.
+///
+template<typename T>
+inline T freq_to_ps(const T i_transfer_rate)
+{
+ // ATTR_MSS_FREQ is in MT/s, and we know microsecond per clock is 1/(freq/2)
+ // actual dimm_freq is 1/2 of the speed bin
+ T l_dimm_freq = i_transfer_rate / 2;
+
+ // ps per clock (note value is rounded down)
+ return CONVERT_PS_IN_A_US / l_dimm_freq;
+}
+
///
-/// @brief Return the number of picoseconds taken by a certain mhz
-/// @param[in] i_mhz the mhz of interest
-/// @return the picoseconds
+/// @brief Return the number in MT/s
+/// @tparam T input and output type
+/// @param[in] i_time_in_ps time in picoseconds
+/// @return speed in MT/s
///
-inline uint64_t mhz_to_ps(const uint64_t i_mhz)
+template<typename T>
+inline T ps_to_freq(const T i_time_in_ps)
{
- // Just used for indexs into the array below
- enum freqs { FREQ_2400 = 0, };
-
- // ATTR_MSS_FREQ is in mHZ, and we know us per clock is 1/(freq/2)
- // We don't have many frequencies, so lets just make a little table.
- static const uint64_t FREQ_TO_PS[MAX_SUPPORTED_FREQUENCIES] =
- {
- // 2400 is 833 picoseconds per clock
- 833
- };
-
- switch(i_mhz)
- {
- case 2400:
- return FREQ_TO_PS[FREQ_2400];
-
- default:
- FAPI_ERR("unsupported frequency %llu", i_mhz);
- fapi2::Assert(false);
-
- // Keeps compiler happy
- return 0;
- }
+ // reverse of freq_to_ps function, solving for freq
+ // since running at DDR, data is transferred on both rising & falling edges
+ // hence the 2X factor
+ return (2 * CONVERT_PS_IN_A_US) / i_time_in_ps;
}
///
@@ -95,7 +99,7 @@ template< fapi2::TargetType T >
inline uint64_t ps_to_cycles(const fapi2::Target<T>& i_target, const uint64_t i_ps)
{
// The frequency in mHZ
- uint64_t l_freq;
+ uint64_t l_freq = 0;
uint64_t l_divisor = 0;
uint64_t l_quotient = 0;
uint64_t l_remainder = 0;
@@ -103,7 +107,7 @@ inline uint64_t ps_to_cycles(const fapi2::Target<T>& i_target, const uint64_t i_
FAPI_TRY( mss::freq( find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq) );
// Hoping the compiler figures out how to do these together.
- l_divisor = mhz_to_ps(l_freq);
+ l_divisor = freq_to_ps(l_freq);
l_quotient = i_ps / l_divisor;
l_remainder = i_ps % l_divisor;
@@ -132,12 +136,12 @@ template< fapi2::TargetType T >
inline uint64_t cycles_to_ps(const fapi2::Target<T>& i_target, const uint64_t i_cycles)
{
// The frequency in mHZ
- uint64_t l_freq;
+ uint64_t l_freq = 0;
FAPI_TRY( mss::freq( find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq) );
- FAPI_DBG("converting %llu cycles to %llups", i_cycles, i_cycles * mhz_to_ps(l_freq));
- return i_cycles * mhz_to_ps(l_freq);
+ FAPI_DBG("converting %llu cycles to %llups", i_cycles, i_cycles * freq_to_ps(l_freq));
+ return i_cycles * freq_to_ps(l_freq);
fapi_try_exit:
@@ -236,28 +240,33 @@ inline uint64_t twlo_twloe(const fapi2::Target<T>& i_target)
}
///
-/// @brief Convert nanoseconds to picoseconds
-/// @param[in] i_time_in_ns int64_t time in nanoseconds
-/// @return int64_t, time in picoseconds
+/// @brief Convert nanoseconds to picoseconds
+/// @tparam T input and output type
+/// @param[in] i_time_in_ns time in nanoseconds
+/// @return time in picoseconds
///
-inline int64_t ns_to_ps(const int64_t& i_time_in_ns)
+template<typename T>
+inline T ns_to_ps(const T i_time_in_ns)
{
return i_time_in_ns * CONVERT_PS_IN_A_NS;
}
///
-/// @brief Convert nanoseconds to picoseconds
-/// @param[in] i_time_in_ps int64_t time in picoseconds
-/// @return int64_t, time in nanoseconds
+/// @brief Convert nanoseconds to picoseconds
+/// @tparam T input and output type
+/// @param[in] i_time_in_ps time in picoseconds
+/// @return time in nanoseconds
///
-inline int64_t ps_to_ns(const int64_t& i_time_in_ps)
+template<typename T>
+inline T ps_to_ns(const T i_time_in_ps)
{
- int64_t remainder = i_time_in_ps % CONVERT_PS_IN_A_NS;
- int64_t l_time_in_ns = i_time_in_ps / CONVERT_PS_IN_A_NS;
+ T remainder = i_time_in_ps % CONVERT_PS_IN_A_NS;
+ T l_time_in_ns = i_time_in_ps / CONVERT_PS_IN_A_NS;
// Round up if remainder isn't even
return l_time_in_ns + ( remainder == 0 ? 0 : 1 );
}
};// mss namespace
+
#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H
index a13c1cd62..e15563970 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H
@@ -43,17 +43,17 @@ namespace mss
/// @return a vector of M targets.
///
template< fapi2::TargetType M, fapi2::TargetType T >
-inline std::vector< fapi2::Target<M> > find_targets( const fapi2::Target<T>& );
+inline std::vector< fapi2::Target<M> > find_targets( const fapi2::Target<T>& i_target);
///
/// @brief find an element based on a fapi2 target
/// @tparam M the target type to be returned
/// @tparam T the fapi2 target type of the argument
-/// @param[in] the fapi2 target T
+/// @param[in] i_target the fapi2 target T
/// @return an M target.
///
template< fapi2::TargetType M, fapi2::TargetType T >
-inline fapi2::Target<M> find_target( const fapi2::Target<T>& );
+inline fapi2::Target<M> find_target( const fapi2::Target<T>& i_target );
///
/// @brief find the McBIST given a McBIST
@@ -182,6 +182,39 @@ inline fapi2::Target<fapi2::TARGET_TYPE_MCA> find_target( const fapi2::Target<fa
return i_target.getParent<fapi2::TARGET_TYPE_MCA>();
}
+///
+/// @brief find a key value from a vector of STL pairs
+/// @tparam T input type
+/// @tparam OT the output type to be returned
+/// @param[in] i_vector_of_pairs the input vector of pairs
+/// @param[in] i_key the "map" key
+/// @param[in] o_value the value found from given key
+/// @return the value corresponding to the key
+///
+template<typename T, typename OT>
+bool find_value_from_key(const std::vector<std::pair<T, OT> >& i_vector_of_pairs, const T& i_key, OT& o_value)
+{
+ // Comparator lambda expression
+ auto compare = [](const std::pair<T, OT>& i_lhs, const T & i_value)
+ {
+ return (i_lhs.first < i_value);
+ };
+
+ // Find iterator to matching key (if it exists)
+ auto l_value_iterator = std::lower_bound(i_vector_of_pairs.begin(), i_vector_of_pairs.end(), i_key, compare);
+
+ // Did you find it? Let me know.
+ if( (l_value_iterator == i_vector_of_pairs.end()) || (i_key != l_value_iterator->first) )
+ {
+ return false;
+ }
+
+ o_value = l_value_iterator->second;
+ return true;
+
+}
+
+
}// mss
#endif
OpenPOWER on IntegriCloud