summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/spd
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2018-04-19 14:49:49 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-06-30 16:55:16 -0400
commit81996e944c89eee35d274813a990558a7cf5c368 (patch)
tree4ad14f0981d4031a9dfff3d79cb9f78f49e5df92 /src/import/generic/memory/lib/spd
parent60b941209240b4c6da120366fe6e4edc9e4a7687 (diff)
downloadblackbird-hostboot-81996e944c89eee35d274813a990558a7cf5c368.tar.gz
blackbird-hostboot-81996e944c89eee35d274813a990558a7cf5c368.zip
Add SPD reader and traits DDR4 def
Includes addition of a generic const file to store constants that are not controller dependent. In addition to spd::c_str for SPD decoder tracing. Change-Id: I6dafe1ff3328a1ac287b29f148e63e304f626ea5 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/57492 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/58197 Reviewed-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Tested-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/generic/memory/lib/spd')
-rw-r--r--src/import/generic/memory/lib/spd/spd_field.H148
-rw-r--r--src/import/generic/memory/lib/spd/spd_fields_ddr4.H759
-rw-r--r--src/import/generic/memory/lib/spd/spd_reader.H123
-rw-r--r--src/import/generic/memory/lib/spd/spd_traits.H164
-rw-r--r--src/import/generic/memory/lib/spd/spd_traits_ddr4.H3764
5 files changed, 4958 insertions, 0 deletions
diff --git a/src/import/generic/memory/lib/spd/spd_field.H b/src/import/generic/memory/lib/spd/spd_field.H
index b4dc02c1a..70761a2ed 100644
--- a/src/import/generic/memory/lib/spd/spd_field.H
+++ b/src/import/generic/memory/lib/spd/spd_field.H
@@ -22,3 +22,151 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file spd_field.H
+/// @brief SPD data fields
+///
+
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_SPD_FIELD_H_
+#define _MSS_SPD_FIELD_H_
+
+#include <cstdint>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
+namespace mss
+{
+namespace spd
+{
+
+///
+/// @class field_t
+/// @brief data structure for SPD byte fields
+/// @note holds byte index, start bit, and bit length of a decoded field
+///
+class field_t
+{
+ private:
+
+ const size_t iv_byte;
+ const size_t iv_start;
+ const size_t iv_length;
+
+ public:
+
+ // default ctor deleted
+ field_t() = delete;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_byte_index
+ /// @param[in] i_start_bit
+ /// @param[in] i_bit_length
+ ///
+ constexpr field_t(const size_t i_byte_index,
+ const size_t i_start_bit,
+ const size_t i_bit_length)
+ : iv_byte(i_byte_index),
+ iv_start(i_start_bit),
+ iv_length(i_bit_length)
+ {}
+
+ ///
+ /// @brief default dtor
+ ///
+ ~field_t() = default;
+
+ ///
+ /// @brief Byte index getter
+ /// @return the byte index for this SPD field
+ ///
+ constexpr size_t get_byte() const
+ {
+ return iv_byte;
+ }
+
+ ///
+ /// @brief Starting bit getter
+ /// @return the starting bit position for this SPD field
+ ///
+ constexpr size_t get_start() const
+ {
+ return iv_start;
+ }
+
+ ///
+ /// @brief bit length getter
+ /// @return the bit length of this SPD field
+ ///
+ constexpr size_t get_length() const
+ {
+ return iv_length;
+ }
+
+};// field_t
+
+///
+/// @class init_fields
+/// @brief Initial fields needed to know how to parse the SPD
+/// @note These are preliminary fields that need to be independently
+/// decoded from any specific DRAM generation SPEC (e.g. SPD factory)
+///
+class init_fields
+{
+ private:
+
+ enum
+ {
+ // Byte 1
+ REVISION_START = 0,
+ REVISION_LEN = 8,
+
+ // Byte 2
+ DEVICE_TYPE_START = 0,
+ DEVICE_TYPE_LEN = 8,
+
+ // Byte 3
+ HYBRID_START = 0,
+ HYBRID_LEN = 1,
+ HYBRID_MEDIA_START = 1,
+ HYBRID_MEDIA_LEN = 3,
+ BASE_MODULE_START = 4,
+ BASE_MODULE_LEN = 4,
+
+ // Byte 130
+ REF_RAW_CARD_START = 0,
+ REF_RAW_CARD_LEN = 8,
+ };
+
+ public:
+
+ // 1st field: Byte number
+ // 2nd field: Start bit
+ // 3rd field: Bit length
+ static constexpr field_t REVISION{1, REVISION_START, REVISION_LEN};
+ static constexpr field_t DEVICE_TYPE{2, DEVICE_TYPE_START, DEVICE_TYPE_LEN};
+ static constexpr field_t BASE_MODULE{3, BASE_MODULE_START, BASE_MODULE_LEN};
+ static constexpr field_t HYBRID{3, HYBRID_START, HYBRID_LEN};
+ static constexpr field_t HYBRID_MEDIA{3, HYBRID_MEDIA_START, HYBRID_MEDIA_LEN};
+ static constexpr field_t REF_RAW_CARD{130, REF_RAW_CARD_START, REF_RAW_CARD_LEN};
+};
+
+///
+/// @class fields
+/// @brief Collection of SPD fields
+/// @tparam D DRAM device type (e.g. DDR4)
+/// @tparam S SPD parameter (e.g. RDIMM_MODULE, NVDIMM_MODULE)
+///
+template <device_type D, parameters S>
+class fields;
+
+}// spd
+}// mss
+
+#endif // _MSS_SPD_FIELD_H_
diff --git a/src/import/generic/memory/lib/spd/spd_fields_ddr4.H b/src/import/generic/memory/lib/spd/spd_fields_ddr4.H
index 83f31c90d..97413367d 100644
--- a/src/import/generic/memory/lib/spd/spd_fields_ddr4.H
+++ b/src/import/generic/memory/lib/spd/spd_fields_ddr4.H
@@ -22,3 +22,762 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file spd_fields_ddr4.H
+/// @brief SPD data fields
+///
+
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_SPD_FIELDS_DDR4_H_
+#define _MSS_SPD_FIELDS_DDR4_H_
+
+#include <generic/memory/lib/spd/spd_field.H>
+
+namespace mss
+{
+namespace spd
+{
+
+///
+/// @class fields
+/// @brief DDR4 SPD General Section fields
+/// @note DDR4, BASE_CNFG specialization
+///
+/// @note Since these fields are used as non-type template params,
+/// they need have external linkage. Currently C++11 can achieve this
+/// by making them static constexpr member variables.
+///
+template<>
+class fields<DDR4, BASE_CNFG>
+{
+ enum
+ {
+ // Byte 0
+ BYTES_USED_START = 4,
+ BYTES_USED_LEN = 4,
+
+ BYTES_TOTAL_START = 1,
+ BYTES_TOTAL_LEN = 3,
+
+ // Byte 1
+ REVISION_START = 0,
+ REVISION_LEN = 8,
+
+ // Byte 2
+ DEVICE_TYPE_START = 0,
+ DEVICE_TYPE_LEN = 8,
+
+ // Byte 3
+ HYBRID_START = 0,
+ HYBRID_LEN = 1,
+ HYBRID_MEDIA_START = 1,
+ HYBRID_MEDIA_LEN = 3,
+ BASE_MODULE_START = 4,
+ BASE_MODULE_LEN = 4,
+
+ // Byte 4
+ SDRAM_CAPACITY_START = 4,
+ SDRAM_CAPACITY_LEN = 4,
+
+ SDRAM_BANKS_START = 2,
+ SDRAM_BANKS_LEN = 2,
+
+ BANK_GROUP_START = 0,
+ BANK_GROUP_LEN = 2,
+
+ // Byte 5
+ COL_ADDRESS_START = 5,
+ COL_ADDRESS_LEN = 3,
+
+ ROW_ADDRESS_START = 2,
+ ROW_ADDRESS_LEN = 3,
+
+ // Byte 6
+ PRIM_SIGNAL_LOAD_START = 6,
+ PRIM_SIGNAL_LOAD_LEN = 2,
+
+ PRIM_DIE_COUNT_START = 1,
+ PRIM_DIE_COUNT_LEN = 3,
+
+ PRIM_PACKAGE_TYPE_START = 0,
+ PRIM_PACKAGE_TYPE_LEN = 1,
+
+ // Byte 7
+ MAC_START = 4,
+ MAC_LEN = 4,
+
+ TMAW_START = 2,
+ TMAW_LEN = 2,
+
+ // Byte 8 reserved
+
+ // Byte 9
+ SOFT_PPR_START = 2,
+ SOFT_PPR_LEN = 1,
+
+ PPR_START = 0,
+ PPR_LEN = 2,
+
+ // Byte 10
+ SEC_SIGNAL_LOAD_START = 6,
+ SEC_SIGNAL_LOAD_LEN = 2,
+
+ DENSITY_RATIO_START = 4,
+ DENSITY_RATIO_LEN = 2,
+
+ SEC_DIE_COUNT_START = 1,
+ SEC_DIE_COUNT_LEN = 3,
+
+ SEC_PACKAGE_TYPE_START = 0,
+ SEC_PACKAGE_TYPE_LEN = 1,
+
+ // Byte 11
+ OPERABLE_START = 7,
+ OPERABLE_LEN = 1,
+
+ ENDURANT_START = 6,
+ ENDURANT_LEN = 1,
+
+ NOM_VOLT_START = 0,
+ NOM_VOLT_LEN = 6,
+
+ // Byte 12
+ SDRAM_WIDTH_START = 5,
+ SDRAM_WIDTH_LEN = 3,
+
+ PACKAGE_RANKS_START = 2,
+ PACKAGE_RANKS_LEN = 3,
+
+ RANK_MIX_START = 1,
+ RANK_MIX_LEN = 1,
+
+ // Byte 13
+ BUS_WIDTH_START = 5,
+ BUS_WIDTH_LEN = 3,
+
+ BUS_EXT_WIDTH_START = 3,
+ BUS_EXT_WIDTH_LEN = 2,
+
+ // Byte 14
+ THERM_SENSOR_RESERV_START = 1,
+ THERM_SENSOR_RESERV_LEN = 7,
+
+ THERM_SENSOR_START = 0,
+ THERM_SENSOR_LEN = 1,
+
+ // Byte 15
+ EXT_MOD_TYPE_START = 5,
+ EXT_MOD_TYPE_LEN = 3,
+
+ // Byte 16 - reserved
+
+ // Byte 17
+ FINE_TIMEBASE_START = 6,
+ FINE_TIMEBASE_LEN = 2,
+
+ MED_TIMEBASE_START = 4,
+ MED_TIMEBASE_LEN = 2,
+
+ // Byte 18
+ TCK_MIN_START = 0,
+ TCK_MIN_LEN = 8,
+
+ // Byte 19
+ TCK_MAX_START = 0,
+ TCK_MAX_LEN = 8,
+
+ // Byte 20-23
+ CAS_BYTE_1_START = 0,
+ CAS_BYTE_1_LEN = 8,
+ CAS_BYTE_2_START = 0,
+ CAS_BYTE_2_LEN = 8,
+ CAS_BYTE_3_START = 0,
+ CAS_BYTE_3_LEN = 8,
+ CAS_BYTE_4_START = 0,
+ CAS_BYTE_4_LEN = 8,
+
+ // Byte 24
+ TAA_MIN_START = 0,
+ TAA_MIN_LEN = 8,
+
+ // Byte 25
+ TRCD_MIN_START = 0,
+ TRCD_MIN_LEN = 8,
+
+ // Byte 26
+ TRP_MIN_START = 0,
+ TRP_MIN_LEN = 8,
+
+ // Byte 27
+ TRASMIN_MSN_START = 4, // MSN = most significant nibble
+ TRASMIN_MSN_LEN = 4,
+
+ TRCMIN_MSN_START = 0, // MSN = most significant nibble
+ TRCMIN_MSN_LEN = 4,
+
+ // Byte 28
+ TRASMIN_LSB_START = 0, // LSB = least significant byte
+ TRASMIN_LSB_LEN = 8,
+
+ // Byte 29
+ TRCMIN_LSB_START = 0, // LSB = least significant byte
+ TRCMIN_LSB_LEN = 8,
+
+ // Byte 30
+ TRFC1MIN_LSB_START = 0,
+ TRFC1MIN_LSB_LEN = 8,
+
+ // Byte 31
+ TRFC1MIN_MSB_START = 0,
+ TRFC1MIN_MSB_LEN = 8,
+
+ // Byte 32
+ TRFC2MIN_LSB_START = 0,
+ TRFC2MIN_LSB_LEN = 8,
+
+ // Byte 33
+ TRFC2MIN_MSB_START = 0,
+ TRFC2MIN_MSB_LEN = 8,
+
+ // Byte 34 & Byte 35
+ TRFC4MIN_LSB_START = 0,
+ TRFC4MIN_LSB_LEN = 8,
+
+ TRFC4MIN_MSB_START = 0,
+ TRFC4MIN_MSB_LEN = 8,
+
+ // Byte 36
+ TFAWMIN_MSN_START = 4,
+ TFAWMIN_MSN_LEN = 4,
+
+ // Byte 37
+ TFAWMIN_LSB_START = 0,
+ TFAWMIN_LSB_LEN = 8,
+
+ // Byte 38
+ TRRD_S_MIN_START = 0,
+ TRRD_S_MIN_LEN = 8,
+
+ // Byte 39
+ TRRD_L_MIN_START = 0,
+ TRRD_L_MIN_LEN = 8,
+
+ // Byte 40
+ TCCD_L_MIN_START = 0,
+ TCCD_L_MIN_LEN = 8,
+
+ // Byte 41
+ TWRMIN_MSN_START = 4, // MSN = most significant nibble
+ TWRMIN_MSN_LEN = 4,
+
+ // Byte 42
+ TWRMIN_LSB_START = 0, // LSB = least significant nibble
+ TWRMIN_LSB_LEN = 8,
+
+ // Byte 43
+ TWTRMIN_L_MSN_START = 0, // MSN = most significant nibble
+ TWTRMIN_L_MSN_LEN = 4,
+
+ TWTRMIN_S_MSN_START = 4, // MSN = most significant nibble
+ TWTRMIN_S_MSN_LEN = 4,
+
+ // Byte 44
+ TWTRMIN_S_LSB_START = 0, // LSB = least significant byte
+ TWTRMIN_S_LSB_LEN = 8,
+
+ // Byte 45
+ TWTRMIN_L_LSB_START = 0,
+ TWTRMIN_L_LSB_LEN = 8,
+
+ // Bytes 46 - 59 - reserved
+
+ // Bytes 78 - 116 - reserved
+
+ // Bytes 117
+ OFFSET_TCCD_L_MIN_START = 0,
+ OFFSET_TCCD_L_MIN_LEN = 8,
+
+ // Bytes 118
+ OFFSET_TRRD_L_MIN_START = 0,
+ OFFSET_TRRD_L_MIN_LEN = 8,
+
+ // Bytes 119
+ OFFSET_TRRD_S_MIN_START = 0,
+ OFFSET_TRRD_S_MIN_LEN = 8,
+
+ // Byte 120
+ OFFSET_TRC_MIN_START = 0,
+ OFFSET_TRC_MIN_LEN = 8,
+
+ // Byte 121
+ OFFSET_TRP_MIN_START = 0,
+ OFFSET_TRP_MIN_LEN = 8,
+
+ // Byte 122
+ OFFSET_TRCD_MIN_START = 0,
+ OFFSET_TRCD_MIN_LEN = 8,
+
+ // Byte 123
+ OFFSET_TAA_MIN_START = 0,
+ OFFSET_TAA_MIN_LEN = 8,
+
+ // Byte 124
+ OFFSET_TCK_MAX_START = 0,
+ OFFSET_TCK_MAX_LEN = 8,
+
+ // Byte 125
+ OFFSET_TCK_MIN_START = 0,
+ OFFSET_TCK_MIN_LEN = 8,
+
+ // Byte 126
+ CRC_LSB_START = 0,
+ CRC_LSB_LEN = 8,
+
+ // Byte 127
+ CRC_MSB_START = 0,
+ CRC_MSB_LEN = 8,
+
+ // Byte 130
+ REF_RAW_CARD_START = 0,
+ REF_RAW_CARD_LEN = 8,
+
+ // Byte 320
+ CONTINUATION_CODES_START = 0,
+ CONTINUATION_CODES_LEN = 8,
+
+ // Byte 321
+ LAST_NON_ZERO_BYTE_START = 0,
+ LAST_NON_ZERO_BYTE_LEN = 8,
+
+ // Byte 322
+ MODULE_MFG_LOC_START = 0,
+ MODULE_MFG_LOC_LEN = 8,
+
+ // Bytes 323-324
+ MODULE_MFG_DATE_START = 0,
+ MODULE_MFG_DATE_LEN = 8,
+
+ // Bytes 325-328
+ MODULE_SERIAL_NUM_START = 0,
+ MODULE_SERIAL_NUM_LEN = 8,
+
+ // Byte 349
+ MODULE_REV_CODE_START = 0,
+ MODULE_REV_CODE_LEN = 8,
+
+ // Byte 350-351
+ DRAM_MFR_ID_CODE_START = 0,
+ DRAM_MFR_ID_CODE_LEN = 8,
+
+ // Byte 352
+ DRAM_STEPPING_START = 0,
+ DRAM_STEPPING_LEN = 8,
+ };
+
+ public:
+
+ // 1st field: Byte number
+ // 2nd field: Start bit
+ // 3rd field: Bit length
+ static constexpr field_t BYTES_USED{0, BYTES_USED_START, BYTES_USED_LEN};
+ static constexpr field_t TOTAL_BYTES{0, BYTES_TOTAL_START, BYTES_TOTAL_LEN};
+ static constexpr field_t REVISION{1, REVISION_START, REVISION_LEN};
+ static constexpr field_t DEVICE_TYPE{2, DEVICE_TYPE_START, DEVICE_TYPE_LEN};
+ static constexpr field_t BASE_MODULE{3, BASE_MODULE_START, BASE_MODULE_LEN};
+ static constexpr field_t HYBRID{3, HYBRID_START, HYBRID_LEN};
+ static constexpr field_t HYBRID_MEDIA{3, HYBRID_MEDIA_START, HYBRID_MEDIA_LEN};
+ static constexpr field_t SDRAM_CAPACITY{4, SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN};
+ static constexpr field_t BANKS_ADDR_BITS{4, SDRAM_BANKS_START, SDRAM_BANKS_LEN};
+ static constexpr field_t BANK_GROUP_BITS{4, BANK_GROUP_START, BANK_GROUP_LEN};
+ static constexpr field_t COL_ADDR_BITS{5, COL_ADDRESS_START, COL_ADDRESS_LEN};
+ static constexpr field_t ROW_ADDR_BITS{5, ROW_ADDRESS_START, ROW_ADDRESS_LEN};
+ static constexpr field_t PRIM_SIGNAL_LOADING{6, PRIM_SIGNAL_LOAD_START, PRIM_SIGNAL_LOAD_LEN};
+ static constexpr field_t PRIM_DIE_COUNT{6, PRIM_DIE_COUNT_START, PRIM_DIE_COUNT_LEN};
+ static constexpr field_t PRIM_PACKAGE_TYPE{6, PRIM_PACKAGE_TYPE_START, PRIM_PACKAGE_TYPE_LEN};
+ static constexpr field_t MAC{7, MAC_START, MAC_LEN};
+ static constexpr field_t TMAW{7, TMAW_START, TMAW_LEN};
+ static constexpr field_t PPR{9, PPR_START, PPR_LEN};
+ static constexpr field_t SOFT_PPR{9, SOFT_PPR_START, SOFT_PPR_LEN};
+ static constexpr field_t SEC_SIGNAL_LOADING{10, SEC_SIGNAL_LOAD_START, SEC_SIGNAL_LOAD_LEN};
+ static constexpr field_t SEC_DENSITY_RATIO{10, DENSITY_RATIO_START, DENSITY_RATIO_LEN};
+ static constexpr field_t SEC_DIE_COUNT{10, SEC_DIE_COUNT_START, SEC_DIE_COUNT_LEN};
+ static constexpr field_t SEC_PACKAGE_TYPE{10, SEC_PACKAGE_TYPE_START, SEC_PACKAGE_TYPE_LEN};
+ static constexpr field_t OPERABLE_FLD{11, OPERABLE_START, OPERABLE_LEN};
+ static constexpr field_t ENDURANT_FLD{11, ENDURANT_START, ENDURANT_LEN};
+ static constexpr field_t SDRAM_WIDTH{12, SDRAM_WIDTH_START, SDRAM_WIDTH_LEN};
+ static constexpr field_t RANK_MIX{12, RANK_MIX_START, RANK_MIX_LEN};
+ static constexpr field_t PACKAGE_RANKS{12, PACKAGE_RANKS_START, PACKAGE_RANKS_LEN};
+ static constexpr field_t BUS_WIDTH{13, BUS_WIDTH_START, BUS_WIDTH_LEN};
+ static constexpr field_t BUS_EXT_WIDTH{13, BUS_EXT_WIDTH_START, BUS_EXT_WIDTH_LEN};
+ static constexpr field_t THERM_SENSOR{14, THERM_SENSOR_START, THERM_SENSOR_LEN};
+ static constexpr field_t EXTENDED_MODULE_TYPE{15, EXT_MOD_TYPE_START, EXT_MOD_TYPE_LEN};
+ static constexpr field_t FINE_TIMEBASE{17, FINE_TIMEBASE_START, FINE_TIMEBASE_LEN};
+ static constexpr field_t MEDIUM_TIMEBASE{17, MED_TIMEBASE_START, MED_TIMEBASE_LEN};
+ static constexpr field_t TCK_MIN{18, TCK_MIN_START, TCK_MIN_LEN};
+ static constexpr field_t TCK_MAX{19, TCK_MAX_START, TCK_MAX_LEN};
+ static constexpr field_t CL_FIRST_BYTE{20, CAS_BYTE_1_START, CAS_BYTE_1_LEN};
+ static constexpr field_t CL_SECOND_BYTE{21, CAS_BYTE_2_START, CAS_BYTE_2_LEN};
+ static constexpr field_t CL_THIRD_BYTE{22, CAS_BYTE_3_START, CAS_BYTE_3_LEN};
+ static constexpr field_t CL_FOURTH_BYTE{23, CAS_BYTE_4_START, CAS_BYTE_4_LEN};
+ static constexpr field_t TAA_MIN{24, TAA_MIN_START, TAA_MIN_LEN};
+ static constexpr field_t TRCD_MIN{25, TRCD_MIN_START, TRCD_MIN_LEN};
+ static constexpr field_t TRP_MIN{26, TRP_MIN_START, TRP_MIN_LEN};
+ static constexpr field_t TRASMIN_MSN{27, TRASMIN_MSN_START, TRASMIN_MSN_LEN};
+ static constexpr field_t TRASMIN_LSB{28, TRASMIN_LSB_START, TRASMIN_LSB_LEN};
+ static constexpr field_t TRCMIN_MSN{27, TRCMIN_MSN_START, TRCMIN_MSN_LEN};
+ static constexpr field_t TRCMIN_LSB{29, TRCMIN_LSB_START, TRCMIN_LSB_LEN};
+ static constexpr field_t TRFC1MIN_LSB{30, TRFC1MIN_LSB_START, TRFC1MIN_LSB_LEN};
+ static constexpr field_t TRFC1MIN_MSB{31, TRFC1MIN_MSB_START, TRFC1MIN_MSB_LEN};
+ static constexpr field_t TRFC2MIN_LSB{32, TRFC2MIN_LSB_START, TRFC2MIN_LSB_LEN};
+ static constexpr field_t TRFC2MIN_MSB{33, TRFC2MIN_MSB_START, TRFC2MIN_MSB_LEN};
+ static constexpr field_t TRFC4MIN_LSB{34, TRFC4MIN_LSB_START, TRFC4MIN_LSB_LEN};
+ static constexpr field_t TRFC4MIN_MSB{35, TRFC4MIN_MSB_START, TRFC4MIN_MSB_LEN};
+ static constexpr field_t TFAWMIN_MSN{36, TFAWMIN_MSN_START, TFAWMIN_MSN_LEN};
+ static constexpr field_t TFAWMIN_LSB{37, TFAWMIN_LSB_START, TFAWMIN_LSB_LEN};
+ static constexpr field_t TRRD_S_MIN{38, TRRD_S_MIN_START, TRRD_S_MIN_LEN};
+ static constexpr field_t TRRD_L_MIN{39, TRRD_L_MIN_START, TRRD_L_MIN_LEN};
+ static constexpr field_t TCCD_L_MIN{39, TCCD_L_MIN_START, TCCD_L_MIN_LEN};
+ static constexpr field_t TWRMIN_MSN{41, TWRMIN_MSN_START, TWRMIN_MSN_LEN};
+ static constexpr field_t TWRMIN_LSB{42, TWRMIN_LSB_START, TWRMIN_LSB_LEN};
+ static constexpr field_t TWTRMIN_S_MSN{43, TWTRMIN_S_MSN_START, TWTRMIN_S_MSN_LEN};
+ static constexpr field_t TWTRMIN_S_LSB{44, TWTRMIN_S_LSB_START, TWTRMIN_S_LSB_LEN};
+ static constexpr field_t TWTRMIN_L_MSN{43, TWTRMIN_L_MSN_START, TWTRMIN_L_MSN_LEN};
+ static constexpr field_t TWTRMIN_L_LSB{45, TWTRMIN_L_LSB_START, TWTRMIN_L_LSB_LEN};
+ static constexpr field_t OFFSET_TCCD_L_MIN{117, OFFSET_TCCD_L_MIN_START, OFFSET_TCCD_L_MIN_LEN};
+ static constexpr field_t OFFSET_TRRD_L_MIN{118, OFFSET_TRRD_L_MIN_START, OFFSET_TRRD_L_MIN_LEN};
+ static constexpr field_t OFFSET_TRRD_S_MIN{119, OFFSET_TRRD_S_MIN_START, OFFSET_TRRD_S_MIN_LEN};
+ static constexpr field_t OFFSET_TRC_MIN{120, OFFSET_TRC_MIN_START, OFFSET_TRC_MIN_LEN};
+ static constexpr field_t OFFSET_TRP_MIN{121, OFFSET_TRP_MIN_START, OFFSET_TRP_MIN_LEN};
+ static constexpr field_t OFFSET_TRCD_MIN{122, OFFSET_TRCD_MIN_START, OFFSET_TRCD_MIN_LEN};
+ static constexpr field_t OFFSET_TAA_MIN{123, OFFSET_TAA_MIN_START, OFFSET_TAA_MIN_LEN};
+ static constexpr field_t OFFSET_TCK_MAX{124, OFFSET_TCK_MAX_START, OFFSET_TCK_MAX_LEN};
+ static constexpr field_t OFFSET_TCK_MIN{125, OFFSET_TCK_MIN_START, OFFSET_TCK_MIN_LEN};
+ static constexpr field_t CRC_LSB{126, CRC_LSB_START, CRC_LSB_LEN};
+ static constexpr field_t CRC_MSB{127, CRC_MSB_START, CRC_MSB_LEN};
+ static constexpr field_t REF_RAW_CARD{130, REF_RAW_CARD_START, REF_RAW_CARD_LEN};
+ static constexpr field_t CONTINUATION_CODES{320, CONTINUATION_CODES_START, CONTINUATION_CODES_LEN};
+ static constexpr field_t LAST_NON_ZERO_BYTE{321, LAST_NON_ZERO_BYTE_START, LAST_NON_ZERO_BYTE_LEN};
+ static constexpr field_t MODULE_MFG_LOCATION{322, MODULE_MFG_LOC_START, MODULE_MFG_LOC_LEN};
+ static constexpr field_t MODULE_MFG_DATE_LSB{323, MODULE_MFG_DATE_START, MODULE_MFG_DATE_LEN};
+ static constexpr field_t MODULE_MFG_DATE_MSB{324, MODULE_MFG_DATE_START, MODULE_MFG_DATE_LEN};
+ static constexpr field_t MODULE_SERIAL_NUM_BYTE1{325, MODULE_SERIAL_NUM_START, MODULE_SERIAL_NUM_LEN};
+ static constexpr field_t MODULE_SERIAL_NUM_BYTE2{326, MODULE_SERIAL_NUM_START, MODULE_SERIAL_NUM_LEN};
+ static constexpr field_t MODULE_SERIAL_NUM_BYTE3{327, MODULE_SERIAL_NUM_START, MODULE_SERIAL_NUM_LEN};
+ static constexpr field_t MODULE_SERIAL_NUM_BYTE4{328, MODULE_SERIAL_NUM_START, MODULE_SERIAL_NUM_LEN};
+ static constexpr field_t MODULE_REV_CODE{349, MODULE_REV_CODE_START, MODULE_REV_CODE_LEN};
+ static constexpr field_t DRAM_MFR_ID_CODE_LSB{350, DRAM_MFR_ID_CODE_START, DRAM_MFR_ID_CODE_LEN};
+ static constexpr field_t DRAM_MFR_ID_CODE_MSB{351, DRAM_MFR_ID_CODE_START, DRAM_MFR_ID_CODE_LEN};
+ static constexpr field_t DRAM_STEPPING{352, DRAM_STEPPING_START, DRAM_STEPPING_LEN};
+};
+
+///
+/// @class fields
+/// @brief DDR4 RDIMM module SPD parameters
+/// @note DDR4, RDIMM_MODULE specialization
+///
+template<>
+class fields<DDR4, RDIMM_MODULE>
+{
+ enum
+ {
+ // Byte 128
+ MODULE_NOM_HEIGHT_START = 3,
+ MODULE_NOM_HEIGHT_LEN = 5,
+ RAW_CARD_EXT_START = 0,
+ RAW_CARD_EXT_LEN = 3,
+
+ // Byte 129
+ FRONT_MODULE_THICKNESS_START = 4,
+ FRONT_MODULE_THICKNESS_LEN = 4,
+ BACK_MODULE_THICKNESS_START = 0,
+ BACK_MODULE_THICKNESS_LEN = 4,
+
+ // Byte 130
+ REF_RAW_CARD_START = 0,
+ REF_RAW_CARD_LEN = 8,
+
+ // Byte 131
+ REGS_USED_START = 6,
+ REGS_USED_LEN = 2,
+ ROWS_OF_DRAMS_START = 4,
+ ROWS_OF_DRAMS_LEN = 2,
+ REGISTER_TYPE_START = 0,
+ REGISTER_TYPE_LEN = 4,
+
+ // Byte 132
+ HEAT_SPREADER_CHAR_START = 1,
+ HEAT_SPREADER_CHAR_LEN = 7,
+ HEAT_SPREADER_SOL_START = 0,
+ HEAT_SPREADER_SOL_LEN = 1,
+
+ // Byte 133
+ CONTINUATION_CODES_START = 0,
+ CONTINUATION_CODES_LEN = 8,
+
+ // Byte 134
+ LAST_NON_ZERO_BYTE_START = 0,
+ LAST_NON_ZERO_BYTE_LEN = 8,
+
+ // Byte 135
+ REGISTER_REV_START = 0,
+ REGISTER_REV_LEN = 8,
+
+ // Byte 136
+ ADDR_MAPPING_START = 7,
+ ADDR_MAPPING_LEN = 1,
+
+ // Byte 137
+ CKE_DRIVER_START = 6,
+ CKE_DRIVER_LEN = 2,
+ ODT_DRIVER_START = 4,
+ ODT_DRIVER_LEN = 2,
+ CA_DRIVER_START = 2,
+ CA_DRIVER_LEN = 2,
+ CS_DRIVER_START = 0,
+ CS_DRIVER_LEN = 2,
+
+ // Byte 138
+ YO_Y2_DRIVER_START = 6,
+ YO_Y2_DRIVER_LEN = 2,
+ Y1_Y3_DRIVER_START = 4,
+ Y1_Y3_DRIVER_LEN = 2,
+ };
+
+ public:
+
+ // First field - SPD byte
+ // Second field - start bit
+ // Third field - bit length
+ static constexpr field_t MODULE_NOMINAL_HEIGHT{128, MODULE_NOM_HEIGHT_START, MODULE_NOM_HEIGHT_LEN};
+ static constexpr field_t RAW_CARD_EXTENSION{128, RAW_CARD_EXT_START, RAW_CARD_EXT_LEN};
+ static constexpr field_t FRONT_MODULE_THICKNESS{129, FRONT_MODULE_THICKNESS_START, FRONT_MODULE_THICKNESS_LEN};
+ static constexpr field_t BACK_MODULE_THICKNESS{129, BACK_MODULE_THICKNESS_START, BACK_MODULE_THICKNESS_LEN};
+ static constexpr field_t REF_RAW_CARD{130, REF_RAW_CARD_START, REF_RAW_CARD_LEN};
+ static constexpr field_t NUM_REGS_USED{131, REGS_USED_START, REGS_USED_LEN};
+ static constexpr field_t ROWS_OF_DRAMS{131, ROWS_OF_DRAMS_START, ROWS_OF_DRAMS_LEN};
+ static constexpr field_t REGISTER_TYPE{131, REGISTER_TYPE_START, REGISTER_TYPE_LEN};
+ static constexpr field_t HEAT_SPREADER_CHAR{132, HEAT_SPREADER_CHAR_START, HEAT_SPREADER_CHAR_LEN};
+ static constexpr field_t HEAT_SPREADER_SOL{132, HEAT_SPREADER_SOL_START, HEAT_SPREADER_SOL_LEN};
+ static constexpr field_t CONTINUATION_CODES{133, CONTINUATION_CODES_START, CONTINUATION_CODES_LEN};
+ static constexpr field_t LAST_NON_ZERO_BYTE{134, LAST_NON_ZERO_BYTE_START, LAST_NON_ZERO_BYTE_LEN};
+ static constexpr field_t REGISTER_REV{135, REGISTER_REV_START, REGISTER_REV_LEN};
+ static constexpr field_t ADDR_MAP_REG_TO_DRAM{136, ADDR_MAPPING_START, ADDR_MAPPING_LEN};
+ static constexpr field_t CKE_DRIVER{137, CKE_DRIVER_START, CKE_DRIVER_LEN};
+ static constexpr field_t ODT_DRIVER{137, ODT_DRIVER_START, ODT_DRIVER_LEN};
+ static constexpr field_t CA_DRIVER{137, CA_DRIVER_START, CA_DRIVER_LEN};
+ static constexpr field_t CS_DRIVER{137, CS_DRIVER_START, CS_DRIVER_LEN};
+ static constexpr field_t YO_Y2_DRIVER{138, YO_Y2_DRIVER_START, YO_Y2_DRIVER_LEN};
+ static constexpr field_t Y1_Y3_DRIVER{138, Y1_Y3_DRIVER_START, Y1_Y3_DRIVER_LEN};
+};
+
+///
+/// @class fields
+/// @brief DDR4 LRDIMM module SPD parameters
+/// @note DDR4, LRDIMM_MODULE specialization
+///
+template<>
+class fields<DDR4, LRDIMM_MODULE>
+{
+ enum
+ {
+ // Byte 128
+ MODULE_NOM_HEIGHT_START = 3,
+ MODULE_NOM_HEIGHT_LEN = 5,
+ RAW_CARD_EXT_START = 0,
+ RAW_CARD_EXT_LEN = 3,
+
+ // Byte 129
+ FRONT_MODULE_THICKNESS_START = 4,
+ FRONT_MODULE_THICKNESS_LEN = 4,
+ BACK_MODULE_THICKNESS_START = 0,
+ BACK_MODULE_THICKNESS_LEN = 4,
+
+ // Byte 130
+ REF_RAW_CARD_START = 0,
+ REF_RAW_CARD_LEN = 8,
+
+ // Byte 131
+ REGS_USED_START = 6,
+ REGS_USED_LEN = 2,
+ ROWS_OF_DRAMS_START = 4,
+ ROWS_OF_DRAMS_LEN = 2,
+ REGISTER_TYPE_START = 0,
+ REGISTER_TYPE_LEN = 4,
+
+ // Byte 132
+ HEAT_SPREADER_CHAR_START = 1,
+ HEAT_SPREADER_CHAR_LEN = 7,
+ HEAT_SPREADER_SOL_START = 0,
+ HEAT_SPREADER_SOL_LEN = 1,
+
+ // Byte 133
+ CONTINUATION_CODES_START = 0,
+ CONTINUATION_CODES_LEN = 8,
+
+ // Byte 134
+ LAST_NON_ZERO_BYTE_START = 0,
+ LAST_NON_ZERO_BYTE_LEN = 8,
+
+ // Byte 135
+ REGISTER_REV_START = 0,
+ REGISTER_REV_LEN = 8,
+
+ // Byte 136
+ ADDR_MAPPING_START = 7,
+ ADDR_MAPPING_LEN = 1,
+
+ // Byte 137
+ CKE_DRIVER_START = 6,
+ CKE_DRIVER_LEN = 2,
+ ODT_DRIVER_START = 4,
+ ODT_DRIVER_LEN = 2,
+ CA_DRIVER_START = 2,
+ CA_DRIVER_LEN = 2,
+ CS_DRIVER_START = 0,
+ CS_DRIVER_LEN = 2,
+
+ // Byte 138
+ YO_Y2_DRIVER_START = 6,
+ YO_Y2_DRIVER_LEN = 2,
+ Y1_Y3_DRIVER_START = 4,
+ Y1_Y3_DRIVER_LEN = 2,
+
+ BCOM_BODT_BCKE_DRIVER_START = 3,
+ BCOM_BODT_BCKE_DRIVER_LEN = 1,
+ BCK_DRIVER_START = 2,
+ BCK_DRIVER_LEN = 1,
+ RCD_SLEW_CNTRL_START = 1,
+ RCD_SLEW_CNTRL_LEN = 1,
+
+ // Byte 139
+ DB_REV_START = 0,
+ DB_REV_LEN = 8,
+
+ // Byte 140
+ VREF_DQ_RANK0_START = 2,
+ VREF_DQ_RANK0_LEN = 6,
+
+ // Byte 141
+ VREF_DQ_RANK1_START = 2,
+ VREF_DQ_RANK1_LEN = 6,
+
+ // Byte 142
+ VREF_DQ_RANK2_START = 2,
+ VREF_DQ_RANK2_LEN = 6,
+
+ // Byte 143
+ VREF_DQ_RANK3_START = 2,
+ VREF_DQ_RANK3_LEN = 6,
+
+ // Byte 144
+ DB_VREF_DQ_START = 0,
+ DB_VREF_DQ_LEN = 8,
+
+ // Byte 145 - 147
+ DB_MDQ_START = 1,
+ DB_MDQ_LEN = 3,
+ DB_MDQ_RTT_START = 5,
+ DB_MDQ_RTT_LEN = 3,
+
+ // Byte 148
+ DRAM_DRIVE_1866_START = 6,
+ DRAM_DRIVE_2400_START = 4,
+ DRAM_DRIVE_3200_START = 2,
+ DRAM_DRIVE_LEN = 2,
+
+ // Byte 149 - 151
+ DRAM_ODT_RTT_NOM_START = 5,
+ DRAM_ODT_RTT_NOM_LEN = 3,
+ DRAM_ODT_RTT_WR_START = 2,
+ DRAM_ODT_RTT_WR_LEN = 3,
+
+ // Bytes 152 - 154
+ DRAM_ODT_RTT_PARK_R01_START = 5,
+ DRAM_ODT_RTT_PARK_R01_LEN = 3,
+ DRAM_ODT_RTT_PARK_R23_START = 2,
+ DRAM_ODT_RTT_PARK_R23_LEN = 3,
+
+ // Byte 155
+ DRAM_VREF_DQ_RANGE_START = 4,
+ DRAM_VREF_DQ_RANGE_LEN = 4,
+ DB_VREF_DQ_RANGE_START = 3,
+ DB_VREF_DQ_RANGE_LEN = 1,
+
+ // Byte 156
+ DB_GAIN_ADJUST_START = 7,
+ DB_GAIN_ADJUST_LEN = 1,
+ DB_DFE_START = 6,
+ DB_DFE_LEN = 1,
+ };
+
+ public:
+
+ // First field - SPD byte
+ // Second field - start bit
+ // Third field - bit length
+ static constexpr field_t MODULE_NOMINAL_HEIGHT{128, MODULE_NOM_HEIGHT_START, MODULE_NOM_HEIGHT_LEN};
+ static constexpr field_t RAW_CARD_EXT{128, RAW_CARD_EXT_START, RAW_CARD_EXT_LEN};
+ static constexpr field_t FRONT_MODULE_THICKNESS{129, FRONT_MODULE_THICKNESS_START, FRONT_MODULE_THICKNESS_LEN};
+ static constexpr field_t BACK_MODULE_THICKNESS{129, BACK_MODULE_THICKNESS_START, BACK_MODULE_THICKNESS_LEN};
+ static constexpr field_t REF_RAW_CARD{130, REF_RAW_CARD_START, REF_RAW_CARD_LEN};
+ static constexpr field_t NUM_REGS_USED{131, REGS_USED_START, REGS_USED_LEN};
+ static constexpr field_t ROWS_OF_DRAMS{131, ROWS_OF_DRAMS_START, ROWS_OF_DRAMS_LEN};
+ static constexpr field_t REGISTER_TYPE{131, REGISTER_TYPE_START, REGISTER_TYPE_LEN};
+ static constexpr field_t HEAT_SPREADER_CHAR{132, HEAT_SPREADER_CHAR_START, HEAT_SPREADER_CHAR_LEN};
+ static constexpr field_t HEAT_SPREADER_SOL{132, HEAT_SPREADER_SOL_START, HEAT_SPREADER_SOL_LEN};
+ static constexpr field_t CONTINUATION_CODES{133, CONTINUATION_CODES_START, CONTINUATION_CODES_LEN};
+ static constexpr field_t LAST_NON_ZERO_BYTE{134, LAST_NON_ZERO_BYTE_START, LAST_NON_ZERO_BYTE_LEN};
+ static constexpr field_t REGISTER_REV{135, REGISTER_REV_START, REGISTER_REV_LEN};
+ static constexpr field_t ADDR_MAP_REG_TO_DRAM{136, ADDR_MAPPING_START, ADDR_MAPPING_LEN};
+ static constexpr field_t CKE_DRIVER{137, CKE_DRIVER_START, CKE_DRIVER_LEN};
+ static constexpr field_t ODT_DRIVER{137, ODT_DRIVER_START, ODT_DRIVER_LEN};
+ static constexpr field_t CA_DRIVER{137, CA_DRIVER_START, CA_DRIVER_LEN};
+ static constexpr field_t CS_DRIVER{137, CS_DRIVER_START, CS_DRIVER_LEN};
+ static constexpr field_t YO_Y2_DRIVER{138, YO_Y2_DRIVER_START, YO_Y2_DRIVER_LEN};
+ static constexpr field_t Y1_Y3_DRIVER{138, Y1_Y3_DRIVER_START, Y1_Y3_DRIVER_LEN};
+ static constexpr field_t DATA_BUFFER_REV{139, DB_REV_START, DB_REV_LEN};
+ static constexpr field_t BCOM_BODT_BCKE_DRIVER{138, BCOM_BODT_BCKE_DRIVER_START, BCOM_BODT_BCKE_DRIVER_LEN};
+ static constexpr field_t BCK_DRIVER{138, BCK_DRIVER_START, BCK_DRIVER_LEN};
+ static constexpr field_t RCD_SLEW_CNTRL{138, RCD_SLEW_CNTRL_START, RCD_SLEW_CNTRL_LEN };
+ static constexpr field_t VREF_DQ_RANK0{140, VREF_DQ_RANK0_START, VREF_DQ_RANK0_LEN};
+ static constexpr field_t VREF_DQ_RANK1{141, VREF_DQ_RANK1_START, VREF_DQ_RANK1_LEN};
+ static constexpr field_t VREF_DQ_RANK2{142, VREF_DQ_RANK2_START, VREF_DQ_RANK2_LEN};
+ static constexpr field_t VREF_DQ_RANK3{143, VREF_DQ_RANK3_START, VREF_DQ_RANK3_LEN};
+ static constexpr field_t DATA_BUFFER_VREF_DQ{144, DB_VREF_DQ_START, DB_VREF_DQ_LEN};
+ static constexpr field_t DB_MDQ_LTE_1866{145, DB_MDQ_START, DB_MDQ_LEN};
+ static constexpr field_t DB_MDQ_LTE_2400{146, DB_MDQ_START, DB_MDQ_LEN};
+ static constexpr field_t DB_MDQ_LTE_3200{147, DB_MDQ_START, DB_MDQ_LEN};
+ static constexpr field_t DB_MDQ_RTT_LTE_1866{145, DB_MDQ_RTT_START, DB_MDQ_RTT_LEN};
+ static constexpr field_t DB_MDQ_RTT_LTE_2400{146, DB_MDQ_RTT_START, DB_MDQ_RTT_LEN};
+ static constexpr field_t DB_MDQ_RTT_LTE_3200{147, DB_MDQ_RTT_START, DB_MDQ_RTT_LEN};
+ static constexpr field_t DRAM_DRIVE_STRENGTH_LTE_1866{148, DRAM_DRIVE_1866_START, DRAM_DRIVE_LEN};
+ static constexpr field_t DRAM_DRIVE_STRENGTH_LTE_2400{148, DRAM_DRIVE_2400_START, DRAM_DRIVE_LEN};
+ static constexpr field_t DRAM_DRIVE_STRENGTH_LTE_3200{148, DRAM_DRIVE_3200_START, DRAM_DRIVE_LEN};
+ static constexpr field_t DRAM_ODT_RTT_NOM_LTE_1866{149, DRAM_ODT_RTT_NOM_START, DRAM_ODT_RTT_NOM_LEN};
+ static constexpr field_t DRAM_ODT_RTT_WR_LTE_1866{149, DRAM_ODT_RTT_WR_START, DRAM_ODT_RTT_WR_LEN};
+ static constexpr field_t DRAM_ODT_RTT_NOM_LTE_2400{150, DRAM_ODT_RTT_NOM_START, DRAM_ODT_RTT_NOM_LEN};
+ static constexpr field_t DRAM_ODT_RTT_WR_LTE_2400{150, DRAM_ODT_RTT_WR_START, DRAM_ODT_RTT_WR_LEN};
+ static constexpr field_t DRAM_ODT_RTT_NOM_LTE_3200{151, DRAM_ODT_RTT_NOM_START, DRAM_ODT_RTT_NOM_LEN};
+ static constexpr field_t DRAM_ODT_RTT_WR_LTE_3200{151, DRAM_ODT_RTT_WR_START, DRAM_ODT_RTT_WR_LEN};
+ static constexpr field_t DRAM_ODT_RTT_PARK_R01_LTE_1866{152, DRAM_ODT_RTT_PARK_R01_START, DRAM_ODT_RTT_PARK_R01_LEN};
+ static constexpr field_t DRAM_ODT_RTT_PARK_R23_LTE_1866{152, DRAM_ODT_RTT_PARK_R23_START, DRAM_ODT_RTT_PARK_R23_LEN};
+ static constexpr field_t DRAM_ODT_RTT_PARK_R01_LTE_2400{153, DRAM_ODT_RTT_PARK_R01_START, DRAM_ODT_RTT_PARK_R01_LEN};
+ static constexpr field_t DRAM_ODT_RTT_PARK_R23_LTE_2400{153, DRAM_ODT_RTT_PARK_R23_START, DRAM_ODT_RTT_PARK_R23_LEN};
+ static constexpr field_t DRAM_ODT_RTT_PARK_R01_LTE_3200{154, DRAM_ODT_RTT_PARK_R01_START, DRAM_ODT_RTT_PARK_R01_LEN};
+ static constexpr field_t DRAM_ODT_RTT_PARK_R23_LTE_3200{154, DRAM_ODT_RTT_PARK_R23_START, DRAM_ODT_RTT_PARK_R23_LEN};
+ static constexpr field_t DRAM_VREF_DQ_RANGE{155, DRAM_VREF_DQ_RANGE_START, DRAM_VREF_DQ_RANGE_LEN};
+ static constexpr field_t DATA_BUFFER_VREF_DQ_RANGE{155, DB_VREF_DQ_RANGE_START, DB_VREF_DQ_RANGE_LEN};
+ static constexpr field_t DATA_BUFFER_GAIN_ADJUST{156, DB_GAIN_ADJUST_START, DB_GAIN_ADJUST_LEN};
+ static constexpr field_t DATA_BUFFER_DFE{156, DB_DFE_START, DB_DFE_LEN};
+};
+
+}// spd
+}// mss
+
+#endif // _MSS_SPD_FIELDS_DDR4_H_
diff --git a/src/import/generic/memory/lib/spd/spd_reader.H b/src/import/generic/memory/lib/spd/spd_reader.H
index f58cbceae..90b9df1da 100644
--- a/src/import/generic/memory/lib/spd/spd_reader.H
+++ b/src/import/generic/memory/lib/spd/spd_reader.H
@@ -22,3 +22,126 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file spd_reader.H
+/// @brief SPD generic API to read SPD byte fields
+///
+
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_SPD_READER_H_
+#define _MSS_SPD_READER_H_
+
+#include <fapi2.H>
+#include <cstdint>
+#include <generic/memory/lib/spd/spd_field.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/spd/spd_traits_ddr4.H>
+#include <generic/memory/lib/spd/spd_checker.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
+namespace mss
+{
+namespace spd
+{
+
+///
+/// @brief Helper function to extract byte information
+/// @tparam F the SPD field to extract
+/// @param[in] i_target the dimm target
+/// @param[in] i_spd_data the SPD data
+/// @param[out] o_value raw value for this SPD field
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template< const field_t& F >
+fapi2::ReturnCode extract_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ uint8_t& o_value)
+{
+ FAPI_ASSERT( F.get_byte() < i_spd_data.size(),
+ fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
+ .set_INDEX(F.get_byte())
+ .set_LIST_SIZE(i_spd_data.size())
+ .set_FUNCTION(EXTRACT_SPD_FLD)
+ .set_TARGET(i_target),
+ "Out of bounds indexing (with %d) on a list of size %d for %s",
+ F.get_byte(),
+ i_spd_data.size(),
+ spd::c_str(i_target));
+
+ {
+ // Extracting desired bits
+ const fapi2::buffer<uint8_t> l_buffer(i_spd_data[F.get_byte()]);
+ l_buffer.extractToRight<F.get_start(), F.get_length()>(o_value);
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%02x.",
+ spd::c_str(i_target),
+ F.get_byte(),
+ o_value);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief SPD reader
+/// @tparam F the SPD field to read
+/// @tparam R the SPD revision
+/// @tparam T data input type
+/// @tparam OT data output type
+/// @tparam TT traits associated with reader, defaulted to readerTraits<F, T>
+/// @param[in] i_target the dimm target
+/// @param[in] i_spd_data the SPD data
+/// @param[out] o_value raw value for this SPD field
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template< const field_t& F, rev R, typename T, typename OT, typename TT = readerTraits<F, R> >
+fapi2::ReturnCode reader( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<T>& i_spd_data,
+ OT& o_value)
+{
+ T l_temp = 0;
+ FAPI_TRY(extract_field<F>(i_target, i_spd_data, l_temp));
+
+ FAPI_DBG("extracted %s value: 0x%02x for %s",
+ TT::FIELD_STR, l_temp, spd::c_str(i_target));
+
+ // Test if retrieved data seems valid
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target,
+ conditional( l_temp,
+ TT::COMPARISON_VAL,
+ typename TT::template COMPARISON_OP<T>() ),
+ F.get_byte(),
+ l_temp) );
+
+ // Output should only change if data check passes
+ o_value = static_cast<OT>(l_temp);
+
+ FAPI_ASSERT( o_value == l_temp,
+ fapi2::MSS_CONVERSION_ERROR()
+ .set_ORIGINAL_VAL(l_temp)
+ .set_CONVERTED_VAL(o_value)
+ .set_TARGET(i_target)
+ .set_FUNCTION(SPD_READER),
+ "Conversion error between original %d to converted %d value for %s",
+ l_temp, o_value, spd::c_str(i_target) );
+
+ FAPI_INF("%s: 0x%02x for %s",
+ TT::FIELD_STR,
+ o_value,
+ spd::c_str(i_target));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}// spd
+}// mss
+
+#endif // _MSS_SPD_READER_H_
diff --git a/src/import/generic/memory/lib/spd/spd_traits.H b/src/import/generic/memory/lib/spd/spd_traits.H
index 656bce7aa..9eb546302 100644
--- a/src/import/generic/memory/lib/spd/spd_traits.H
+++ b/src/import/generic/memory/lib/spd/spd_traits.H
@@ -22,3 +22,167 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+///
+/// @file spd_traits.H
+/// @brief Declaration for assocated traits to reading SPD
+///
+
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_SPD_READER_TRAITS_H_
+#define _MSS_SPD_READER_TRAITS_H_
+
+#include <cstdint>
+#include <functional>
+#include <generic/memory/lib/spd/spd_field.H>
+
+namespace mss
+{
+namespace spd
+{
+
+///
+/// @brief Checks SPD input field against a custom conditional
+/// @tparam T SPD field input type
+/// @tparam F Callable object type
+/// @param[in] i_spd_field Extracted SPD field
+/// @param[in] i_comparison_val value we are comparing against
+/// @param[in] i_op comparison operator function object
+/// @return boolean true or false
+///
+template < typename T, typename F >
+bool conditional(const T i_spd_field,
+ const size_t i_comparison_val,
+ const F i_op)
+{
+ return i_op(i_spd_field, i_comparison_val);
+}
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam F holds SPD field info
+/// @tparam R the revision of the SPD field
+/// @tparam B boolean required to activate trait class - defaulted to true_type
+///
+template< const field_t& F, rev R, typename B = std::true_type >
+class readerTraits;
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note REVISION field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < init_fields::REVISION, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "SPD Revision";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DEVICE_TYPE field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits< init_fields::DEVICE_TYPE, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x11; ///< Largest valid SPD encoding
+ static constexpr const char* FIELD_STR = "DRAM Device Type";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BASE_MODULE field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < init_fields::BASE_MODULE, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1101;
+ static constexpr const char* FIELD_STR = "Base Module";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note HYBRID field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits< init_fields::HYBRID, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 1;
+ static constexpr const char* FIELD_STR = "Hybrid";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note HYBRID_MEDIA field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits< init_fields::HYBRID_MEDIA, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 1;
+ static constexpr const char* FIELD_STR = "Hybrid Media";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note REF_RAW_CARD field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits< init_fields::REF_RAW_CARD, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 1;
+ static constexpr const char* FIELD_STR = "Reference Raw Card";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+}// spd
+}// mss
+
+#endif //_MSS_SPD_READER_TRAITS_H_
diff --git a/src/import/generic/memory/lib/spd/spd_traits_ddr4.H b/src/import/generic/memory/lib/spd/spd_traits_ddr4.H
index ef6caf462..5d2323bba 100644
--- a/src/import/generic/memory/lib/spd/spd_traits_ddr4.H
+++ b/src/import/generic/memory/lib/spd/spd_traits_ddr4.H
@@ -22,3 +22,3767 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file spd_traits_ddr4.H
+/// @brief Assocated traits for reading DDR4 SPD fields
+///
+
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_SPD_TRAITS_DDR4_H_
+#define _MSS_SPD_TRAITS_DDR4_H_
+
+#include <cstdint>
+#include <generic/memory/lib/spd/spd_fields_ddr4.H>
+#include <generic/memory/lib/spd/spd_traits.H>
+
+namespace mss
+{
+namespace spd
+{
+
+// Note: The 3rd template parameter is a compile-time conditional
+// to activate trait class based on a valid SPD revision.
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BYTES_USED field partial specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template<rev R>
+class readerTraits < fields<DDR4, BASE_CNFG>::BYTES_USED, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b0100; ///< Largest valid SPD encoding
+ static constexpr const char* FIELD_STR = "SPD Bytes Used";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TOTAL_BYTES field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template<rev R>
+class readerTraits < fields<DDR4, BASE_CNFG>::TOTAL_BYTES, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b010; ///< Largest valid SPD encoding
+ static constexpr const char* FIELD_STR = "SPD Bytes Total";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note REVISION field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::REVISION, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Encoding Level";
+
+ template <typename T>
+ using COMPARISON_OP = std::less<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DEVICE_TYPE field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::DEVICE_TYPE, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xC; ///< Largest valid SPD encoding
+ static constexpr const char* FIELD_STR = "DRAM Device Type";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DEVICE_TYPE field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::DEVICE_TYPE, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x11; ///< Largest valid SPD encoding
+ static constexpr const char* FIELD_STR = "DRAM Device Type";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BASE_MODULE field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::BASE_MODULE, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1101;
+ static constexpr const char* FIELD_STR = "Base Module";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note HYBRID field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Hybrid";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note HYBRID field specialization
+/// @note valid for rev >= 1.1 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1;
+ static constexpr const char* FIELD_STR = "Hybrid";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note HYBRID_MEDIA field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID_MEDIA, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Hybrid Media";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note HYBRID_MEDIA field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID_MEDIA, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1;
+ static constexpr const char* FIELD_STR = "Hybrid Media";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BANK_GROUP_BITS field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::BANK_GROUP_BITS, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Bank Group";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BANKS_ADDR_BITS field specialization
+/// @note rev 1.0 specialization
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::BANKS_ADDR_BITS, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "Bank Address Bits";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SDRAM_CAPACITY field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::SDRAM_CAPACITY, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b0111;
+ static constexpr const char* FIELD_STR = "SDRAM capacity";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SDRAM_CAPACITY, field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::SDRAM_CAPACITY, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1001;
+ static constexpr const char* FIELD_STR = "SDRAM Capacity";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note COL_ADDR_BITS field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::COL_ADDR_BITS, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b011;
+ static constexpr const char* FIELD_STR = "Column Address Bits";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note ROW_ADDR_BITS field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::ROW_ADDR_BITS, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b110;
+ static constexpr const char* FIELD_STR = "Row Address Bits";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PRIM_SIGNAL_LOADING field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::PRIM_SIGNAL_LOADING, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Primary Signal Loading";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PRIM_DIE_COUNT field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::PRIM_DIE_COUNT, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Primary Die Count";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PRIM_PACKAGE_TYPE field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::PRIM_PACKAGE_TYPE, R,
+ std::integral_constant<bool, (R >= rev::V1_0)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Primary Package Type";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MAC field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MAC, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1000;
+ static constexpr const char* FIELD_STR = "Maximum Activate Count (MAC)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TMAW field specialization
+/// @note rev 1.0 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::TMAW, R,
+ std::integral_constant<bool, (R >= rev::V1_0)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Maximum Activate Window (TMAW)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PPR field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::PPR, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "Post package repair (PPR)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SOFT_PPR field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::SOFT_PPR, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Soft post package repair (SPPR)";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SOFT_PPR field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::SOFT_PPR, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "Soft post package repair (SPPR)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SEC_SIGNAL_LOADING field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::SEC_SIGNAL_LOADING, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Secondary Signal Loading";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SEC_SIGNAL_LOADING field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::SEC_SIGNAL_LOADING, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Secondary Signal Loading";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SEC_DENSITY_RATIO field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DENSITY_RATIO, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Secondary DRAM density ratio";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SEC_DENSITY_RATIO field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DENSITY_RATIO, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Secondary DRAM density ratio";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SEC_DIE_COUNT field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DIE_COUNT, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Secondary Die Count";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SEC_DIE_COUNT field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DIE_COUNT, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Secondary Die Count";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SEC_PACKAGE_TYPE field specialization
+/// @note rev 1.0 specialization
+///
+template< >
+class readerTraits< fields<DDR4, BASE_CNFG>::SEC_PACKAGE_TYPE, V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Secondary Package Type";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note SEC_PACKAGE_TYPE field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::SEC_PACKAGE_TYPE, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Secondary Package Type";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OPERABLE_FLD field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OPERABLE_FLD, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Operable nominal voltage";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note ENDURANT_FLD field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::ENDURANT_FLD, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Endurant nominal voltage";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note SDRAM_WIDTH field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::SDRAM_WIDTH, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b011;
+ static constexpr const char* FIELD_STR = "Device Width";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note PACKAGE_RANKS field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::PACKAGE_RANKS, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Package Ranks per DIMM";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note PACKAGE_RANKS field specialization
+/// @note valid for rev >= 1.1 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::PACKAGE_RANKS, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Package Ranks per DIMM";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note RANK_MIX field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::RANK_MIX, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Rank Mix";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note RANK_MIX field specialization
+/// @note rev 1.1 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::RANK_MIX, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Rank Mix";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BUS_WIDTH field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::BUS_WIDTH, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b011;
+ static constexpr const char* FIELD_STR = "Primary Bus Width";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BUS_EXT_WIDTH field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::BUS_EXT_WIDTH, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b001;
+ static constexpr const char* FIELD_STR = "Bus Width Extension (bits)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note THERM_SENSOR field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::THERM_SENSOR, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Thermal Sensor";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note EXTENDED_MODULE_TYPE field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::EXTENDED_MODULE_TYPE, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Extended Base Module Type";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MED_TIMEBASE field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MEDIUM_TIMEBASE, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Medium Timebase";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note FINE_TIMEBASE field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::FINE_TIMEBASE, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Fine Timebase";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TCK_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TCK_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "tCKmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TCK_MAX field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TCK_MAX, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "tCKmax in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CL_FIRST_BYTE field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::CL_FIRST_BYTE, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "CAS latencies supported - First byte";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CL_SECOND_BYTE field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::CL_SECOND_BYTE, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "CAS latencies supported - Second byte";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CL_THIRD_BYTE field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::CL_THIRD_BYTE, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x03;
+ static constexpr const char* FIELD_STR = "CAS latencies supported - Third byte";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CL_THIRD_BYTE field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::CL_THIRD_BYTE, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "CAS latencies supported - Third byte";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CL_FOURTH_BYTE field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, BASE_CNFG>::CL_FOURTH_BYTE, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "CAS latencies supported - Fourth byte";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CL_FOURTH_BYTE field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, BASE_CNFG>::CL_FOURTH_BYTE, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xBF;
+ static constexpr const char* FIELD_STR = "CAS latencies supported - Fourth byte";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TAA_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TAA_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tAAmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRCD_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRCD_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRCDmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRP_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRP_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRPmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRASMIN_MSN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRASMIN_MSN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRASmin (most significant nibble) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRASMIN_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRASMIN_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRASmin (least significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRCMIN_MSN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRCMIN_MSN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRCmin (most significant nibble) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRCMIN_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRCmin (least significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRFC1MIN_MSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRFC1MIN_MSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRFC1min (most significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRFC1MIN_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRFC1MIN_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRFC1min (least significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRFC2MIN_MSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRFC2MIN_MSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRFC2min (most significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRFC2MIN_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRFC2MIN_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRFC2min (least significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRFC4MIN_MSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRFC4MIN_MSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRFC4min (most significant byte) in MTB";
+
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRFC4MIN_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRFC4MIN_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRFC4min (least significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TFAWMIN_MSN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TFAWMIN_MSN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "Minimum Four Activate Window Delay Time (tFAWmin) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TFAWMIN_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TFAWMIN_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "Minimum Four Activate Window Delay Time (tFAWmin) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRRD_S_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRRD_S_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRRD_Smin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TRRD_L_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TRRD_L_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tRRD_Lmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TCCD_L_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TCCD_L_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tCCD_Lmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater<T>;
+
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TWRMIN_MSN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TWRMIN_MSN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tWRmin (most significant nibble) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TWRMIN_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TWRMIN_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tWRmin (least significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TWTRMIN_S_MSN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_S_MSN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tWTR_Smin (most significant nibble) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TWTRMIN_S_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_S_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tWTR_Smin (least significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TWTRMIN_L_MSN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_L_MSN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tWTR_Lmin (most significant nibble) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note TWTRMIN_L_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_L_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "tWTR_Lmin (least significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OFFSET_TCCD_L_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCCD_L_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+
+ static constexpr const char* FIELD_STR = "Fine Offset tCCD_Lmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OFFSET_TRRD_L_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRRD_L_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+
+ static constexpr const char* FIELD_STR = "Fine Offset for tRRD_Lmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OFFSET_TRRD_S_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRRD_S_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+
+ static constexpr const char* FIELD_STR = "Fine Offset for tRRD_Smin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OFFSET_TRC_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRC_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Fine Offset for tRCmin (least significant byte) in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OFFSET_TRP_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRP_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+
+ static constexpr const char* FIELD_STR = "Fine Offset for tRPmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OFFSET_TAA_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TAA_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Fine Offset for tAAmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OFFSET_TRCD_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRCD_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Fine Offset for tRCDmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OFFSET_TCK_MIN field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCK_MIN, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Fine Offset for tCKmin in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note OFFSET_TCK_MAX field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCK_MAX, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Fine Offset for tCKmax in MTB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CRC_MSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::CRC_MSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "CRC (most significant byte) for base config";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CRC_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::CRC_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "CRC (least significant byte) for base config";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CONTINUATION_CODES field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::CONTINUATION_CODES, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x89;
+ static constexpr const char* FIELD_STR = "Number of continuation codes, module manufacturer";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note LAST_NON_ZERO_BYTE field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::LAST_NON_ZERO_BYTE, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Last non-zero byte";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_MFG_LOCATION field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_LOCATION, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Module Manufacturing Location";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_MFG_DATE_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_DATE_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Odd parity for num of continuation codes, module manufacturer";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_MFG_DATE_MSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_DATE_MSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Odd parity for num of continuation codes, module manufacturer";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_SERIAL_NUM_BYTE1 field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE1, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Module Serial Number byte 1";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_SERIAL_NUM_BYTE2 field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE2, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Module Serial Number byte 2";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_SERIAL_NUM_BYTE3 field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE3, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Module Serial Number byte 3";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_SERIAL_NUM_BYTE4 field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE4, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Module Serial Number byte 4";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_REV_CODE field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_REV_CODE, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Module Revision Code";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_MFR_ID_CODE_LSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_MFR_ID_CODE_LSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x89;
+ static constexpr const char* FIELD_STR = "DRAM manufacturer ID code, LSB";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_MFR_ID_CODE_MSB field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_MFR_ID_CODE_MSB, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "DRAM manufacturer ID code, MSB";
+
+ template <typename T>
+ using COMPARISON_OP = std::not_equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_STEPPING field specialization
+/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_STEPPING, R,
+ std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "DRAM stepping";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_NOMINAL_HEIGHT field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::MODULE_NOMINAL_HEIGHT, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11111;
+
+ static constexpr const char* FIELD_STR = "Module Nominal Height";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note FRONT_MODULE_THICKNESS field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::FRONT_MODULE_THICKNESS, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1111;
+
+ static constexpr const char* FIELD_STR = "Front Module Max Thickness";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BACK_MODULE_THICKNESS field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::BACK_MODULE_THICKNESS, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1111;
+ static constexpr const char* FIELD_STR = "Back Module Max Thickness";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note REF_RAW_CARD field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::REF_RAW_CARD, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Reference Raw Card";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note NUM_REGS_USED field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::NUM_REGS_USED, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Number of registers used";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note ROWS_OF_DRAMS field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::ROWS_OF_DRAMS, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Number of rows of DRAMs";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note REGISTER_TYPE field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::REGISTER_TYPE, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b0001;
+ static constexpr const char* FIELD_STR = "Register Type";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note HEAT_SPREADER_CHAR field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::HEAT_SPREADER_CHAR, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Heat spreader thermal characteristics";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note HEAT_SPREADER_SOL field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::HEAT_SPREADER_SOL, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Heat spreader solution";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CONTINUATION_CODES field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::CONTINUATION_CODES, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x89; // JEP106AS
+ static constexpr const char* FIELD_STR = "Number of continuation codes";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note LAST_NON_ZERO_BYTE field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::LAST_NON_ZERO_BYTE, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Last non-zero byte";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note REGISTER_REV field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::REGISTER_REV, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Register revision number";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note ADDR_MAP_REG_TO_DRAM field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::ADDR_MAP_REG_TO_DRAM, R,
+
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Address mapping from register to DRAM";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CKE_DRIVER field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template<>
+class readerTraits< fields<DDR4, RDIMM_MODULE>::CKE_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Register Output Driver for CKE";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CKE_DRIVER field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::CKE_DRIVER, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for CKE";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note ODT_DRIVER field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template<>
+class readerTraits< fields<DDR4, RDIMM_MODULE>::ODT_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Register Output Driver for ODT";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note ODT_DRIVER field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::ODT_DRIVER, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for ODT";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CA_DRIVER field specialization
+/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, RDIMM_MODULE>::CA_DRIVER, R,
+ std::integral_constant<bool, (R <= rev::RDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for command/address (CA)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CS_DRIVER field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, RDIMM_MODULE>::CS_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Register Output Driver for Chip Select (CS)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CS_DRIVER field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, RDIMM_MODULE>::CS_DRIVER, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for Chip Select (CS)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note YO_Y2_DRIVER field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, RDIMM_MODULE>::YO_Y2_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Register Output Driver for clock (Y0,Y2)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note YO_Y2_DRIVER field specialization
+/// @note rev 1.1 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, RDIMM_MODULE>::YO_Y2_DRIVER, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for clock (Y0,Y2)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note Y1_Y3_DRIVER field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, RDIMM_MODULE>::Y1_Y3_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Register Output Driver for clock (Y1,Y3)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note Y1_Y3_DRIVER field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, RDIMM_MODULE>::Y1_Y3_DRIVER, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for clock (Y1,Y3)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note MODULE_NOMINAL_HEIGHT field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::MODULE_NOMINAL_HEIGHT, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11111;
+ static constexpr const char* FIELD_STR = "Module Nominal Height";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note RAW_CARD_EXT field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::RAW_CARD_EXT, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Raw Card Extension";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note FRONT_MODULE_THICKNESS field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::FRONT_MODULE_THICKNESS, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1111;
+ static constexpr const char* FIELD_STR = "Front Module Max Thickness";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BACK_MODULE_THICKNESS field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::BACK_MODULE_THICKNESS, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1111;
+ static constexpr const char* FIELD_STR = "Back Module Max Thickness";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note REF_RAW_CARD field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::REF_RAW_CARD, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Reference Raw Card";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note NUM_REGS_USED field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::NUM_REGS_USED, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "Number of registers used";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note ROWS_OF_DRAMS field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::ROWS_OF_DRAMS, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Number of rows of DRAMs";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note REGISTER_TYPE field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::REGISTER_TYPE, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b0001;
+ static constexpr const char* FIELD_STR = "Register Type";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note HEAT_SPREADER_SOL field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::HEAT_SPREADER_SOL, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Heat spreader solution";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CONTINUATION_CODES field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::CONTINUATION_CODES, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x89; // JEP106AS
+ static constexpr const char* FIELD_STR = "Number of continuation codes";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note LAST_NON_ZERO_BYTE field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::LAST_NON_ZERO_BYTE, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Last non-zero byte";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note REGISTER_REV field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::REGISTER_REV, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Register revision number";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note ADDR_MAP_REG_TO_DRAM field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::ADDR_MAP_REG_TO_DRAM, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Address mapping from register to DRAM";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CKE_DRIVER field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::CKE_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+
+ static constexpr const char* FIELD_STR = "Register Output Driver for CKE";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CKE_DRIVER field specialization
+/// @note valid for rev >= 1.1 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::CKE_DRIVER, R,
+ std::integral_constant<bool, R >= rev::V1_1 > >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for CKE";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note ODT_DRIVER field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::ODT_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Register Output Driver for ODT";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note ODT_DRIVER field specialization
+/// @note valid for rev >= 1.1 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::ODT_DRIVER, R,
+ std::integral_constant<bool, R >= rev::V1_1 > >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for ODT";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CA_DRIVER field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::CA_DRIVER, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for command/address (CA)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CS_DRIVER field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::CS_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Register Output Driver for Chip Select (CS)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note CS_DRIVER field specialization
+/// @note valid for rev >= 1.1 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::CS_DRIVER, R,
+ std::integral_constant<bool, R >= rev::V1_1 > >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+
+ static constexpr const char* FIELD_STR = "Register Output Driver for Chip Select (CS)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note YO_Y2_DRIVER field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::YO_Y2_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Register Output Driver for clock (Y0,Y2)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note YO_Y2_DRIVER field specialization
+/// @note valid for rev >= 1.1 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::YO_Y2_DRIVER, R,
+ std::integral_constant<bool, R >= rev::V1_1> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for clock (Y0,Y2)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note Y1_Y3_DRIVER field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::Y1_Y3_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b10;
+ static constexpr const char* FIELD_STR = "Register Output Driver for clock (Y1,Y3)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note Y1_Y3_DRIVER field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::Y1_Y3_DRIVER, R,
+ std::integral_constant<bool, R >= rev::V1_1> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b11;
+ static constexpr const char* FIELD_STR = "Register Output Driver for clock (Y1,Y3)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note BCOM_BODT_BCKE_DRIVER, field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCOM_BODT_BCKE_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Register Output Driver for data buffer control (BCOM, BODT, BCKE)";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note BCOM_BODT_BCKE_DRIVER, field specialization
+/// @note valid for rev >= 1.1 specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCOM_BODT_BCKE_DRIVER, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 1;
+ static constexpr const char* FIELD_STR = "Register Output Driver for data buffer control (BCOM, BODT, BCKE)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note BCK_DRIVER field specialization
+/// @note rev 1.0 specialization
+///
+template<>
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCK_DRIVER, rev::V1_0 >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Register Output Driver for data buffer control (BCK)";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note BCK_DRIVER field specialization
+/// @note valid for rev >= 1.1
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCK_DRIVER, R,
+ std::integral_constant<bool, (R >= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 1;
+ static constexpr const char* FIELD_STR = "Register Output Driver for data buffer control (BCK)";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note RCD_SLEW_CNTRL field specialization
+/// @note rev 1.0 & 1.1 specialization
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::RCD_SLEW_CNTRL, R,
+ std::integral_constant<bool, (R <= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "RCD output slew rate control";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note RCD_SLEW_CNTRL field specialization
+/// @note valid for rev >= 1.2
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::RCD_SLEW_CNTRL, R,
+ std::integral_constant<bool, (R >= rev::V1_2)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 1;
+ static constexpr const char* FIELD_STR = "RCD output slew rate control";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DATA_BUFFER_REV field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_REV, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0xFF;
+ static constexpr const char* FIELD_STR = "Data buffer revision";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note VREF_DQ_RANK0 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK0, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b110010;
+ static constexpr const char* FIELD_STR = "DRAM VrefDQ for Package Rank 0";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note VREF_DQ_RANK1 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK1, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b110010;
+ static constexpr const char* FIELD_STR = "DRAM VrefDQ for Package Rank 1";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note VREF_DQ_RANK2 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK2, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b110010;
+ static constexpr const char* FIELD_STR = "DRAM VrefDQ for Package Rank 2";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note VREF_DQ_RANK3 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK3, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b110010;
+ static constexpr const char* FIELD_STR = "DRAM VrefDQ for Package Rank 3";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DATA_BUFFER_VREF_DQ field specialization
+/// @note rev 1.0 specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ, R,
+
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b110010;
+ static constexpr const char* FIELD_STR = "Data Buffer VrefDQ for DRAM Interface";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DB_MDQ_LTE_1866 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_1866, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Data Buffer MDQ Drive Strength for data rate <= 1866";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DB_MDQ_LTE_2400 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_2400, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Data Buffer MDQ Drive Strength for 1866 < data rate <= 2400";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DB_MDQ_LTE_3200 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_3200, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Data Buffer MDQ Drive Strength for 2400 < data rate <=3200";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DB_MDQ_RTT_LTE_1866 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_1866, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Data Buffer MDQ RTT for data rate <= 1866";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DB_MDQ_RTT_LTE_2400 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_2400, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Data Buffer MDQ RTT for 1866 < data rate <= 2400";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DB_MDQ_RTT_LTE_3200 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_3200, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "Data Buffer MDQ RTT for 2400 < data rate <=3200";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_DRIVE_STRENGTH_LTE_1866 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_1866, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "DRAM Drive Strength for data rates <= 1866";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_DRIVE_STRENGTH_LTE_2400 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_2400, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "DRAM Drive Strength for 1866 < data rates <= 2400";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_DRIVE_STRENGTH_LTE_3200 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_3200, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "DRAM Drive Strength for 2400 < data rates <= 3200";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_NOM_LTE_1866 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_1866, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_NOM for data rates <= 1866";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_NOM_LTE_2400 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_2400, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_NOM for 1866 < data rates <= 2400";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_NOM_LTE_3200 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_3200, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b111;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_NOM for 2400 < data rates <= 3200";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_WR_LTE_1866 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_1866, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b100;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_WR for data rates <= 1866";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_WR_LTE_2400 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_2400, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b100;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_WR for 1866 < data rates <= 2400";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_WR_LTE_3200 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_3200, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b100;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_WR for 2400 < data rates <= 3200";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_PARK_R01_LTE_1866 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_1866, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_PARK, package rank 0, 1 for data rates <= 1866";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_PARK_R01_LTE_2400 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_2400, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_PARK, package rank 0, 1 for 1866 < data rates <= 2400";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_PARK_R01_LTE_3200 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_3200, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_PARK, package rank 0, 1 for 2400 < data rates <= 3200";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_PARK_R23_LTE_1866 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_1866, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_PARK, package rank 2, 3 for data rates <= 1866";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_PARK_R23_LTE_2400 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_2400, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_PARK, package rank 2, 3 for 1866 < data rates <= 2400";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_ODT_RTT_PARK_R23_LTE_3200 field specialization
+/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev)
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_3200, R,
+ std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "DRAM ODT RTT_PARK, package rank 2, 3 for 2400 < data rates <= 3200";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note DRAM_VREF_DQ_RANGE field specialization
+/// @note rev 1.0 & 1.1 specialization
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_VREF_DQ_RANGE, R,
+ std::integral_constant<bool, (R <= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1111;
+ static constexpr const char* FIELD_STR = "VrefDQ range for DRAM interface range";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note DRAM_VREF_DQ_RANGE field specialization
+/// @note rev 1.2+ specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::DRAM_VREF_DQ_RANGE, R,
+ std::integral_constant<bool, (R >= rev::V1_2)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1111;
+ static constexpr const char* FIELD_STR = "VrefDQ range for DRAM interface range";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note DATA_BUFFER_VREF_DQ field specialization
+/// @note rev 1.0 & 1.1 specialization
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ_RANGE, R,
+ std::integral_constant<bool, (R <= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Data Buffer VrefDQ range for DRAM interface range";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note DATA_BUFFER_VREF_DQ field specialization
+/// @note rev 1.2+ specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ_RANGE, R,
+ std::integral_constant<bool, (R >= rev::V1_2)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b1;
+ static constexpr const char* FIELD_STR = "Data Buffer VrefDQ range for DRAM interface range";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note DATA_BUFFER_DFE field specialization
+/// @note rev 1.0 & 1.1 specialization
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_DFE, R,
+ std::integral_constant<bool, (R <= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0;
+ static constexpr const char* FIELD_STR = "Data Buffer DFE";
+
+ template <typename T>
+ using COMPARISON_OP = std::equal_to<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note DATA_BUFFER_DFE field specialization
+/// @note rev 1.2+ specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_DFE, R,
+ std::integral_constant<bool, (R >= rev::V1_2)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0b01;
+ static constexpr const char* FIELD_STR = "Data Buffer DFE";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note DATA_BUFFER_GAIN_ADJUST field specialization
+/// @note rev 1.0 & 1.1 specialization
+///
+template< rev R >
+class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_GAIN_ADJUST, R,
+ std::integral_constant<bool, (R <= rev::V1_1)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 1;
+ static constexpr const char* FIELD_STR = "Data Buffer Gain Adjust";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @note DATA_BUFFER_GAIN_ADJUST field specialization
+/// @note rev 1.2+ specialization
+///
+template< rev R >
+class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_GAIN_ADJUST, R,
+ std::integral_constant<bool, (R >= rev::V1_2)> >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 1;
+ static constexpr const char* FIELD_STR = "Data Buffer Gain Adjust";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+}// spd
+}// mss
+
+#endif //_MSS_SPD_TRAITS_DDR4_H_
OpenPOWER on IntegriCloud