summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C5713
1 files changed, 3140 insertions, 2573 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C
index d215773a0..00c4c6419 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_decoder.C
@@ -7,7 +7,7 @@
/* */
/* EKB Project */
/* */
-/* COPYRIGHT 2015 */
+/* COPYRIGHT 2015,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -17,6 +17,7 @@
/* */
/* IBM_PROLOG_END_TAG */
+
///
/// @file spd_decoder.C
/// @brief SPD decoder definitions
@@ -28,8 +29,9 @@
// *HWP Consumed by: HB:FSP
#include <fapi2.H>
-#include "../mss.H"
+#include <mss.H>
#include "../utils/conversions.H"
+#include "../utils/find.H"
#include "spd_decoder.H"
using fapi2::TARGET_TYPE_MCBIST;
@@ -43,7 +45,7 @@ namespace mss
namespace spd
{
-// Note: IBM's implementation of std::maps are not thread safe
+// Note: IBM's implementation of std::map is not thread safe
// =========================================================
// Byte 0 maps
@@ -51,31 +53,22 @@ namespace spd
// Page 14
// DDR4 SPD Document Release 3
// Byte 0 (0x000): Number of Bytes Used / Number of Bytes in SPD Device
-
-static const uint16_t bytes_used_map[] =
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint16_t> > BYTES_USED_MAP =
{
- // Shifting index by 1 first since first key value is undefined
- // Key values < 1 and > 3 aren't supported or reserved
-
- // Undefined
- 128,
- 256,
- 384,
- 512,
- //...
- // All other bits reserved
+ //{key byte, number of used bytes}
+ {1, 128},
+ {2, 256},
+ {3, 384},
+ {4, 512}
};
-static const uint16_t bytes_total_map[] =
-{
- // Shifting index by 1 first since first key value is undefined
- // Key values < 1 and > 2 aren't supported or reserved
- // Undefined
- 256,
- 512,
- //...
- // All other bits reserved
+static const std::vector<std::pair<uint8_t, uint16_t> > BYTES_TOTAL_MAP =
+{
+ //{key byte, number of total bytes}
+ {1, 256},
+ {2, 512}
};
// =========================================================
@@ -84,28 +77,13 @@ static const uint16_t bytes_total_map[] =
// Page 16
// DDR4 SPD Document Release 3
// Byte 2 (0x002): Key Byte / DRAM Device Type
-
-static const uint8_t dram_gen_map[] =
-{
- // Initial and ending index values are not supported or reserved
- // Shifting index by 11 since initial dram gen types aren't supported (by IBM)
- // Key values < 12 and > 13 are not supported or reserved
-
- // Reserved
- // Fast page mode is not supported
- // EDO is not supported
- // Pipelined Nibbleis not supported
- // SDRAM
- // ROM is not supported
- // DDR SGRAM is not supported
- // DDR SDRAM is not supported
- // DDR2 SDRAM is not supported
- // DDR2 SDRAM FB-DIMM is not supported
- // DDR2 SDRAM FB-DIMM PROBE is not supported
- fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR3,
- fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4,
- //...
- // All other bits reserved
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > DRAM_GEN_MAP =
+{
+ //{key value, dram gen}
+ {0x0B, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR3},
+ {0x0C, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4}
+ // Other key bytes reserved or not supported
};
// =========================================================
@@ -114,30 +92,27 @@ static const uint8_t dram_gen_map[] =
// Page 17
// DDR4 SPD Document Release 3
// Byte 3 (0x003): Key Byte / Module Type
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > BASE_MODULE_TYPE_MAP =
+{
+ //{key byte, dimm type}
+ {1, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM},
+ {2, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM},
+ {4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM}
+};
-static const uint8_t base_module_type_map[] =
-{
-
- // Initial and ending index values are not supported or reserved
- // Index shifted by 1 since first module type isn't supported (by IBM)
- // Key values < 1 and > 4 are not supported or reserved
-
- // Extending DIMM not supported
- fapi2::ENUM_ATTR_SPD_MODULE_TYPE_RDIMM,
- fapi2::ENUM_ATTR_SPD_MODULE_TYPE_UDIMM,
- fapi2::ENUM_ATTR_SPD_MODULE_TYPE_SO_DIMM,
- fapi2::ENUM_ATTR_SPD_MODULE_TYPE_LRDIMM,
- // Mini-RDIMM not supported
- // Mini-UDIMM not supported
- // Reserved
- // 72b-SO-RDIMM not supported
- // 72b-SO-UDIMM not supported
- // Reserved
- // Reserved
- // 16b-SO-DIMM
- // 32b-SO-DIMM
- // Reserved
- // Reserved
+static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MEDIA_MAP =
+{
+ //{key, value}
+ {0, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE},
+ {1, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM}
+};
+
+static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MAP =
+{
+ //{key byte, value}
+ {0, fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID},
+ {1, fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID}
};
// =========================================================
@@ -146,74 +121,62 @@ static const uint8_t base_module_type_map[] =
// Page 18
// DDR4 SPD Document Release 3
// Byte 4 (0x004): SDRAM Density and Banks
-
-static const uint8_t sdram_capacity_map[] =
-{
- // Initial and ending index values are not supported or reserved
- // Index shifted by 2 since first module type isn't supported (by IBM)
- // Key values < 2 and > 9 are not supported or reserved
-
- // 256 Mbs is not supported
- // 512 Mbs is not supported
- // // Units (Gigabits)
- 1, // Gb
- 2, // Gb
- 4, // Gb
- 8, // Gb
- 16, // Gb
- 32, // Gb
- 12, // Gb
- 24, // Gb
- //...
- //All others reserved
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > SDRAM_DENSITY_MAP =
+{
+ // {key byte, capacity in GBs}
+ {2, 1},
+ {3, 2},
+ {4, 4},
+ {5, 8},
+ {6, 16},
+ {7, 32},
+ {8, 12},
+ {12, 24}
};
-static const uint8_t sdram_banks_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > BANK_ADDR_BITS_MAP =
{
- // Key values > 1 are not supported or reserved
-
- 4, // banks address bits (2 address bits)
- 8, // banks address bits (3 address bits)
- //...
- // All others Reserved
+ // {key byte, number of bank address bits}
+ {0, 2},
+ {1, 3}
};
-static const uint8_t sdram_bankgroups_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > BANK_GROUP_BITS_MAP =
{
- // Key values > 2 are not supported or reserved
-
- 0, // No bank groups (0 bank group bits)
- 2, // 2 bank groups (1 bank group bit)
- 4, // 4 bank groups (2 bank group bits)
- //Reserved
+ // {key byte, number of bank groups bits}
+ {0, 0},
+ {1, 1},
+ {2, 2}
};
+
// =========================================================
// Byte 5 maps
// Item JC-45-2220.01x
// Page 18
// DDR4 SPD Document Release 3
// Byte 5 (0x005): SDRAM Addressing
-
-static const uint8_t column_address_map[] =
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > COLUMN_ADDRESS_BITS_MAP =
{
- 9, // Column address bits 000
- 10, // Column address bits 001
- 11, // Column address bits 010
- 12, // Column address bits 011
- // All others reserved
+ //{key byte,col address bits}
+ {0, 9},
+ {1, 10},
+ {2, 11},
+ {3, 12}
};
-static const uint8_t row_address_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > ROW_ADDRESS_BITS_MAP =
{
- 12, // Row address bits 000
- 13, // Row address bits 001
- 14, // Row address bits 010
- 15, // Row address bits 011
- 16, // Row address bits 100
- 17, // Row address bits 101
- 18, // Row address bits 110
- // All others reserved
+ //{key byte,row address bits}
+ {0, 12},
+ {1, 13},
+ {2, 14},
+ {3, 15},
+ {4, 16},
+ {5, 17},
+ {6, 18}
};
// =========================================================
@@ -222,28 +185,34 @@ static const uint8_t row_address_map[] =
// Page 19
// DDR4 SPD Document Release 3
// Byte 6 (0x006): Primary SDRAM Package Type
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_SIGNAL_LOADING_MAP =
+{
+ // {key byte, signal loading}
+ {0, UNSPECIFIED},
+ {1, MULTI_LOAD_STACK},
+ {2, SINGLE_LOAD_STACK}
+};
-static const uint8_t die_count_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_DIE_COUNT_MAP =
{
- 1, // 000 = Single die
- 2, // 001 = 2 die
- 3, // 010 = 3 die
- 4, // 011 = 4 die
- 5, // 100 = 5 die
- 6, // 101 = 6 die
- 7, // 110 = 7 die
- 8, // 111 = 8 die
+ // {key byte, number of die}
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {3, 4},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 8}
+
};
-static const uint8_t package_type_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_PACKAGE_TYPE_MAP =
{
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_SDP,
- uint8_t(~0),
- uint8_t(~0),
- uint8_t(~0),
- uint8_t(~0),
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_DDP_QDP,
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_3DS,
+ // {key byte, value}
+ {0, MONOLITHIC},
+ {1, NON_MONOLITHIC}
};
// =========================================================
@@ -252,26 +221,27 @@ static const uint8_t package_type_map[] =
// Page 20
// DDR4 SPD Document Release 3
// Byte 7 (0x007): SDRAM Optional Features
-
-uint16_t static const MAC_map[] =
-{
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNTESTED, // Untested MAC
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_700K, // 700K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_600K, // 600K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_500K, // 500K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_400K, // 400K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_300K, // 300K
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_200K, // 200K
- uint16_t(~0), // Reserved
- fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNLIMITED,// Unlimited MAC
- // All others reserved
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint32_t> > MAC_MAP =
+{
+ // {key byte, maximum activate count}
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNTESTED},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_MAC_700K},
+ {2, fapi2::ENUM_ATTR_EFF_DRAM_MAC_600K},
+ {3, fapi2::ENUM_ATTR_EFF_DRAM_MAC_500K},
+ {4, fapi2::ENUM_ATTR_EFF_DRAM_MAC_400K},
+ {5, fapi2::ENUM_ATTR_EFF_DRAM_MAC_300K},
+ {6, fapi2::ENUM_ATTR_EFF_DRAM_MAC_200K},
+ {8, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNLIMITED}
};
-uint16_t static const tMAW_map[] =
+// Multiplier with tREFI is not taken into account here
+static const std::vector<std::pair<uint8_t, uint32_t> > TMAW_MAP =
{
- 8192,
- 4096,
- 2048,
+ // {key byte, tMAW multiplier}
+ {0, 8192},
+ {1, 4096},
+ {2, 2048}
};
// =========================================================
@@ -280,48 +250,77 @@ uint16_t static const tMAW_map[] =
// Page 21
// DDR4 SPD Document Release 3
// Byte 9 (0x009): Other SDRAM Optional Features
-static const uint8_t ppr_map[]
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > SOFT_PPR_MAP =
{
- fapi2::ENUM_ATTR_EFF_DRAM_PPR_NOT_SUPPORTED,
- fapi2::ENUM_ATTR_EFF_DRAM_PPR_SUPPORTED,
- //...
- // Reserved
+ // {key byte, value }
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED}
};
-static const uint8_t soft_ppr_map[]
+static const std::vector<std::pair<uint8_t, uint8_t> > PPR_MAP =
{
- fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED,
- fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED,
+ // {key byte, value }
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_PPR_NOT_SUPPORTED},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_PPR_SUPPORTED}
};
// =========================================================
-// Byte 6 maps
+// Byte 10 maps
// Item JC-45-2220.01x
-// Page 19
+// Page 21-22
// DDR4 SPD Document Release 3
-// Byte 6 (0x006): Primary SDRAM Package Type
+// Byte 10 (0x00A): Secondary SDRAM Package Type
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > SEC_SIGNAL_LOADING_MAP =
+{
+ // {key byte, signal loading}
+ {0, UNSPECIFIED},
+ {1, MULTI_LOAD_STACK},
+ {2, SINGLE_LOAD_STACK}
+};
+
+static const std::vector<std::pair<uint8_t, uint8_t> > SEC_DIE_COUNT_MAP =
+{
+ // {key byte, number of die}
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {3, 4},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 8}
+
+};
+
+static const std::vector<std::pair<uint8_t, uint8_t> > SEC_PACKAGE_TYPE_MAP =
+{
+ // {key byte, value }
+ {0, MONOLITHIC},
+ {1, NON_MONOLITHIC}
+};
+
-static const uint8_t sec_die_count_map[] =
+// =========================================================
+// Byte 11 maps
+// Item JC-45-2220.01x
+// Page 22-23
+// DDR4 SPD Document Release 3
+// Byte 11 (0x00B): Modle Nominal Voltage
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > ENDURANT_MAP =
{
- 1, // 000 = Single die
- 2, // 001 = 2 die
- 3, // 010 = 3 die
- 4, // 011 = 4 die
- 5, // 100 = 5 die
- 6, // 101 = 6 die
- 7, // 110 = 7 die
- 8, // 111 = 8 die
+ // {key byte, value }
+ {0, NOT_ENDURANT},
+ {1, ENDURANT}
};
-static const uint8_t sec_package_type_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > OPERABLE_MAP =
{
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_SDP,
- uint8_t(~0),
- uint8_t(~0),
- uint8_t(~0),
- uint8_t(~0),
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_DDP_QDP,
- fapi2::ENUM_ATTR_EFF_STACK_TYPE_3DS,
+ // {key byte, value }
+ {0, NOT_OPERABLE },
+ {1, OPERABLE}
};
// =========================================================
@@ -330,51 +329,51 @@ static const uint8_t sec_package_type_map[] =
// Page 23
// DDR4 SPD Document Release 3
// Byte 12 (0x00C): Module Organization
-static const uint8_t device_type_map[] =
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > DEVICE_WIDTH_MAP =
{
- // // Units
- 4, // bits
- 8, // bits
- 16, // bits
- 32, // bits
+ // {key byte, device width (bits)}
+ {0, 4},
+ {1, 8},
+ {2, 16},
+ {3, 32},
// All others reserved
};
-static const uint8_t num_pkgs_ranks_per_dimm_map[] =
-{
- // // Units
- 1, // package rank
- 2, // package ranks
- 3, // package ranks
- 4, // package ranks
- 5, // package ranks
- 6, // package ranks
- 7, // package ranks
- 8 // package ranks
- // All others reserved
+static const std::vector<std::pair<uint8_t, uint8_t> > NUM_PACKAGE_RANKS_MAP =
+{
+ // {key byte, num of package ranks per DIMM (package ranks)}
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {3, 4},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 8}
};
// =========================================================
-// Byte 12 maps
+// Byte 13 maps
// Item JC-45-2220.01x
-// Page 23
+// Page 27
// DDR4 SPD Document Release 3
// Byte 13 (0x00D): Module Memory Bus Width
-static const uint8_t prim_bus_width_map[] =
+// =========================================================
+static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_MAP =
{
- // // Units
- 8, // bits
- 16, // bits
- 32, // bits
- 64, // bits
+ // {key byte, bus width (in bits)
+ {0, 8},
+ {1, 16},
+ {2, 32},
+ {3, 64}
// All others reserved
};
-static const uint8_t bus_width_ext_map[] =
+static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_EXT_MAP =
{
- // // Units
- 0, // bits
- 8, // bits
+ {0, 0},
+ {1, 8}
// All others reserved
};
@@ -384,3165 +383,3733 @@ static const uint8_t bus_width_ext_map[] =
// Page 29
// DDR4 SPD Document Release 3
// Byte 17 (0x011): Timebases
-
+// =========================================================
// Created a maps of a single value in case mapping expands to more values
-static const uint8_t medium_timebase_map[] =
+static const std::vector<std::pair<uint8_t, int64_t> > MEDIUM_TIMEBASE_MAP =
{
- // // Units
- 125, // ps
+ // {key byte, medium timebase (in picoseconds)
+ {0, 125}
// All others reserved
};
-static const uint8_t fine_timebase_map[] =
+static const std::vector<std::pair<uint8_t, int64_t> > FINE_TIMEBASE_MAP =
{
- // // Units
- 1, // ps
+ // {key byte, fine timebase (in picoseconds)
+ {0, 1}
// All others reserved
};
-// =========================================================
-// Function implementations
-// =========================================================
-namespace check
-{
+/////////////////////////
+// Static member functions implementation
+/////////////////////////
+
///
-/// @brief Checks that stack type conforms to JEDEC table
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// @return fapi2::ReturnCode
-/// @note Consumed in (Byte 7) sdram_package_type(...)
-/// Item JC-45-2220.01x
-/// Page 20 (Terminology table)
-/// DDR4 SPD Document Release 3
-bool stack_type(const uint8_t i_stack_type, const uint8_t i_die_count)
+/// @brief Decodes SPD Revision encoding level
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value revision number
+/// @return fapi2::ReturnCode
+/// @note Decodes SPD Byte 1 (3~0).
+/// @note Item JC-45-2220.01x
+/// @note Page 14-15
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::rev_encoding_level(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- const size_t STACK_SDP = 0;
- const size_t STACK_DDP_QDP = 5;
- const size_t STACK_3DS = 6;
+ constexpr size_t BYTE_INDEX = 1;
+ constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_bit_fields = 0;
- const size_t SINGLE_DIE_PACKAGE = 1;
- const size_t DUAL_DIE_PACKAGE = 2;
- const size_t QUAD_DIE_PACKAGE = 4;
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_buffer(l_raw_byte);
- const size_t TWO_SDRAM_DIE = 2;
- const size_t EIGHT_SDRAM_DIE = 8;
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Use const or enums
- switch(i_stack_type)
- {
- case STACK_SDP:
- //SDP has single die
- return i_die_count == SINGLE_DIE_PACKAGE;
- break;
+ // Extracting desired bits
+ l_buffer.extractToRight<ENCODING_LEVEL_START, ENCODING_LEVEL_LEN>(l_bit_fields);
- case STACK_DDP_QDP:
- //DDP has 2 die, QDP has 4 die
- return (i_die_count == DUAL_DIE_PACKAGE) || (i_die_count == QUAD_DIE_PACKAGE);
- break;
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_bit_fields != UNDEFINED),
+ BYTE_INDEX,
+ l_raw_byte,
+ "Failed check on SPD rev encoding level") );
- case STACK_3DS:
- //3DS has 2 - 8 dies
- return (i_die_count >= TWO_SDRAM_DIE) && (i_die_count <= EIGHT_SDRAM_DIE);
- break;
+ // Update output only after check passes
+ o_value = l_bit_fields;
- default:
- return false; // Doesn't meet JEDEC spec
- }
-}// stack_type()
+ // Print decoded info
+ FAPI_DBG("%s. Rev - Encoding Level : %d",
+ c_str(i_target),
+ o_value);
-} // check namespace
+fapi_try_exit:
+ return fapi2::current_err;
+}
///
-/// @brief Calculates timing value
-/// @param[in] const int64_t& i_spd_timing_mtb,
-/// const int64_t& i_spd_timing_ftb,
-/// const int64_t& multiplier_mtb,
-/// const int64_t& multiplier_ftb
-/// @return int64_t, (timing value)
-inline int64_t calc_timing(const int64_t& i_spd_timing_mtb,
- const int64_t& i_spd_timing_ftb,
- const int64_t& multiplier_mtb,
- const int64_t& multiplier_ftb)
+/// @brief Decodes SPD Revision additions level
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value revision number
+/// @return fapi2::ReturnCode
+/// @note Decodes SPD Byte 1 (bits 7~4).
+/// @note Item JC-45-2220.01x
+/// @note Page 14-15
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::rev_additions_level(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- int64_t timing_val = i_spd_timing_mtb * multiplier_mtb;
- int64_t offset = (i_spd_timing_ftb * multiplier_ftb);
- int64_t remainder_val = timing_val % multiplier_mtb;
+ constexpr size_t BYTE_INDEX = 1;
+ constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_bit_fields = 0;
- if( remainder_val == 0)
- {
- // If the timing value can be expressed as an integer number
- // of MTB units, return that
- return timing_val;
- }
- else
- {
- // Else round up and incorporate correction factor
- return (++timing_val) + offset;
- }
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_buffer(l_raw_byte);
+
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<ADDITIONS_LEVEL_START, ADDITIONS_LEVEL_LEN>(l_bit_fields);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_bit_fields != UNDEFINED),
+ BYTE_INDEX,
+ l_raw_byte,
+ "Failed check on SPD rev encoding level") );
+
+ // Update output only after check passes
+ o_value = l_bit_fields;
+
+ // Print decoded info
+ FAPI_DBG("%s. Rev - Additions Level : %d",
+ c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Decodes SPD number of bytes
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// size_t i_read_spd_size
+/// @brief Decodes base module type (DIMM type) from SPD
+/// @param[in] i_target
+/// @param[in] i_spd_data PD blob
+/// @param[out] o_value
/// @return fapi2::ReturnCode
-/// @note Decodes SPD Byte 0
+/// @note Decodes SPD Byte 3 (bits 0~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::number_of_bytes(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
+fapi2::ReturnCode decoder::base_module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
const uint8_t* i_spd_data,
- const size_t i_read_spd_size)
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 0;
+ constexpr size_t BYTE_INDEX = 3;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // SPD Bytes used mapping limits
- const size_t BYTES_USED_MAP_OFFSET = 1;
- const size_t BYTES_USED_MIN_VALID_KEY = 1; // All previous keys are not supported or reserved
- const size_t BYTES_USED_MAX_VALID_KEY = 4; // The rest are not supported or reserved
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Total SPD bytes mapping limits
- const size_t BYTES_TOTAL_MAP_OFFSET = 1;
- const size_t BYTES_TOTAL_MIN_VALID_KEY = 1; // All previous keys are not supported or reserved
- const size_t BYTES_TOTAL_MAX_VALID_KEY = 2; // The rest are not supported or reserved
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX",
+ c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Byte variables used for decoding
- uint8_t l_spd_bytes_used = 0;
- uint8_t l_spd_bytes_total = 0;
- uint8_t l_reserved = 0;
- uint16_t l_total_bytes_map_val = 0;
- uint16_t l_used_bytes_map_val = 0;
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BASE_MODULE_START, BASE_MODULE_LEN>(l_field_bits);
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
- // Trace in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte 0: 0x%llX.",
- mss::c_str(i_target_dimm),
- i_spd_data[BYTE_INDEX]);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BASE_MODULE_TYPE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check on Base Module Type") );
- // Decoding 1st nibble, bits 3~0 (SPD Bytes Used)
- l_spd_buffer.extractToRight<BYTES_USED_START, BYTES_USED_LEN>(l_spd_bytes_used);
-
- // Check to assure SPD Bytes Used (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_spd_bytes_used >= BYTES_USED_MIN_VALID_KEY) &&
- (l_spd_bytes_used <= BYTES_USED_MAX_VALID_KEY),
- BYTE_INDEX,
- l_spd_bytes_used,
- "Failed check on Used SPD bytes") );
-
- // Decoding bits 6~4 (SPD Bytes Total)
- l_spd_buffer.extractToRight<BYTES_TOTAL_START, BYTES_TOTAL_LEN>(l_spd_bytes_total);
-
- // Check to assure SPD Bytes Total (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_spd_bytes_total >= BYTES_TOTAL_MIN_VALID_KEY) &&
- (l_spd_bytes_total <= BYTES_TOTAL_MAX_VALID_KEY),
- BYTE_INDEX,
- l_spd_bytes_total,
- "Failed check on total SPD bytes" ) );
-
- // Decoding bit 7 (Reserved bit)
- l_spd_buffer.extractToRight<BYTES_RESERVED_START, BYTES_RESERVED_LEN>(l_reserved);
-
- // Hold map values in temp variables
- l_used_bytes_map_val = bytes_used_map[l_spd_bytes_used - BYTES_USED_MAP_OFFSET];
- l_total_bytes_map_val = bytes_total_map[l_spd_bytes_total - BYTES_TOTAL_MAP_OFFSET];
-
- // Size of input SPD read should match size it claims to be based on the SPD spec
- // "Used SPD bytes" wasn't used since manufacturers may not use all available bytes
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_total_bytes_map_val == i_read_spd_size,
- BYTE_INDEX,
- l_total_bytes_map_val,
- "Failed SPD size check") );
-
- FAPI_INF("%s. Bytes Used: %d, Total Bytes: %d, Reserved : %d",
- mss::c_str(i_target_dimm),
- l_used_bytes_map_val,
- l_total_bytes_map_val,
- l_reserved);
+ FAPI_DBG("%s. Base Module Type: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Decodes SPD Revision
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// @param[in, out] uint8_t io_revision_num
-/// @return fapi2::ReturnCode
-/// @note Decodes SPD Byte 1
+/// @brief Object factory to select correct decoder based on SPD revision & dimm type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value shared pointer to the factory object
+/// @return fapi2::ReturnCode
///
-fapi2::ReturnCode decoder::revision(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::factory(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ std::shared_ptr<decoder>& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 1;
- const size_t UNDEFINED = 0xFF; // per JEDEC spec
+ uint8_t l_dimm_type = 0;
+ uint8_t l_encoding_rev = 0;
+ uint8_t l_additions_rev = 0;
- // Byte variables used for decoding
- uint8_t l_revision_num = 0;
+ // Get dimm type & revision levels
+ FAPI_TRY(base_module_type(i_target, i_spd_data, l_dimm_type));
+ FAPI_TRY(rev_encoding_level(i_target, i_spd_data, l_encoding_rev));
+ FAPI_TRY(rev_additions_level(i_target, i_spd_data, l_additions_rev));
- // Verify SPD revision is not undefined. Value is defined by the JEDEC spec
- l_revision_num = i_spd_data[BYTE_INDEX];
+ // Get decoder object needed for current dimm type and spd rev
+ switch(l_dimm_type)
+ {
+ // Each dimm type rev is independent
+ case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM:
+
+ // SPD Revision format #.#
+ // 1st # = encoding level
+ // 2nd # = additions level
+ switch(l_encoding_rev)
+ {
+ case 1:
+ switch(l_additions_rev)
+ {
+ case 0:
+ case 1:
+ o_value = std::make_shared<decoder>();
+ break;
+
+ default:
+ FAPI_TRY( mss::check::spd::
+ invalid_factory_sel(i_target,
+ l_dimm_type,
+ l_encoding_rev,
+ l_additions_rev,
+ "Additions Level Unsupported!") );
+ break;
+ }//end additions
+
+ break;
+
+ default:
+ FAPI_TRY( mss::check::spd::
+ invalid_factory_sel(i_target,
+ l_dimm_type,
+ l_encoding_rev,
+ l_additions_rev,
+ "Encoding Level Unsupported!") );
+ break;
+ }// end encodings
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_revision_num != UNDEFINED),
- BYTE_INDEX,
- l_revision_num,
- "Failed check on SPD revision") );
- // Print decoded info
- FAPI_INF("%s. SPD data at Byte %d: 0x%llX, Revision number : %d",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX],
- l_revision_num);
+ break;
+
+ default:
+ FAPI_TRY( mss::check::spd::
+ invalid_factory_sel(i_target,
+ l_dimm_type,
+ l_encoding_rev,
+ l_additions_rev,
+ "DIMM Type Unsupported!") );
+ break;
+
+ } // end dimm type
fapi_try_exit:
return fapi2::current_err;
+
}
+
+/////////////////////////
+// Member Method implementation
+/////////////////////////
+
///
-/// @brief Decodes DRAM Device Type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes number of used SPD bytes
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of SPD bytes used
/// @return fapi2::ReturnCode
-/// @note Decodes SPD Byte 2
+/// @note Decodes SPD Byte 0 bits(0~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 14
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::dram_device_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::number_of_used_bytes(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint16_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 2;
+ constexpr size_t BYTE_INDEX = 0;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+ uint16_t l_map_value = 0;
- // dram generation mapping limits
- const size_t MIN_VALID_KEY = 12; // All previous keys are not supported or reserved
- const size_t MAX_VALID_KEY = 13; // The rest are not supported or reserved
- const size_t MAP_OFFSET = 11; // SPD DRAM device type map has an index offset of 11 (simplifies array)
- // //since initial map values are not supported or reserved (ignored for now)
+ // Buffers used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BYTES_USED_START, BYTES_USED_LEN>(l_field_bits);
- // Byte variables used for decoding
- uint8_t l_device_type = 0;
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
- // Attribute variables used to set decoded vals
- uint8_t l_device_gen[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BYTES_USED_MAP, l_field_bits, l_map_value),
+ BYTE_INDEX,
+ l_map_value,
+ "Failed check on SPD total bytes") );
- // Check to assure SPD DRAM device type (map) wont be at invalid values
- l_device_type = i_spd_data[BYTE_INDEX];
+ // Don't update output with garbage data until until all tests pass
+ o_value = l_map_value;
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_device_type >= MIN_VALID_KEY) &&
- (l_device_type <= MAX_VALID_KEY),
- BYTE_INDEX,
- l_device_type,
- "Unsupported/reserved key value retried from SPD") );
+ FAPI_DBG("%s. Bytes Used: %d",
+ mss::c_str(i_target),
+ o_value);
- // Retrive entire MCS level attribute
- FAPI_TRY(eff_dram_gen(l_target_mcs, &l_device_gen[0][0]));
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Update attribute to decoded byte values
- l_device_gen[PORT_NUM][DIMM_NUM] = dram_gen_map[l_device_type - MAP_OFFSET];
+///
+/// @brief Decodes total number of SPD bytes
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of total SPD bytes
+/// @return fapi2::ReturnCode
+/// @note Decodes SPD Byte 0 (bits 4~6)
+/// @note Item JC-45-2220.01x
+/// @note Page 14
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::number_of_total_bytes(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint16_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 0;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, l_target_mcs, l_device_gen));
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Print decoded info
- FAPI_INF("%s SPD data at Byte %d: 0x%llX. Device type : %d",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX],
- l_device_gen[PORT_NUM][DIMM_NUM]);
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BYTES_TOTAL_START, BYTES_TOTAL_LEN>(l_field_bits);
+
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BYTES_TOTAL_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check on SPD total bytes") );
+
+ FAPI_DBG("%s. Total Bytes: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
-
}
///
-/// @brief Decodes SPD module type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// @return fapi2::ReturnCode
-/// @note Decodes SPD Byte 3
+/// @brief Decodes DRAM Device Type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value dram device type enumeration
+/// @return fapi2::ReturnCode
+/// @note Decodes SPD Byte 2
+/// @note Item JC-45-2220.01x
+/// @note Page 16
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::dram_device_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 3;
- // Base module mapping limits // since first index is not supported
- const size_t BASE_MODULE_MAP_OFFSET = 1; // base_module_type_map has an index offset of 1
- const size_t MIN_VALID_KEY = 1; // All previous keys are not supported or reserved
- const size_t MAX_VALID_KEY = 4; // The rest are not supported or reserved
+ constexpr size_t BYTE_INDEX = 2;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
- // Hybrid Media limit
- const size_t MAX_HYBRID_MEDIA_KEY = 1; // All other key values reserved
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Hybrid
- const size_t MAX_HYBRID_KEY = 1; // Nothing else exits afterwards
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(DRAM_GEN_MAP, l_raw_byte, o_value),
+ BYTE_INDEX,
+ l_raw_byte,
+ "Failed check on SPD dram device type") );
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Print decoded info
+ FAPI_DBG("%s Device type : %d",
+ c_str(i_target),
+ o_value);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Byte variables used for decoding
- uint8_t l_base_module_type = 0;
- uint8_t l_hybrid_media = 0;
- uint8_t l_hybrid = 0;
+///
+/// @brief Decodes hybrid media field from SPD
+/// @param[in] i_target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing hybrid memory type
+/// @return fapi2::ReturnCode
+/// @note Decodes SPD Byte 3 (bits 4~6)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::hybrid_media(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
- // Attribute variables used to set decoded vals
- uint8_t l_module_type[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+{
+ constexpr size_t BYTE_INDEX = 3;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
// Trace in the front assists w/ debug
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<HYBRID_MEDIA_START, HYBRID_MEDIA_LEN>(l_field_bits);
- // Decoding bits 3~0
- l_spd_buffer.extractToRight<BASE_MODULE_START, BASE_MODULE_LEN>(l_base_module_type);
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
- // Check to assure SPD DRAM base module type (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_base_module_type >= MIN_VALID_KEY) &&
- (l_base_module_type <= MAX_VALID_KEY),
- BYTE_INDEX,
- l_base_module_type,
- "Failed check for SPD DRAM base module type") );
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(HYBRID_MEDIA_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check on Hybrid Media type") );
- // Decoding bits 6~4
- l_spd_buffer.extractToRight<HYBRID_MEDIA_START, HYBRID_MEDIA_LEN>(l_hybrid_media);
+ FAPI_DBG("%s. Hybrid Media: %d",
+ mss::c_str(i_target),
+ o_value);
- // Check to assure SPD DRAM hybrid media is valid
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_hybrid_media <= MAX_HYBRID_MEDIA_KEY,
- BYTE_INDEX,
- l_hybrid_media,
- "Failed check for SPD DRAM hybrid media") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Decoding bit 7
- l_spd_buffer.extractToRight<HYBRID_START, HYBRID_LEN>(l_hybrid);
+///
+/// @brief Decodes hybrid field from SPD
+/// @param[in] i_target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing if module is hybrid
+/// @return fapi2::ReturnCode
+/// @note Decodes SPD Byte 3 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::hybrid(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 3;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
+
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Check to assure SPD DRAM hybrid media is valid
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_hybrid_media <= MAX_HYBRID_KEY,
- BYTE_INDEX,
- l_hybrid,
- "Failed check for SPD DRAM hybrid media") );
- // Retrive entire MCS level attribute
- FAPI_TRY(spd_module_type(l_target_mcs, &l_module_type[0][0]));
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<HYBRID_START, HYBRID_LEN>(l_field_bits);
- // Update attribute to decoded byte values
- l_module_type[PORT_NUM][DIMM_NUM] = base_module_type_map[l_base_module_type - BASE_MODULE_MAP_OFFSET];
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_SPD_MODULE_TYPE, l_target_mcs, l_module_type));
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(HYBRID_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check on hybrid field") );
- FAPI_INF("%s. Base Module Type: %d, Hybrid Media: %d, Hybrid: %d",
- c_str(i_target_dimm),
- l_module_type[PORT_NUM][DIMM_NUM],
- l_hybrid_media,
- l_hybrid);
+ FAPI_DBG("%s. Hybrid: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Decode SDRAM density
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM density from SPD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value SDRAM density in GBs
/// @return fapi2::ReturnCode
-/// @note SPD Byte 4
+/// @note SPD Byte 4 (bits 0~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::sdram_density(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::sdram_density(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+
{
- // Immutable constants
- const size_t BYTE_INDEX = 4;
- // DRAM capacity mapping limits
- const size_t CAPACITY_MAP_OFFSET = 1; // base_module_type_map has an index offset of 1
- const size_t CAPACITY_MIN_VALID_KEY = 2; // All previous keys are not supported or reserved
- const size_t CAPACITY_MAX_VALID_KEY = 9; // The rest are not supported or reserved
+ constexpr size_t BYTE_INDEX = 4;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // DRAM banks mapping limits
- const size_t BANKS_MAX_VALID_KEY = 1; // The rest are not supported or reserved
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN>(l_field_bits);
- // DRAM bank groups mapping limits
- const size_t BANK_GRP_MAX_VALID_KEY = 2; // The rest are not supported or reserved
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(SDRAM_DENSITY_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SPD DRAM capacity") );
+
+ FAPI_DBG("%s. SDRAM density: %d",
+ mss::c_str(i_target),
+ o_value);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+///
+/// @brief Decodes number of SDRAM banks from SPD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value Number of SDRAM banks
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 4 (bits 4~5)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::banks(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
- // Byte variables used for decoding
- uint8_t l_sdram_capacity = 0;
- uint8_t l_sdram_banks = 0;
- uint8_t l_sdram_bank_group = 0;
+{
- // Attribute variables used to set decoded vals
- uint8_t l_capacities[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_banks[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_bank_groups[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ constexpr size_t BYTE_INDEX = 4;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
// Trace in the front assists w/ debug
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Decoding bits 3~0
- l_spd_buffer.extractToRight<SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN>(l_sdram_capacity);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SDRAM_BANKS_START, SDRAM_BANKS_LEN>(l_field_bits);
// Check to assure SPD DRAM capacity (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sdram_capacity >= CAPACITY_MIN_VALID_KEY) &&
- (l_sdram_capacity <= CAPACITY_MAX_VALID_KEY),
- BYTE_INDEX,
- l_sdram_capacity,
- "Failed check for SPD DRAM capacity") );
- // Decoding bits 5~4
- l_spd_buffer.extractToRight<SDRAM_BANKS_START, SDRAM_BANKS_LEN>(l_sdram_banks);
-
- // Check to assure SPD DRAM banks (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sdram_banks <= BANKS_MAX_VALID_KEY),
- BYTE_INDEX,
- l_sdram_banks,
- "Failed check for SPD DRAM banks") );
-
- // Decoding bits 7~6
- l_spd_buffer.extractToRight<BANK_GROUP_START, BANK_GROUP_LEN>(l_sdram_bank_group);
-
- // Check to assure SPD DRAM banks groups (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sdram_bank_group <= BANK_GRP_MAX_VALID_KEY),
- BYTE_INDEX,
- l_sdram_bank_group,
- "Failed check for SPD DRAM bank groups") );
-
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_density(l_target_mcs, &l_capacities[0][0]) );
- FAPI_TRY( eff_dram_banks(l_target_mcs, &l_banks[0][0]) );
- FAPI_TRY( eff_dram_bank_groups(l_target_mcs, &l_bank_groups[0][0]) );
-
- // Update attribute to decoded byte values
- l_capacities[PORT_NUM][DIMM_NUM] = sdram_capacity_map[l_sdram_capacity - CAPACITY_MAP_OFFSET];
- l_banks[PORT_NUM][DIMM_NUM] = sdram_banks_map[l_sdram_banks];
- l_bank_groups[PORT_NUM][DIMM_NUM] = sdram_bankgroups_map[l_sdram_bank_group];
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DENSITY, l_target_mcs, l_capacities));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_BANKS, l_target_mcs, l_banks));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_BANK_GROUPS, l_target_mcs, l_bank_groups));
-
- FAPI_INF("%s. SDRAM capacity: %d, banks: %d, bank groups: %d",
- c_str(i_target_dimm),
- sdram_capacity_map[l_sdram_capacity],
- sdram_banks_map[l_sdram_banks],
- sdram_bankgroups_map[l_sdram_bank_group]);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BANK_ADDR_BITS_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SPD DRAM banks") );
+
+ FAPI_DBG("%s. Banks: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Decode SDRAM addressing
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes number of SDRAM bank groups from SPD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value Number of SDRAM bank groups
/// @return fapi2::ReturnCode
-/// @note SPD Byte 5
+/// @note SPD Byte 4 (bits 6~7)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::sdram_addressing(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::bank_groups(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 5;
- // DRAM column address mapping limits
- const size_t COLUMN_MAX_VALID_KEY = 3; // The rest are not supported or reserved
- // DRAM row address mapping limits
- const size_t ROW_MAX_VALID_KEY = 6; // The rest are not supported or reserved
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Byte variables used for decoding
- uint8_t l_column_addr = 0;
- uint8_t l_row_addr = 0;
- uint8_t l_reserved = 0;
-
- // Attribute variables used to set decoded vals
- uint8_t l_columns[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_rows[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ constexpr size_t BYTE_INDEX = 4;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
// Trace in the front assists w/ debug
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Decoding bits 2~0 (Column Address bits)
- l_spd_buffer.extractToRight<COL_ADDRESS_START, COL_ADDRESS_LEN>(l_column_addr);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BANK_GROUP_START, BANK_GROUP_LEN>(l_field_bits);
- // Check to assure SPD DRAM Column Address bits (map) wont be indexed at invalid values
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_column_addr <= COLUMN_MAX_VALID_KEY),
- BYTE_INDEX,
- l_column_addr,
- "Failed check for SPD DRAM bank groups") );
-
- // Decoding bits 3~0 (Row address bits)
- l_spd_buffer.extractToRight<ROW_ADDRESS_START, ROW_ADDRESS_LEN>(l_row_addr);
-
- // Check to assure SPD DRAM Row address bits (map) wont be at invalid values
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_row_addr <= ROW_MAX_VALID_KEY),
- BYTE_INDEX,
- l_row_addr,
- "Failed check for SPD DRAM bank groups") );
-
- // Decoding bits 7~6
- l_spd_buffer.extractToRight<ADDRESS_RESERVED_START, ADDRESS_RESERVED_LEN>(l_reserved);
-
- // Check to assure SPD reserved bits are 0 as defined in JEDEC SPD spec
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_reserved == 0),
- BYTE_INDEX,
- l_reserved,
- "Failed check for SPD DRAM bank groups") );
-
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_cols(l_target_mcs, &l_columns[0][0]) );
- FAPI_TRY( eff_dram_rows(l_target_mcs, &l_rows[0][0]) );
-
- // Update attribute to decoded byte values
- l_columns[PORT_NUM][DIMM_NUM] = column_address_map[l_column_addr];
- l_rows[PORT_NUM][DIMM_NUM] = row_address_map[l_row_addr];
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_COLS, l_target_mcs, l_columns));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_ROWS, l_target_mcs, l_rows));
-
- FAPI_INF("%s. Columns: %d, Rows: %d",
- c_str(i_target_dimm),
- l_columns[PORT_NUM][DIMM_NUM],
- l_rows[PORT_NUM][DIMM_NUM]);
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BANK_GROUP_BITS_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SPD DRAM bank groups") );
+
+ FAPI_DBG("%s. Bank Groups: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
-
///
-/// @brief Decode SDRAM Package Type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes number of SDRAM column address bits
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of column address bits
/// @return fapi2::ReturnCode
-/// @note SPD Byte 6
+/// @note SPD Byte 5 (bits 2~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::primary_package_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::column_address_bits(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 6;
- const size_t INVALID_VALUE = 0x11; //per JEDEC spec
- const size_t RESERVED = 0;
- // DRAM die count mapping limits
- const size_t DIE_COUNT_MAX_VALID_KEY = 7; // Nothing greater doesn't exist
- const size_t INVALID_PACKAGE_TYPE = ~0;
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<COL_ADDRESS_START, COL_ADDRESS_LEN>(l_field_bits);
- // Byte variables used for decoding
- uint8_t l_prim_signal_loading = 0;
- uint8_t l_reserved = 0;
- uint8_t l_prim_die_count = 0;
- uint8_t l_prim_package_type = 0;
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(COLUMN_ADDRESS_BITS_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SDRAM Column Address Bits") );
- // Attribute variables used to set decoded vals
- uint8_t l_stack_type = 0;
- uint8_t l_sdram_package_type[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_sdram_die_count[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_DBG("%s. Number of Column Address Bits: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes number of SDRAM row address bits
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of row address bits
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 5 (bits 5~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::row_address_bits(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<ROW_ADDRESS_START, ROW_ADDRESS_LEN>(l_field_bits);
- // Decoding bits 1~0 (Signal loading)
- l_spd_buffer.extractToRight<PRIM_PRIM_SIGNAL_LOAD_START, PRIM_PRIM_SIGNAL_LOAD_LEN>(l_prim_signal_loading);
-
- // Check to assure SPD DRAM signal loading conforms to JEDEC SPEC
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_prim_signal_loading != INVALID_VALUE),
- BYTE_INDEX,
- l_prim_signal_loading,
- "Failed check for SPD DRAM signal loading") );
- // Decoding bits 3~2 (Reserved)
- l_spd_buffer.extractToRight<PACKAGE_RESERVE_START, PACKAGE_RESERVE_LEN>(l_reserved);
-
- // Check to assure SPD reserved bits are 0 as defined in JEDEC SPD spec
- mss::check::spd::valid_value_warn(i_target_dimm,
- (l_reserved == RESERVED),
- BYTE_INDEX,
- l_reserved,
- "Failed check for SPD DRAM reserved bits");
-
- // Decoding bits 6~4 (Die Count)
- l_spd_buffer.extractToRight<PRIM_DIE_COUNT_START, PRIM_DIE_COUNT_LEN>(l_prim_die_count);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_prim_die_count <= DIE_COUNT_MAX_VALID_KEY),
- BYTE_INDEX,
- l_prim_die_count,
- "Failed check for SPD DRAM die count") );
- // Decoding bit 7
- l_spd_buffer.extractToRight<PRIM_PACKAGE_TYPE_START, PRIM_PACKAGE_TYPE_LEN>(l_prim_package_type);
-
- // Manipulating and combining l_prim_package_type and l_prim_signal_loading to produce the following
- // table for indexing the package_type_map[].
- // 0000 0000 = SDP (monolithic device)
- // 0000 0101 = DDP/QDP (non-monolithic device)
- // 0000 0110 = 3DS (non-monolithic device)
- // What this essentially does is remove reserved bits.
- // This was done to avoid having large gaps (of 0's) in the package_type_map (sparsed array)
- // since we can't use std::map due to thread saftey issues
- l_stack_type = (l_prim_package_type >> 5) | l_prim_signal_loading;
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- check::stack_type(l_stack_type, die_count_map[l_prim_die_count]) &&
- (package_type_map[l_stack_type] != INVALID_PACKAGE_TYPE),
- BYTE_INDEX,
- package_type_map[l_stack_type],
- "Failed check for SPD DRAM stack type") );
-
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_stack_type(l_target_mcs, &l_sdram_package_type[0][0]) );
- FAPI_TRY( eff_prim_die_count(l_target_mcs, &l_sdram_die_count[0][0]) );
-
- // Update attribute to decoded byte values
- l_sdram_die_count[PORT_NUM][DIMM_NUM] = die_count_map[l_prim_die_count];
- l_sdram_package_type[PORT_NUM][DIMM_NUM] = package_type_map[l_stack_type];
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_STACK_TYPE, l_target_mcs, l_sdram_package_type));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_PRIM_DIE_COUNT, l_target_mcs, l_sdram_die_count));
-
- FAPI_INF("%s. Signal loading: %d, Die count: %d, Stack type: %d",
- c_str(i_target_dimm),
- l_prim_signal_loading,
- die_count_map[l_prim_die_count],
- l_sdram_package_type[PORT_NUM][DIMM_NUM]);
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(ROW_ADDRESS_BITS_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SDRAM Row Address Bits") );
+
+ FAPI_DBG("%s. Number of Row Address Bits: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
-//TODO
-// Need to complete this function, map need tREF1 calculations
///
-/// @brief Decode SDRAM Optional Features
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Primary SDRAM signal loading
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing signal loading type
/// @return fapi2::ReturnCode
-/// @note SPD Byte 7
+/// @note SPD Byte 6 (bits 1~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 19
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::sdram_optional_features(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::prim_sdram_signal_loading(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 7;
- const size_t RESERVED = 0;
- // MAC mapping limits
- const size_t MAC_RESERVED = 7; //per JEDEC spec
- const size_t MAC_MAX_VALID_KEY = 8;
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
+
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<PRIM_SIGNAL_LOAD_START, PRIM_SIGNAL_LOAD_LEN>(l_field_bits);
- // TMAW mappint limits
- const size_t TMAW_MAX_VALID_KEY = 2;
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(PRIM_SIGNAL_LOADING_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Primary SDRAM Signal Loading") );
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ FAPI_DBG("%s. Primary SDRAM Signal Loading: %d",
+ mss::c_str(i_target),
+ o_value);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Byte variables used for decoding
- uint16_t l_MAC = 0; // Maximum Active Count
- uint16_t l_tMAW = 0; // Maximum Active Window
- uint8_t l_reserved = 0;
+///
+/// @brief Decodes Primary SDRAM die count
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value die count
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 6 (bits 6~4)
+/// @note Item JC-45-2220.01x
+/// @note Page 19
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::prim_sdram_die_count(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- // Attribute variables used to set decoded vals
- uint16_t l_mac[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint16_t l_tmaw[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Decoding bits 3~0 (MAC)
- l_spd_buffer.extractToRight<MAC_START, MAC_LEN>(l_MAC);
- // Check to assure SPD DRAM signal loading conforms to JEDEC SPEC
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_MAC <= MAC_MAX_VALID_KEY) &&
- l_MAC != MAC_RESERVED,
- BYTE_INDEX,
- l_MAC,
- "Failed check for Maximum Active Count (MAC)") );
-
- // Decoding bits 5~4 (tMAW)
- l_spd_buffer.extractToRight<TMAW_START, TMAW_LEN>(l_tMAW);
-
- // Check to assure SPD DRAM signal loading conforms to JEDEC SPEC
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tMAW <= TMAW_MAX_VALID_KEY),
- BYTE_INDEX,
- l_tMAW,
- "Failed check for Maximum Active Window (tMAW)") );
-
- // Decoding bits 7~6 (Reserved)
- l_spd_buffer.extractToRight<OPT_FEAT_RESERVED_START, OPT_FEAT_RESERVED_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- (l_reserved == RESERVED),
- BYTE_INDEX,
- l_reserved,
- "Failed check for Reserved bits") ;
-
- // Retrive entire MCS level attribute
- FAPI_TRY(eff_dram_mac(l_target_mcs, &l_mac[0][0]));
- FAPI_TRY(eff_dram_tmaw(l_target_mcs, &l_tmaw[0][0]));
-
- // Update attribute to decoded byte values
- l_mac[PORT_NUM][DIMM_NUM] = MAC_map[l_MAC];
- l_tmaw[PORT_NUM][DIMM_NUM] = tMAW_map[l_tMAW];
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_MAC, l_target_mcs, l_mac));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TMAW, l_target_mcs, l_tmaw));
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<PRIM_DIE_COUNT_START, PRIM_DIE_COUNT_LEN>(l_field_bits);
- // Print decoded info
- FAPI_INF("%s. MAC: %d, tMAW: %d",
- c_str(i_target_dimm),
- l_tmaw[PORT_NUM][DIMM_NUM],
- l_mac[PORT_NUM][DIMM_NUM]);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(PRIM_DIE_COUNT_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SDRAM Row Address Bits") );
+
+ FAPI_DBG("%s. Number of Row Address Bits: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
-}// decode_sdram_optional_features()
+}
///
-/// @brief Decode SDRAM Thermal and Refresh Options
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Primary SDRAM package type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing package type
/// @return fapi2::ReturnCode
-/// @note SPD Byte 8, currently reserved
+/// @note SPD Byte 6 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 19
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::thermal_and_refresh_options(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::prim_sdram_package_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 8;
- const size_t RESERVED_BYTE = 0; // per JEDEC spec
- // Byte variable
- uint8_t l_reserved = i_spd_data[BYTE_INDEX];
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Check to assure SPD reserved byte is 0 per JEDEC spec
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_reserved == RESERVED_BYTE),
- BYTE_INDEX,
- l_reserved,
- "Failed check for SPD DRAM reserved byte") );
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Print decoded info
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<PRIM_PACKAGE_TYPE_START, PRIM_PACKAGE_TYPE_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(PRIM_PACKAGE_TYPE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SDRAM Row Address Bits") );
+
+ FAPI_DBG("%s. Number of Row Address Bits: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
-}// decode_thermal_and_refresh_options()
+}
///
-/// @brief Decode Other SDRAM Optional Features
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode SDRAM Maximum activate count
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing max activate count
/// @return fapi2::ReturnCode
-/// @note SPD Byte 9
+/// @note SPD Byte 7 (bits 3~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 20
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::other_optional_features(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::maximum_activate_count(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint32_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 9;
- const size_t RESERVED = 0;
- // Soft PPR mapping limits
- const size_t SOFT_PPR_MAX_VALID_KEY = 2; // Nothing greater doesn't exist
+ constexpr size_t BYTE_INDEX = 7;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // PPR mapping limits
- const size_t PPR_MAX_VALID_KEY = 2; // Nothing greater doesn't exist
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<MAC_START, MAC_LEN>(l_field_bits);
- // Byte variables used for decoding
- uint8_t l_reserved = 0;
- uint8_t l_soft_ppr = 0;// Soft Post Package Repair
- uint8_t l_ppr = 0; // Post Package Repair
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(MAC_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SDRAM Maximum Active Count (MAC)") );
- // Attribute variables used to set decoded vals
- uint8_t l_soft_PPRs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_PPRs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_DBG("%s. Maximum Active Count (MAC): %d",
+ mss::c_str(i_target),
+ o_value);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value max activate window multiplier
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 7 (bits 3~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 20
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::maximum_activate_window_multiplier(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint32_t& o_value)
+{
+
+ constexpr size_t BYTE_INDEX = 7;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Decoding bits 4~0
- l_spd_buffer.extractToRight<PPR_RESERVED_START, PPR_RESERVED_LEN>(l_reserved);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<TMAW_START, TMAW_LEN>(l_field_bits);
- mss::check::spd::valid_value_warn(i_target_dimm,
- (l_reserved == RESERVED),
- BYTE_INDEX,
- l_reserved,
- "Failed check for reserved bits");
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(TMAW_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Maximum Active Window (tMAW)") );
- // Decoding bit 5
- l_spd_buffer.extractToRight<SOFT_PPR_START, SOFT_PPR_LEN>(l_soft_ppr);
+ FAPI_DBG("%s. Maximum Active Window multiplier: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_soft_ppr < SOFT_PPR_MAX_VALID_KEY),
- BYTE_INDEX,
- l_soft_ppr,
- "Failed check for SOFT PPR") );
+///
+/// @brief Decode Soft post package repair (soft PPR)
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing if soft PPR is supported
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 9 (bit 5)
+/// @note Item JC-45-2220.01x
+/// @note Page 21
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::soft_post_package_repair(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- // Decoding bits 7~6
- l_spd_buffer.extractToRight<PPR_START, PPR_LEN>(l_ppr);
+ constexpr size_t BYTE_INDEX = 9;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_ppr < PPR_MAX_VALID_KEY),
- BYTE_INDEX,
- l_ppr,
- "Failed check for PPR") );
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Retrive entire MCS level attribute
- FAPI_TRY(eff_dram_soft_ppr(l_target_mcs, &l_soft_PPRs[0][0]));
- FAPI_TRY(eff_dram_ppr(l_target_mcs, &l_PPRs[0][0]));
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Update attribute to decoded byte values
- l_soft_PPRs[PORT_NUM][DIMM_NUM] = soft_ppr_map[l_soft_ppr];
- l_PPRs[PORT_NUM][DIMM_NUM] = ppr_map[l_ppr];
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SOFT_PPR_START, SOFT_PPR_LEN>(l_field_bits);
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_SOFT_PPR, l_target_mcs, l_soft_PPRs));
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_PPR, l_target_mcs, l_PPRs));
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(SOFT_PPR_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Soft PPR") );
- // Printed decoded info
- FAPI_INF("%s. Soft PPR: %d, PPR: %d, Reserved: %d",
- c_str(i_target_dimm),
- l_soft_PPRs[PORT_NUM][DIMM_NUM],
- l_PPRs[PORT_NUM][DIMM_NUM],
- l_reserved);
+ FAPI_DBG("%s. Soft Post Package Repair (Soft PPR): %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Decode Secondary SDRAM Package Type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode Post package repair (PPR)
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing if (hard) PPR is supported
/// @return fapi2::ReturnCode
-/// @note SPD Byte 10
+/// @note SPD Byte 9 (bits 7~6)
+/// @note Item JC-45-2220.01x
+/// @note Page 21
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::secondary_package_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::post_package_repair(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 10;
- const size_t SUPPORTED_VALUE = 0;
- // Byte variables used for decoding
- uint8_t l_sec_signal_loading = 0;
- uint8_t l_density_ratio = 0;
- uint8_t l_sec_die_count = 0;
- uint8_t l_sec_package_type = 0;
+ constexpr size_t BYTE_INDEX = 9;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
+
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Currently we do not support asymmetrical assembly of multiple SDRAM package types
- // According to the JEDEC spec, for modules with symmetrical assembly (which we do support),
- // this byte must be coded as 0x00. Additional checks were added to isolate any corrupt data failure
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<PPR_START, PPR_LEN>(l_field_bits);
- // Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(PPR_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for PPR") );
- // Decoding bits 1~0 (Signal loading)
- l_spd_buffer.extractToRight<SEC_SIGNAL_LOAD_START, SEC_SIGNAL_LOAD_LEN>(l_sec_signal_loading);
-
- // Check to assure SPD DRAM signal loading conforms to JEDEC SPEC
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sec_signal_loading == SUPPORTED_VALUE),
- BYTE_INDEX,
- l_sec_signal_loading,
- "Failed check for SPD DRAM signal loading") );
-
- // Decoding bits 3~2 (Density Ratio)
- l_spd_buffer.extractToRight<DENSITY_RATIO_START, DENSITY_RATIO_LEN>(l_density_ratio);
-
- // Check to assure SPD density ratio bits are 0 to assure symmetical package
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_density_ratio == SUPPORTED_VALUE),
- BYTE_INDEX,
- l_density_ratio,
- "Failed check for SPD DRAM density ratio") );
-
- // Decoding bits 6~4 (Die Count)
- l_spd_buffer.extractToRight<SEC_DIE_COUNT_START, SEC_DIE_COUNT_LEN>(l_sec_die_count);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sec_die_count == SUPPORTED_VALUE),
- BYTE_INDEX,
- l_sec_die_count,
- "Failed check for SPD DRAM secondary die count") );
-
- // Decoding bit 7
- l_spd_buffer.extractToRight<SEC_PACKAGE_TYPE_START, SEC_PACKAGE_TYPE_LEN>(l_sec_package_type);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- (l_sec_package_type == SUPPORTED_VALUE),
- BYTE_INDEX,
- l_sec_package_type,
- "Failed check for SPD DRAM secondary package type") );
-
- // Printed decoded info
- FAPI_INF("Signal Loading: %d, DRAM Density Ratio: %d, Die Count: %d, SDRAM Package Type: %d",
- l_sec_signal_loading,
- l_density_ratio,
- l_sec_die_count,
- l_sec_package_type);
+ FAPI_DBG("%s. Post Package Repair (PPR): %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
+
///
-/// @brief Decode Module Nominal Voltage, VDD
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Secondary SDRAM signal loading
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing signal loading type
/// @return fapi2::ReturnCode
-/// @note SPD Byte 11
+/// @note SPD Byte 10 (bits 1~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::module_nominal_voltage(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::sec_sdram_signal_loading(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 11;
- const size_t RESERVED = 0; // per JEDEC sepc
- const size_t SUPPORTED = 1; // per JEDEC sepc
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
- // Byte variables used for decoding
- uint8_t l_operable = 0;
- uint8_t l_endurant = 0;
- uint8_t l_reserved = 0;
+ constexpr size_t BYTE_INDEX = 10;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Attribute variables used to set decoded vals
- uint64_t l_operable_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SEC_SIGNAL_LOAD_START, SEC_SIGNAL_LOAD_LEN>(l_field_bits);
- // Decoding bits 0 (Operable)
- l_spd_buffer.extractToRight<OPERABLE_START, OPERABLE_LEN>(l_operable);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(SEC_SIGNAL_LOADING_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for SDRAM Row Address Bits") );
- // DDR4 only supports 1.2 V, if not OPERABLE at this voltage than fail IPL
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_operable == SUPPORTED,
- BYTE_INDEX,
- l_operable,
- "Failed check for OPERABLE module nominal voltage") );
- // Decoding bits 1 (Endurant)
- l_spd_buffer.extractToRight<ENDURANT_START, ENDURANT_LEN>(l_endurant);
+ FAPI_DBG("%s. Number of Row Address Bits: %d",
+ mss::c_str(i_target),
+ o_value);
- // OPERABLE at 1.2V implies ENDURANT at 1.2V
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_endurant == SUPPORTED,
- BYTE_INDEX,
- l_endurant,
- "Failed check for ENDURABLE module nominal voltage") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Decoding bits 7~2 (Reserved)
- l_spd_buffer.extractToRight<NOM_VOLT_START, NOM_VOLT_LEN>(l_reserved);
+///
+/// @brief Decodes Secondary DRAM Density Ratio
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value raw bits from SPD
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 10 (bits 3~2)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::sec_dram_density_ratio(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for module nominal voltage RESERVED bits");
+ constexpr size_t BYTE_INDEX = 10;
+ constexpr size_t UNDEFINED = 3; // JEDEC map doesn't go beyond 3
- // Retrive entire MCS level attribute
- FAPI_TRY(spd_module_nominal_voltage(l_target_mcs, &l_operable_attrs[0][0]));
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Update attribute to decoded byte values
- l_operable_attrs[PORT_NUM][DIMM_NUM] = l_operable;
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_SPD_MODULE_NOMINAL_VOLTAGE, l_target_mcs, l_operable_attrs) );
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Printed decoded info
- FAPI_INF( "%s Operable: %d, Endurant: %d, Reserved: %d",
- c_str(i_target_dimm),
- l_operable,
- l_endurant,
- l_reserved );
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<DENSITY_RATIO_START, DENSITY_RATIO_LEN>(l_field_bits);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ l_field_bits != UNDEFINED,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for DRAM Density Ratio") );
+
+ FAPI_DBG("%s. DRAM Density Ratio: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
+
}
///
-/// @brief Decode Module Organization
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Secondary SDRAM die count
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value die count
/// @return fapi2::ReturnCode
-/// @note SPD Byte 12
+/// @note SPD Byte 10 (bits 6~4)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::module_organization(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::sec_sdram_die_count(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 12;
- const size_t RESERVED = 0;
- // SDRAM device width mapping limits
- const size_t MAX_DEV_WIDTH_VALID_KEY = 3; // All others reserved
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Number of package ranks per DIMM mapping limits
- const size_t MAX_PKG_RANKS_VALID_KEY = 7; // max supported packages
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Rank mix limits
- const size_t SYMMETRICAL = 0; // asymmetical not supported
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SEC_DIE_COUNT_START, SEC_DIE_COUNT_LEN>(l_field_bits);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(SEC_DIE_COUNT_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Secondary Die Count") );
- // Byte variables used for decoding
- uint8_t l_device_width = 0;
- uint8_t l_num_pkgs_ranks = 0;
- uint8_t l_rank_mix = 0;
- uint8_t l_reserved = 0;
+ FAPI_DBG("%s. Secondary Die Count: %d",
+ mss::c_str(i_target),
+ o_value);
- // Attribute variables used to set decoded vals
- uint8_t l_sdram_device_widths[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_num_pkg_ranks_per_dimm[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- uint8_t l_rank_mixes[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+fapi_try_exit:
+ return fapi2::current_err;
+}
+///
+/// @brief Decodes Secondary SDRAM package type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing package type
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 10 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::sec_sdram_package_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ constexpr size_t BYTE_INDEX = 5;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Decoding Bits 2~0
- l_spd_buffer.extractToRight<SDRAM_WIDTH_START, SDRAM_WIDTH_LEN>(l_device_width);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_device_width <= MAX_DEV_WIDTH_VALID_KEY,
- BYTE_INDEX,
- l_device_width,
- "Failed check for SDRAM device width") );
- // Decoding Bits 5~3
- l_spd_buffer.extractToRight<PACKAGE_RANKS_START, PACKAGE_RANKS_LEN>(l_num_pkgs_ranks);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_num_pkgs_ranks <= MAX_PKG_RANKS_VALID_KEY,
- BYTE_INDEX,
- l_num_pkgs_ranks,
- "Failed check for number of packages per DIMM") );
- // Decoding Bit 6
- l_spd_buffer.extractToRight<RANK_MIX_START, RANK_MIX_LEN>(l_rank_mix);
-
- // We only support symmetrical rank mix
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_rank_mix == SYMMETRICAL,
- BYTE_INDEX,
- l_rank_mix,
- "Failed check for number of packages per DIMM") );
- // Decoding Bit 7
- l_spd_buffer.extractToRight<MODULE_ORG_RESERVED_START, MODULE_ORG_RESERVED_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for number of packages per DIMM");
-
- // Retrive entire MCS level attribute
- FAPI_TRY(eff_dram_width(l_target_mcs, &l_sdram_device_widths[0][0]));
- FAPI_TRY(eff_num_packages_per_rank(l_target_mcs, &l_num_pkg_ranks_per_dimm[0][0]));
- FAPI_TRY(eff_dram_rank_mix(l_target_mcs, &l_rank_mixes[0][0]));
-
- // Update attribute to decoded byte values
- l_sdram_device_widths[PORT_NUM][DIMM_NUM] = device_type_map[l_device_width];
- l_num_pkg_ranks_per_dimm[PORT_NUM][DIMM_NUM] = num_pkgs_ranks_per_dimm_map[l_num_pkgs_ranks];
- l_rank_mixes[PORT_NUM][DIMM_NUM] = l_rank_mix;
-
- // Update MCS level attribute
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_WIDTH, l_target_mcs, l_sdram_device_widths) );
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_PACKAGES_PER_RANK, l_target_mcs, l_num_pkg_ranks_per_dimm) );
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RANK_MIX, l_target_mcs, l_rank_mixes) );
-
- // Printed decoded info
- FAPI_INF( "%s. Device Width: %d, Number of rank packages per DIMM: %d, Rank Mix: %d",
- c_str(i_target_dimm),
- l_sdram_device_widths[PORT_NUM][DIMM_NUM],
- l_num_pkg_ranks_per_dimm[PORT_NUM][DIMM_NUM],
- l_rank_mixes[PORT_NUM][DIMM_NUM] );
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SEC_PACKAGE_TYPE_START, SEC_PACKAGE_TYPE_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(SEC_PACKAGE_TYPE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Secondary Package Type") );
+
+ FAPI_DBG("%s. Secondary Package Type: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
-//TODO
-// Returning correct stuff (bits) ?? Or am I supposed to calc "Module DRAM Capacity" pg 27
///
-/// @brief Decode Module Memory Bus Width
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode Module Nominal Voltage, VDD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing if 1.2V is operable
/// @return fapi2::ReturnCode
-/// @note SPD Byte 13
+/// @note SPD Byte 11 (bit 0)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::module_memory_bus_width(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::operable_nominal_voltage(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 13;
- const size_t RESERVED = 0;
- // Primary bus width mapping limits
- const size_t MAX_PRIM_BUS_WIDTH_KEY = 3; // All others reserved
+ constexpr size_t BYTE_INDEX = 11;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Bus width extention mapping limits
- const size_t MAX_VALID_BUS_WIDTH_EXT_KEY = 1; // All others reserved
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<OPERABLE_START, OPERABLE_LEN>(l_field_bits);
- // Byte variables used for decoding
- uint8_t l_bus_width = 0;
- uint8_t l_bus_width_ext = 0;
- uint8_t l_reserved = 0;
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(OPERABLE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Endur") );
- // Attribute variables used to set decoded vals
- uint8_t l_module_bus_widths[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_DBG("%s. Operable: %d",
+ mss::c_str(i_target),
+ o_value);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode Module Nominal Voltage, VDD
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value enum representing if 1.2V is endurant
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 11 (bit 1)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::endurant_nominal_voltage(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+
+ constexpr size_t BYTE_INDEX = 11;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Decoding Bits 2~0
- l_spd_buffer.extractToRight<BUS_WIDTH_START, BUS_WIDTH_LEN>(l_bus_width);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_bus_width <= MAX_PRIM_BUS_WIDTH_KEY,
- BYTE_INDEX,
- l_bus_width,
- "Failed check on primary bus width") );
- // Decoding Bits 4~3
- l_spd_buffer.extractToRight<BUS_EXT_WIDTH_START, BUS_EXT_WIDTH_LEN>(l_bus_width_ext);
-
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_bus_width_ext <= MAX_VALID_BUS_WIDTH_EXT_KEY,
- BYTE_INDEX,
- l_bus_width_ext,
- "Failed check for bus width extension") );
- // Decoding bits Bits 7~5
- l_spd_buffer.extractToRight<BUS_WIDTH_RESERVED_START, BUS_WIDTH_RESERVED_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for bus width reserved bits");
-
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_module_bus_width(l_target_mcs, &l_module_bus_widths[0][0]) );
-
- // Update attribute to decoded byte values
- l_module_bus_widths[PORT_NUM][DIMM_NUM] = prim_bus_width_map[l_bus_width] + bus_width_ext_map[l_bus_width_ext];
-
- // Update MCS level attribute
- FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_MODULE_BUS_WIDTH, l_target_mcs, l_module_bus_widths);
-
- // Printed decoded info
- FAPI_INF( "%s Module Memory Bus Width (in bits): %d, Primary bus width: %d, Bus width extension: %d",
- c_str(i_target_dimm),
- l_module_bus_widths[PORT_NUM][DIMM_NUM],
- prim_bus_width_map[l_bus_width],
- bus_width_ext_map[l_bus_width_ext] );
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<ENDURANT_START, ENDURANT_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(ENDURANT_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Endurant") );
+
+ FAPI_DBG("%s. Endurant: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
-
///
-/// @brief Decode Module Thermal Sensor
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM device width
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value device width in bits
/// @return fapi2::ReturnCode
-/// @note SPD Byte 14, no attribute found for this
+/// @note SPD Byte 12 (bits 2~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::module_thermal_sensor(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::device_width(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 14;
- const size_t VALID_VALUE = 1;
- const size_t RESERVED = 0;
- // Byte variables used for decoding
- uint8_t l_reserved = 0;
- uint8_t l_thermal_sensor = 0;
+ constexpr size_t BYTE_INDEX = 12;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Attribute variables used to set decoded vals
- uint8_t l_therm_sensors[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<SDRAM_WIDTH_START, SDRAM_WIDTH_LEN>(l_field_bits);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(DEVICE_WIDTH_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Device Width") );
- // Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ FAPI_DBG("%s. Device Width: %d",
+ mss::c_str(i_target),
+ o_value);
- // Decoding Bits 6~0
- l_spd_buffer.extractToRight<THERM_SENSOR_RESERV_START, THERM_SENSOR_RESERV_LEN>(l_reserved);
+fapi_try_exit:
+ return fapi2::current_err;
+}
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for thermal sensor reserved bits");
- // Decoding bits Bit 7
- l_spd_buffer.extractToRight<THERM_SENSOR_START, THERM_SENSOR_LEN>(l_thermal_sensor);
- // Length is a single bit (0 or 1), anything larger means corrupt data
- FAPI_TRY( mss::check::spd::valid_value_fail(i_target_dimm,
- l_thermal_sensor <= VALID_VALUE,
- BYTE_INDEX,
- l_thermal_sensor,
- "Failed check for thermal sensor") );
+///
+/// @brief Decodes number of package ranks per DIMM
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value number of package ranks per DIMM
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 12 (bits 5~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::num_package_ranks_per_dimm(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
- // Retrive entire MCS level attribute
- FAPI_TRY( spd_module_thermal_sensor(l_target_mcs, &l_therm_sensors[0][0]) );
+ constexpr size_t BYTE_INDEX = 12;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Update attribute to decoded byte values
- l_therm_sensors[PORT_NUM][DIMM_NUM] = l_thermal_sensor;
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Update MCS level attribute
- FAPI_ATTR_SET(fapi2::ATTR_SPD_MODULE_THERMAL_SENSOR, l_target_mcs, l_therm_sensors);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<PACKAGE_RANKS_START, PACKAGE_RANKS_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(NUM_PACKAGE_RANKS_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Num Package Ranks Per DIMM") );
- // Printed decoded info
- FAPI_INF("%s. Thermal sensor: %d, Reserved: %d",
- c_str(i_target_dimm),
- l_thermal_sensor,
- l_reserved );
+ FAPI_DBG("%s. Num Package Ranks per DIMM: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Decode Extended Module Type
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Rank Mix
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value rank mix value from SPD
/// @return fapi2::ReturnCode
-/// @note SPD Byte 15, no attribute for this byte
+/// @note SPD Byte 12 (bit 6)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::extended_module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::rank_mix(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 15;
- const size_t RESERVED = 0;
- // Byte variables used for decoding
- uint8_t l_ext_module_type = 0;
- uint8_t l_reserved = 0;
+ constexpr size_t BYTE_INDEX = 12;
+ constexpr size_t INVALID_VALUE = 2;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
+
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_raw_byte);
- // Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<RANK_MIX_START, RANK_MIX_LEN>(l_field_bits);
- // Decoding Bits 3~0
- l_spd_buffer.extractToRight<EXT_MOD_TYPE_START, EXT_MOD_TYPE_LEN>(l_ext_module_type);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_field_bits < INVALID_VALUE),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Rank Mix") );
- // According to JEDEC spec this value should be coded as 0000 which is the value as the reserved bits
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- l_ext_module_type == RESERVED,
- BYTE_INDEX,
- l_ext_module_type,
- "Failed check for extended base module type") );
- // Decoding Bit 7~4
- l_spd_buffer.extractToRight<EXT_MOD_TYPE_RESERV_START, EXT_MOD_TYPE_RESERV_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for extended module type reserved bits");
-
- // Printed decoded info
- FAPI_INF("%s. Extended Base Module Type: %d, Reserved: %d",
- c_str(i_target_dimm),
- l_ext_module_type,
- l_reserved );
+ o_value = l_field_bits;
+
+ FAPI_DBG("%s. Rank Mix: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
+
///
-/// @brief Decode Timebases
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes primary bus width
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value primary bus width in bits
/// @return fapi2::ReturnCode
-/// @note SPD Byte 17
+/// @note SPD Byte 13 (bits 2~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 27
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::timebases(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::prim_bus_width(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 17;
- const size_t RESERVED = 0;
+ constexpr size_t BYTE_INDEX = 13;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Medium timebase mapping limits
- const int64_t MAX_VALID_MTB_KEY = 1; // All others reserved
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Fine timebase mapping limits
- const int64_t MAX_VALID_FTB_KEY = 1; // All others reserved
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BUS_WIDTH_START, BUS_WIDTH_LEN>(l_field_bits);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BUS_WIDTH_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Primary Bus Width") );
- // Byte variables used for decoding
- int64_t l_fine_timebase = 0;
- int64_t l_medium_timebase = 0;
- int64_t l_reserved = 0;
+ FAPI_DBG("%s. Primary Bus Width: %d",
+ mss::c_str(i_target),
+ o_value);
- // Attribute variables used to set decoded vals
- int64_t l_FTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_MTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+///
+/// @brief Decodes bus width extension
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value bus width extension in bits
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 13 (bits 2~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 28
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::bus_width_extension(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 13;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
// Buffer used for bit manipulation
- fapi2::buffer<uint8_t> l_spd_buffer(i_spd_data[BYTE_INDEX]);
-
- // TODO - update ENUMS to take account to int64_t
- // Decoding Bits 1~0
- l_spd_buffer.extractToRight<FINE_TIMEBASE_START, FINE_TIMEBASE_LEN>(l_fine_timebase);
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- l_fine_timebase < MAX_VALID_FTB_KEY,
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- l_fine_timebase,
- "Failed check for fine timebase") );
- // Decoding Bits 3~2
- l_spd_buffer.extractToRight<MED_TIMEBASE_START, MED_TIMEBASE_LEN>(l_medium_timebase);
+ l_raw_byte);
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- l_medium_timebase < MAX_VALID_MTB_KEY,
- BYTE_INDEX,
- l_medium_timebase,
- "Failed check for medium timebase") );
- // Decoding bits Bits 7~4
- l_spd_buffer.extractToRight<TIMEBASE_RESERV_START, TIMEBASE_RESERV_LEN>(l_reserved);
-
- mss::check::spd::valid_value_warn(i_target_dimm,
- l_reserved == RESERVED,
- BYTE_INDEX,
- l_reserved,
- "Failed check for timebases reserved bits");
-
- // Retrive entire MCS level attribute
- FAPI_TRY( spd_fine_timebase(l_target_mcs, &l_FTBs[0][0]) );
- FAPI_TRY( spd_medium_timebase(l_target_mcs, &l_MTBs[0][0]) );
-
- // Update attribute to decoded byte values
- l_FTBs[PORT_NUM][DIMM_NUM] = fine_timebase_map[l_fine_timebase];
- l_MTBs[PORT_NUM][DIMM_NUM] = medium_timebase_map[l_medium_timebase];
-
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_SPD_FINE_TIMEBASE, l_target_mcs, l_FTBs );
- FAPI_ATTR_SET( fapi2::ATTR_SPD_MEDIUM_TIMEBASE, l_target_mcs, l_MTBs );
-
- // Printed decoded info
- FAPI_INF( "%s. Fine Timebase: %d, Medium Timebase: %d",
- c_str(i_target_dimm),
- l_FTBs[PORT_NUM][DIMM_NUM],
- l_MTBs[PORT_NUM][DIMM_NUM] );
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<BUS_EXT_WIDTH_START, BUS_EXT_WIDTH_LEN>(l_field_bits);
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(BUS_WIDTH_EXT_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Bus Width Extension") );
+
+ FAPI_DBG("%s. Bus Width Extension (bits): %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
+
///
-/// @brief Decode SDRAM Minimum Cycle Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode Module Thermal Sensor
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value thermal sensor value from SPD
/// @return fapi2::ReturnCode
-/// @note SPD Byte 18 & Byte 125
-/// This byte depends on the fine & medium timebase values
-/// obtained from Byte 17
+/// @note SPD Byte 14 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 28
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::min_cycle_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::thermal_sensor(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MTB = 18; // min cycle medium timebase (mtb)
- const size_t BYTE_INDEX_FTB = 125; // min cycle fine timebase (ftb)
- const int64_t MIN_CYCLE_TIME_MTB = 1; // from JEDEC
- const int64_t MAX_CYCLE_TIME_MTB = 255; // from JEDEC
+ constexpr size_t BYTE_INDEX = 14;
+ constexpr size_t INVALID_VALUE = 2; // single bit value 0 or 1
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- const int64_t MIN_CYCLE_TIME_FTB = -128; // from JEDEC
- const int64_t MAX_CYCLE_TIME_FTB = 127; // from JEDEC
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<THERM_SENSOR_START, THERM_SENSOR_LEN>(l_field_bits);
- // Byte variables used for decoding
- int64_t l_tCKmin_mtb = 0;
- int64_t l_tCKmin_ftb = 0;
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ l_field_bits < INVALID_VALUE,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Thermal Sensor") );
+ o_value = l_field_bits;
- // Attribute variables
- int64_t l_min_cycle_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_MTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_FTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_DBG("%s. Thermal Sensor: %d",
+ mss::c_str(i_target),
+ o_value);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_MTB,
- i_spd_data[BYTE_INDEX_MTB]);
-
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_FTB,
- i_spd_data[BYTE_INDEX_FTB]);
-
- // Retrieve SDRAM Maximum Cycle Time
- l_tCKmin_mtb = i_spd_data[BYTE_INDEX_MTB];
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tCKmin_mtb <= MAX_CYCLE_TIME_MTB) &&
- (l_tCKmin_mtb >= MIN_CYCLE_TIME_MTB),
- BYTE_INDEX_MTB,
- l_tCKmin_mtb,
- "Failed check for tCKmin (min cycle time) in MTB units") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Retrieve Fine Offset for SDRAM Minimum Cycle Time
- // casted int8_t undoes 2's complement on the uint8_t spd data
- l_tCKmin_ftb = int8_t(i_spd_data[BYTE_INDEX_FTB]);
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tCKmin_ftb <= MAX_CYCLE_TIME_FTB) &&
- (l_tCKmin_ftb >= MIN_CYCLE_TIME_FTB),
- BYTE_INDEX_FTB,
- l_tCKmin_ftb,
- "Failed check for tCKmin (min cycle time) in FTB units") );
-
-
- // Retrieving medium timebase (MTB) multiplier used for timing calculation
- FAPI_TRY( spd_medium_timebase(l_target_mcs, &l_MTBs[0][0]) );
- FAPI_TRY( spd_fine_timebase(l_target_mcs, &l_FTBs[0][0]) );
-
- // Retrive entire MCS level attribute
- FAPI_TRY( spd_timing_tckmin(l_target_mcs, &l_min_cycle_times[0][0]) );
-
- // Update attribute to decoded byte values
- // Calculating minimum cycle time in picosconds
- l_min_cycle_times[PORT_NUM][DIMM_NUM] = calc_timing(l_tCKmin_mtb,
- l_tCKmin_ftb,
- l_MTBs[PORT_NUM][DIMM_NUM],
- l_FTBs[PORT_NUM][DIMM_NUM]);
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_TIMING_TCKMIN, l_target_mcs, l_min_cycle_times );
-
- // Printed decoded info
- FAPI_INF("%s. tCKmin (min cycle time): %d (ps)",
- c_str(i_target_dimm),
- l_min_cycle_times[PORT_NUM][DIMM_NUM] );
+///
+/// @brief Decode Extended Base Module Type
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value raw data from SPD
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 15 (bits 3~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 28
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::extended_base_module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint8_t& o_value)
+{
+
+ constexpr size_t BYTE_INDEX = 15;
+ constexpr size_t RESERVED = 0;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
+
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
+
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<EXT_MOD_TYPE_START, EXT_MOD_TYPE_LEN>(l_field_bits);
+
+ // Currently reserved to 0b000
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ l_field_bits == RESERVED,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Extended Base Module Type") );
+ o_value = l_field_bits;
+
+ FAPI_DBG("%s. Extended Base Module Type: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
+
///
-/// @brief Decode SDRAM Maximum Cycle Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decode Fine Timebase
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value fine_timebase from SPD in picoseconds
/// @return fapi2::ReturnCode
-/// @note SPD Byte 19 and 124
+/// @note SPD Byte 17 (bits 1~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 29
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::max_cycle_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_timebase(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MTB = 19; // min cycle medium timebase (mtb)
- const size_t BYTE_INDEX_FTB = 124; // min cycle fine timebase (ftb)
- const int64_t MIN_CYCLE_TIME_MTB = 1; // from JEDEC
- const int64_t MAX_CYCLE_TIME_MTB = 255; // from JEDEC
+ constexpr size_t BYTE_INDEX = 17;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- const int64_t MIN_CYCLE_TIME_FTB = -128; // from JEDEC
- const int64_t MAX_CYCLE_TIME_FTB = 127; // from JEDEC
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<FINE_TIMEBASE_START, FINE_TIMEBASE_LEN>(l_field_bits);
- // Byte variables used for decoding
- int64_t l_tCKmax_mtb = 0;
- int64_t l_tCKmax_ftb = 0;
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(FINE_TIMEBASE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Fine Timebase") );
- // Attribute variable
- int64_t l_max_cycle_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_MTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_FTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ FAPI_DBG("%s. Fine Timebase: %d",
+ mss::c_str(i_target),
+ o_value);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_MTB,
- i_spd_data[BYTE_INDEX_MTB]);
-
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_FTB,
- i_spd_data[BYTE_INDEX_FTB]);
-
- // Retrieve SDRAM Maximum Cycle Time
- l_tCKmax_mtb = i_spd_data[BYTE_INDEX_MTB];
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tCKmax_mtb <= MAX_CYCLE_TIME_MTB) &&
- (l_tCKmax_mtb >= MIN_CYCLE_TIME_MTB),
- BYTE_INDEX_MTB,
- l_tCKmax_mtb,
- "Failed check for tCKmin (min cycle time) in MTB units") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Retrieve Fine Offset for SDRAM Maximum Cycle Time
- // casted int8_t undoes 2's complement on the uint8_t spd data
- l_tCKmax_ftb = int8_t(i_spd_data[BYTE_INDEX_FTB]);
+///
+/// @brief Decode Medium Timebase
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value medium timebase from SPD in picoseconds
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 17 (bits 3~2)
+/// @note Item JC-45-2220.01x
+/// @note Page 29
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::medium_timebase(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
+{
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tCKmax_ftb <= MAX_CYCLE_TIME_FTB) &&
- (l_tCKmax_ftb >= MIN_CYCLE_TIME_FTB),
- BYTE_INDEX_FTB,
- l_tCKmax_ftb,
- "Failed check for tCKmin (min cycle time) in FTB units") );
+ constexpr size_t BYTE_INDEX = 17;
+ uint8_t l_raw_byte = i_spd_data[BYTE_INDEX];
+ uint8_t l_field_bits = 0;
- // Retrieving medium timebase (MTB) multiplier used for timing calculation
- FAPI_TRY( spd_medium_timebase(l_target_mcs, &l_MTBs[0][0]) );
- FAPI_TRY( spd_fine_timebase(l_target_mcs, &l_FTBs[0][0]) );
+ // Buffer used for bit manipulation
+ fapi2::buffer<uint8_t> l_spd_buffer(l_raw_byte);
- // Retrive entire MCS level attribute
- FAPI_TRY(spd_timing_tckmax(l_target_mcs, &l_max_cycle_times[0][0]))
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_raw_byte);
- // Update attribute to decoded byte values
- l_max_cycle_times[PORT_NUM][DIMM_NUM] = calc_timing(l_tCKmax_mtb,
- l_tCKmax_ftb,
- l_MTBs[PORT_NUM][DIMM_NUM],
- l_FTBs[PORT_NUM][DIMM_NUM]);
+ // Extracting desired bits
+ l_spd_buffer.extractToRight<MED_TIMEBASE_START, MED_TIMEBASE_LEN>(l_field_bits);
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_TIMING_TCKMAX, l_target_mcs, l_max_cycle_times );
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ mss::find_value_from_key(MEDIUM_TIMEBASE_MAP, l_field_bits, o_value),
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed check for Medium Timebase") );
- // Printed decoded info
- FAPI_INF("%s. tCKmax (max cycle time): %d (ps)",
- c_str(i_target_dimm),
- l_max_cycle_times[PORT_NUM][DIMM_NUM] );
+ FAPI_DBG("%s. Medium Timebase: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
+
///
-/// @brief Decode Minimum CAS Latency Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Cycle Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCKmin in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte 24 & 123
+/// @note SPD Byte 18
+/// @note Item JC-45-2220.01x
+/// @note Page 31-32
+/// @note DDR4 SPD Document Release 3
+/// @warning If tCKmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tCKmin (SPD byte 125)
+/// used for correction to get the actual value.
///
-fapi2::ReturnCode decoder::min_cas_latency_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_cycle_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MTB = 24; // min cycle medium timebase (mtb)
- const size_t BYTE_INDEX_FTB = 123; // min cycle fine timebase (ftb)
+ constexpr size_t BYTE_INDEX = 18;
- const int64_t MIN_CYCLE_TIME_MTB = 1; // from JEDEC
- const int64_t MAX_CYCLE_TIME_MTB = 255; // from JEDEC
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- const int64_t MIN_CYCLE_TIME_FTB = -128; // from JEDEC
- const int64_t MAX_CYCLE_TIME_FTB = 127; // from JEDEC
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: %d.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_timing_val);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the min cycle time (tckmin) in MTB") );
- // Byte variables used for decoding
- int64_t l_tAAmin_mtb = 0;
- int64_t l_tAAmin_ftb = 0;
+ FAPI_DBG("%s. Minimum Cycle Time (tCKmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Attribute variable
- int64_t l_min_cas_latency_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_MTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
- int64_t l_FTBs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_MTB,
- i_spd_data[BYTE_INDEX_MTB]);
-
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX_FTB,
- i_spd_data[BYTE_INDEX_FTB]);
-
- // Retrieve SDRAM Minimum CAS Latency Time
- l_tAAmin_mtb = i_spd_data[BYTE_INDEX_MTB];
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tAAmin_mtb <= MAX_CYCLE_TIME_MTB) &&
- (l_tAAmin_mtb >= MIN_CYCLE_TIME_MTB),
- BYTE_INDEX_MTB,
- l_tAAmin_mtb,
- "Failed check for min CAS latency time (tAAmin) in MTB units") );
-
- // Retrieve Fine Offset for Minimum CAS Latency Time
- // casted int8_t undoes 2's complement on the uint8_t spd data
- l_tAAmin_ftb = int8_t(i_spd_data[BYTE_INDEX_FTB]);
-
- FAPI_TRY(mss::check::spd::valid_value_fail(i_target_dimm,
- (l_tAAmin_ftb <= MAX_CYCLE_TIME_FTB) &&
- (l_tAAmin_ftb >= MIN_CYCLE_TIME_FTB),
- BYTE_INDEX_FTB,
- l_tAAmin_ftb,
- "Failed check for min CAS latency time (tAAmin) in FTB units") );
-
- // Retrieving medium timebase (MTB) multiplier used for timing calculation
- FAPI_TRY( spd_medium_timebase(l_target_mcs, &l_MTBs[0][0]) );
- FAPI_TRY( spd_fine_timebase(l_target_mcs, &l_FTBs[0][0]) );
-
- // Retrive entire MCS level attribute
- FAPI_TRY(spd_timing_taamin(l_target_mcs, &l_min_cas_latency_times[0][0]))
-
- // Update attribute to decoded byte values
- l_min_cas_latency_times[PORT_NUM][DIMM_NUM] = calc_timing(l_tAAmin_mtb,
- l_tAAmin_ftb,
- l_MTBs[PORT_NUM][DIMM_NUM],
- l_FTBs[PORT_NUM][DIMM_NUM]);
-
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_TIMING_TAAMIN, l_target_mcs, l_min_cas_latency_times );
-
- // Printed decoded info
- FAPI_INF("%s. tAAmin (min cycle time): %d (ps)",
- c_str(i_target_dimm),
- l_min_cas_latency_times[PORT_NUM][DIMM_NUM] );
+///
+/// @brief Decodes SDRAM Maximum Cycle Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCKmax in MTB units
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 19
+/// @note Item JC-45-2220.01x
+/// @note Page 32
+/// @note DDR4 SPD Document Release 3
+/// @warning If tCKmax cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tCKmax (SPD byte 124)
+/// used for correction to get the actual value.
+///
+fapi2::ReturnCode decoder::max_cycle_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 19;
+
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
+
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: %d.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_timing_val);
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the max cycle time (tckmax) in MTB") );
+
+ FAPI_DBG("%s. Maximum Cycle Time (tCKmax) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
return fapi2::current_err;
}
-#if 0
///
/// @brief Decode CAS Latencies Supported
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value bitmap of supported CAS latencies
/// @return fapi2::ReturnCode
-/// @note SPD Byte 20-23
+/// @note SPD Bytes 20-23
+/// @note Item JC-45-2220.01x
+/// @note Page 33-34
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::supported_cas_latencies(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::supported_cas_latencies(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint64_t& o_value)
{
- // Immutable constants
- const size_t FIRST_BYTE = 20;
- const size_t SEC_BYTE = 21;
- const size_t THIRD_BYTE = 22;
- const size_t FORTH_BYTE = 23;
+ constexpr size_t FIRST_BYTE = 20;
+ constexpr size_t SEC_BYTE = 21;
+ constexpr size_t THIRD_BYTE = 22;
+ constexpr size_t FOURTH_BYTE = 23;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ // Buffers used for bit manipulation
+ fapi2::buffer<uint64_t> l_buffer;
- // Byte variables used for decoding
- uint64_t l_supported_cas_lat = 0;
+ // Trace print in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ c_str(i_target),
+ FIRST_BYTE,
+ i_spd_data[FIRST_BYTE]);
+
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ c_str(i_target),
+ SEC_BYTE,
+ i_spd_data[SEC_BYTE]);
+
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ c_str(i_target),
+ THIRD_BYTE,
+ i_spd_data[THIRD_BYTE])
+
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ c_str(i_target),
+ FOURTH_BYTE,
+ i_spd_data[FOURTH_BYTE]);
+
+ // Combine Bytes to create bitmap - right aligned
+ l_buffer.insertFromRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(i_spd_data[FIRST_BYTE]).
+ insertFromRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(i_spd_data[SEC_BYTE]).
+ insertFromRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(i_spd_data[THIRD_BYTE]).
+ insertFromRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(i_spd_data[FOURTH_BYTE]);
+
+ // According to the JEDEC spec:
+ // Byte 23 bit 6 is reserved and must be coded as 0.
+ // Warn instead of fail because in last revision this was a reserved byte coded as 0x00
+ constexpr size_t BIT_START = 33; // relative position of bit 6 in byte 23 relative to uint64_t
+ constexpr size_t BIT_LEN = 1;
+
+ FAPI_TRY( mss::check::spd::
+ fail_for_invalid_value(i_target,
+ !(l_buffer.getBit<BIT_START, BIT_LEN>()),
+ FOURTH_BYTE,
+ i_spd_data[FOURTH_BYTE],
+ "Failed check on CAS latencies supported") );
+
+ // Update output value only if range check passes
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(o_value);
+
+ FAPI_DBG("%s. CAS latencies supported (bitmap): 0x%llX",
+ mss::c_str(i_target),
+ o_value);
- // Attribute variables used to set decoded vals
- uint64_t l_supported_CLs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+fapi_try_exit:
+ return fapi2::current_err;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_first_byte_buff(i_spd_data[FIRST_BYTE]);
- fapi2::buffer<uint8_t> l_second_byte_buff(i_spd_data[SEC_BYTE]);
- fapi2::buffer<uint8_t> l_third_byte_buff(i_spd_data[THIRD_BYTE]);
- fapi2::buffer<uint8_t> l_forth_byte_buff(i_spd_data[FORTH_BYTE]);
+}
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+///
+/// @brief Decodes SDRAM Minimum CAS Latency Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tAAmin in MTB units
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 24
+/// @note Item JC-45-2220.01x
+/// @note Page 34
+/// @note DDR4 SPD Document Release 3
+/// @warning If tAAmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tAAmin (SPD byte 123)
+/// used for correction to get the actual value.
+///
+fapi2::ReturnCode decoder::min_cas_latency_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
+{
+ constexpr size_t BYTE_INDEX = 24;
- // TODO - update ENUMS to take account to int64_t
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Combine Bytes 20 - 23 to create bitmap
- l_first_byte_buff.extractToRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(l_supported_cas_lat).
- l_second_byte_buff.extractToRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(l_supported_cas_lat).
- l_third_byte_buff.extractToRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(l_supported_cas_lat).
- l_forth_byte_buff.extractToRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(l_supported_cas_lat);
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( cas_latencies_supported(l_target_mcs, &l_supported_CLs[0][0]) );
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ l_timing_val);
- // Update attribute to decoded byte values
- l_supported_CLs[PORT_NUM][DIMM_NUM] = l_supported_cas_lat;
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum CAS Latency Time (tAAmin) in MTB") );
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_SPD_CAS_LATENCIES_SUPPORTED, l_target_mcs, l_supported_CLs );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
-}
+ // Only update output if it passes check
+ o_value = l_timing_val;
+ FAPI_DBG("%s. Minimum CAS Latency Time (tAAmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+fapi_try_exit:
+ return fapi2::current_err;
+}
///
-/// @brief Decode Minimum RAS to CAS Delay Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRCDmin in MTB units
/// @return fapi2::ReturnCode
/// @note SPD Byte 25
+/// @note Item JC-45-2220.01x
+/// @note Page 35
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRCDmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRCDmin (SPD byte 122)
+/// used for correction to get the actual value
///
-fapi2::ReturnCode decoder::min_ras_to_cas_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_ras_to_cas_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 25;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 25;
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Attribute variable (rcd = ras to cas delay)
- int64_t l_min_rcd_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_timing_val);
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum RAS to CAS Delay Time (tRCDmin) in MTB") );
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trcd(l_target_mcs, &l_min_rcd_times[0][0]) );
+ // Only update output if it passes check
+ o_value = l_timing_val;
- // Update attribute to decoded byte values
- l_min_rcd_times[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ FAPI_DBG("%s. Minimum RAS to CAS Delay Time (tRCDmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRCD, l_target_mcs, l_min_rcd_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Decode Minimum Row Precharge Delay Time
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRPmin in MTB units
/// @return fapi2::ReturnCode
/// @note SPD Byte 26
+/// @note Item JC-45-2220.01x
+/// @note Page 36-37
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRPmin cannot be divided evenly by the MTB,
+// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRPmin (SPD byte 121)
+/// used for correction to get the actual value
///
-fapi2::ReturnCode decoder::min_row_precharge_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_row_precharge_delay_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 26;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 26;
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Attribute variable (rp = row to precharge)
- int64_t l_min_rp_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Explicit conversion
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trp(l_target_mcs, &l_min_rp_times[0][0]) );
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Row Precharge Delay Time (tRPmin) in MTB") );
- // Update attribute to decoded byte values
- l_min_rp_times[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Only update output if it passes check
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRP, l_target_mcs, l_min_rp_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ FAPI_DBG("%s. Minimum Row Precharge Delay Time (tRPmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Decode Minimum Active to Precharge Delay Time (tRASmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRASmin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 27 Bits 3~0 along with Byte 28 Bits 7~0
+/// @note SPD Byte 27 (bits 3~0) & Byte 28 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 38
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::min_activate_to_precharge_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_active_to_precharge_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 27; // MSN = most significant byte
- const size_t BYTE_INDEX_LSB = 28; // LSB = least significant byte
+ // Lambda expression to retrieve tRASmin's most significant nibble (MSN)
+ auto tRASmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 27;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (tRAS = Active to Precharge Delay Time)
- int64_t l_tRASmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRASMIN_MSN_START, TRASMIN_MSN_LEN>(l_out);
- // Attribute variable
- int64_t l_min_ras_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSB]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // Lambda expression to retrieve tRASmin's least significant byte (LSB)
+ auto tRASmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 28;
+ uint8_t l_out = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TRASMIN_LSB_START, TRASMIN_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRASmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRASmin_LSB(i_target, i_spd_data) );
- // TODO - update ENUMS to take account to int64_t
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Combining bits to create timing value
- l_buffer_upper_nibble.extractToRight<TRASMIN_MSN_START, TRASMIN_MSN_LEN>(l_tRASmin);
- l_buffer_lower_byte.extractToRight<TRASMIN_LSB_START, TRASMIN_LSB_LEN>(l_tRASmin);
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_tras(l_target_mcs, &l_min_ras_times[0][0]) );
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
- // Update attribute to decoded byte values (returning picoseconds)
- l_min_ras_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRASmin);
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // But byte 28 of the JEDEC spec explains how to piece this together - AAM
+ constexpr size_t ERROR_BYTE_INDEX = 28;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRAS, l_target_mcs, l_min_ras_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Active to Precharge Delay Time (tRASmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_DBG("%s. Minimum Active to Precharge Delay Time (tRASmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Minimum Active to Active/Refresh Delay Time (tRCmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRCmin in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte Byte 27 Bits 7~4 along with Byte 29 Bits 7~0
+/// @note SPD Byte 27 (bits 7~4) & SPD Byte 29 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 38
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRCmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRCmin (SPD byte 120)
+/// used for correction to get the actual value.
///
-fapi2::ReturnCode
-decoder::min_activate_to_activate_refresh_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_active_to_active_refresh_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 27; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 28; // LSB = least significant byte
+ // Lambda expression to retrieve tRCmin's most significant nibble (MSN)
+ auto tRCmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 27;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (RC = Activate to Activate/Refresh Delay)
- uint16_t l_tRCmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRCMIN_MSN_START, TRCMIN_MSN_LEN>(l_out);
- // Attribute variable
- uint16_t l_min_rc_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tRCmin's least significant byte (LSB)
+ auto tRCmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 29;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Combining bits to create timing value
- l_buffer_upper_nibble.extractToRight<TRCMIN_MSN_START, TRCMIN_MSN_LEN>(l_tRCmin);
- l_buffer_lower_byte.extractToRight<TRCMIN_LSB_START, TRCMIN_LSB_LEN>(l_tRCmin);
+ // Extracting desired bits
+ l_buffer.extractToRight<TRCMIN_LSB_START, TRCMIN_LSB_LEN>(l_out);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_rc_times[0][0]) );
+ return l_out;
+ };
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_rc_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRCmin);
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRC, l_target_mcs, l_min_rc_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRCmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRCmin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
+
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
+
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // But byte 29 of the JEDEC spec explains how to piece this together - AAM
+ constexpr size_t ERROR_BYTE_INDEX = 29;
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_DBG("%s. Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Minimum Refresh Recovery Delay Time 1 (tRFC1min)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRFC1min in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte Byte 30 (LSB) along with Byte 31 (MSB)
+/// @note SPD Byte 30 & Byte 31
+/// @note Item JC-45-2220.01x
+/// @note Page 39-40
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_1(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_1(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 31; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 30; // LSB = least significant byte
+ // Lambda expression to retrieve tRFC1min's most significant byte (MSB)
+ auto tRFC1min_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 31;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (RFC1 = Minimum Refresh Recovery Delay Time)
- uint32_t l_tRFC1min = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC1MIN_MSB_START, TRFC1MIN_MSB_LEN>(l_out);
- // Attribute variable
- uint32_t l_min_rfc1_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_MSB(i_spd_data[BYTE_INDEX_MSB]);
- fapi2::buffer<uint8_t> l_buffer_LSB(i_spd_data[BYTE_INDEX_LSB]);
+ // Lambda expression to retrieve tRFC1min's least significant byte (LSB)
+ auto tRFC1min_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 30;
+ uint8_t l_out = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC1MIN_LSB_START, TRFC1MIN_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSB_START = 48;
+ constexpr size_t MSB_LEN = 8;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC1min_MSB(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRFC1min_LSB(i_target, i_spd_data) );
- // Combining bits to create timing value
- l_buffer_MSB.extractToRight<, >();
- l_buffer_LSB.extractToRight<, >();
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_rfc1_times[0][0]) );
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_rfc1_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRFC1min);
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRFC1, l_target_mcs, l_min_rfc1_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 30) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 30;
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_DBG("%s. Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum Refresh Recovery Delay Time 2 (tRFC2min)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRFC2min in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte Byte 32 (LSB) along with Byte 33 (MSB)
+/// @note SPD Byte 32 & Byte 33
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_2(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_2(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 33; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 32; // LSB = least significant byte
+ // Lambda expression to retrieve tRFC2min's most significant byte (MSB)
+ auto tRFC2min_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 33;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (RFC1 = Minimum Refresh Recovery Delay 2)
- uint32_t l_tRFC2min = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC2MIN_MSB_START, TRFC2MIN_MSB_LEN>(l_out);
- // Attribute variable
- uint32_t l_min_rfc2_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_MSB(i_spd_data[BYTE_INDEX_MSB]);
- fapi2::buffer<uint8_t> l_buffer_LSB(i_spd_data[BYTE_INDEX_LSB]);
+ // Lambda expression to retrieve tRFC2min's least significant byte (LSB)
+ auto tRFC2min_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 32;
+ uint8_t l_out = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC2MIN_LSB_START, TRFC2MIN_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSB_START = 48;
+ constexpr size_t MSB_LEN = 8;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC2min_MSB(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRFC2min_LSB(i_target, i_spd_data) );
- // Combining bits to create timing value
- l_buffer_MSB.extractToRight<, >();
- l_buffer_LSB.extractToRight<, >();
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_rfc2_times[0][0]) );
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_rfc1_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRFC2min);
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRFC2, l_target_mcs, l_min_rfc2_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 33) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 33;
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_DBG("%s. Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum Refresh Recovery Delay Time 4 (tRFC4min)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRFC4min in MTB units
/// @return fapi2::ReturnCode
-/// @note SPD Byte Byte 34 (LSB) along with Byte 5 (MSB)
+/// @note SPD Byte 34 & Byte 35
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_4(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_refresh_recovery_delay_time_4(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 35; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 34; // LSB = least significant byte
+ // Lambda expression to retrieve tRFC4min's most significant byte (MSB)
+ auto tRFC4min_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 35;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (RFC4 = Minimum Refresh Recovery Delay 4)
- uint32_t l_tRFC4min = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC4MIN_MSB_START, TRFC4MIN_MSB_LEN>(l_out);
- // Attribute variable
- uint32_t l_min_rfc4_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_MSB(i_spd_data[BYTE_INDEX_MSB]);
- fapi2::buffer<uint8_t> l_buffer_LSB(i_spd_data[BYTE_INDEX_LSB]);
+ // Lambda expression to retrieve tRFC4min's least significant byte (LSB)
+ auto tRFC4min_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 34;
+ uint8_t l_out = 0;
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TRFC4MIN_LSB_START, TRFC4MIN_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSB_START = 48;
+ constexpr size_t MSB_LEN = 8;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
- // Combining bits to create timing value
- l_buffer_MSB.extractToRight<, >();
- l_buffer_LSB.extractToRight<, >();
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC4min_MSB(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tRFC4min_LSB(i_target, i_spd_data) );
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_rfc4_times[0][0]) );
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_rfc1_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tRFC4min);
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRFC2, l_target_mcs, l_min_rfc4_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 34) for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 34;
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_DBG("%s. Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum Four Activate Window Delay Time (t FAW min)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes SDRAM Minimum Four Activate Window Delay Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tFAWmin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 36 Bits 3 ~ 0 along with Byte 37 Bits 7 ~ 0
+/// @note SPD Byte 36 (bits 3~0) & Byte 37 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 42
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::min_four_activate_window_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_tfaw(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 36; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 37; // LSB = least significant byte
+ // Lambda expression to retrieve tFAWmin's most significant nibble (MSN)
+ auto tFAWmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 36;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (FAW = Four Activate Window Delay)
- uint16_t l_tFAW = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TFAWMIN_MSN_START, TFAWMIN_MSN_LEN>(l_out);
- // Attribute variable
- uint16_t l_min_faw_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tFAWmin's least significant byte (LSB)
+ auto tFAWmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 37;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Combining bits to create timing value
- l_buffer_upper_nibble.extractToRight<TRCMIN_MSN_START, TRCMIN_MSN_LEN>(l_tFAW);
- l_buffer_lower_byte.extractToRight<TRCMIN_LSB_START, TRCMIN_LSB_LEN>(l_tFAW);
+ // Extracting desired bits
+ l_buffer.extractToRight<TFAWMIN_LSB_START, TFAWMIN_LSB_LEN>(l_out);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trc(l_target_mcs, &l_min_faw_times[0][0]) );
+ return l_out;
+ };
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_faw_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tFAW);
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRC, l_target_mcs, l_min_faw_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tFAWmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tFAWmin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
+
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
+
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 37) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 37;
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Four Activate Window Delay Time (tFAWmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_DBG("%s. Minimum Four Activate Window Delay Time (tFAWmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum Activate to Activate Delay Time (tRRD_Smin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRRD_Smin MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 38
+/// @note SPD Byte 38
+/// @note Item JC-45-2220.01x
+/// @note Page 43
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRRD_Smin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRRD_Smin (SPD byte 119)
+/// used for correction to get the actual value.
///
-fapi2::ReturnCode
-decoder::min_act_to_act_delay_time_diff_bank_group(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_trrd_s(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 38;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 38;
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
- // Attribute variable (rrd_s = Activate to Activate Delay)
- int64_t l_min_tRRD_S[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Retrieve Minimum Activate to Activate Delay Time - Different Bank Group
+ // explicit conversion to int64_t
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_timing_val);
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB") );
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_tRRD_S[0][0]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update attribute to decoded byte values
- l_min_tRRD_S[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ FAPI_DBG("%s. Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRRD_S, l_target_mcs, l_min_tRRD_S );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum Activate to Activate Delay Time (tRRD_Lmin), samebank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRRD_Lmin MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 39
+/// @note SPD Byte 39
+/// @note Item JC-45-2220.01x
+/// @note Page 43-44
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRRD_Lmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRRD_Lmin (SPD byte 118)
+/// used for correction to get the actual value.
///
-fapi2::ReturnCode
-decoder::min_act_to_act_delay_time_same_bank_group(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_trrd_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 39;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 39;
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
- // Attribute variable (rrd_s = Activate to Activate Delay)
- int64_t l_min_tRRD_S[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Retrieve Minimum Activate to Activate Delay Time - Same Bank Group
+ // explicit conversion to int64_t
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_tRRD_S[0][0]) );
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB") );
- // Update attribute to decoded byte values
- l_min_tRRD_S[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TRRD_L, l_target_mcs, l_min_tRRD_S );
+ FAPI_DBG("%s. Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum CAS to CAS Delay Time (tCCD_Lmin), same bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCCD_Lmin MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 40
+/// @note SPD Byte 40
+/// @note Item JC-45-2220.01x
+/// @note Page 44-45
+/// @note DDR4 SPD Document Release 3
+/// @warning If tCCD_Lmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tCCD_Lmin (SPD byte 117)
+/// used for correction to get the actual value.
///
-fapi2::ReturnCode decoder::min_cas_to_cas_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_tccd_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 40;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 40;
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ // Retrieve Minimum CAS to CAS Delay Time - Same Bank Group
+ // explicit conversion to int64_t
+ int64_t l_timing_val = int64_t(i_spd_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_tCCD_L[0][0]) );
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB") );
- // Update attribute to decoded byte values
- l_min_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TCCD_L, l_target_mcs, l_min_tCCD_L );
+ FAPI_DBG("%s. Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum Write Recovery Time (tWRmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Write Recovery Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tWRmin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 41 Bits 3~0, Byte 42 Bits 7~0
+/// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::min_write_recovery_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_write_recovery_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 41; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 42; // LSB = least significant byte
+ // Lambda expression to retrieve tWRmin's most nibble byte (MSN)
+ auto tWRmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 41;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (FAW = Four Activate Window Delay)
- uint16_t l_tWRmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TWRMIN_MSN_START, TWRMIN_MSN_LEN>(l_out);
- // Attribute variable
- int64_t l_min_wr_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tWRmin's least significant byte (LSB)
+ auto tWRmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 42;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Combining bits to create timing value
- l_buffer_upper_nibble.insert<, >(l_tWRmin);
- l_buffer_lower_byte.insert<, >(l_tWRmin);
+ // Extracting desired bits
+ l_buffer.extractToRight<TWRMIN_LSB_START, TWRMIN_LSB_LEN>(l_out);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_twr(l_target_mcs, &l_min_wr_times[0][0]) );
+ return l_out;
+ };
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_wr_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tWRmin);
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TWR, l_target_mcs, l_min_wr_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tWRmin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
+
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
+
+ // JEDEC spec limits for this timing value
+ // This value used to be reserved to 0 - before spec update
+ // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+
+ constexpr int64_t TIMING_LOWER_BOUND = 0;
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 42) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 42;
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Write Recovery Time (tWRmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_DBG("%s. Minimum Write Recovery Time (tWRmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Minimum Write to Read Time (tWTR_Smin), different bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Write to Read Time - Different Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tWRT_Smin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 43 Bits 3~0, Byte 44 Bits 7~0
+/// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::min_write_to_read_time_diff_bank_group(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_twtr_s(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 43; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 44; // LSB = least significant byte
+ // Lambda expression to retrieve tWRT_Smin's most nibble byte (MSN)
+ auto tWRT_Smin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 43;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (WRT = Write to Read Time)
- int64_t l_tWRTmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TWTRMIN_S_MSN_START, TWTRMIN_S_MSN_LEN>(l_out);
- // Attribute variable
- int64_t l_min_wrt_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tWRT_Smin's least significant byte (LSB)
+ auto tWRT_Smin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 44;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<TWTRMIN_S_LSB_START, TWTRMIN_S_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRT_Smin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tWRT_Smin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
- // Combining bits to create timing value
- l_buffer_upper_nibble.insert<, >(l_tWRTmin);
- l_buffer_lower_byte.insert<, >(l_tWRTmin);
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_twrt(l_target_mcs, &l_min_wrt_times[0][0]) );
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_wrt_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tWRTmin);
+ // JEDEC spec limits for this timing value
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TWRT, l_target_mcs, l_min_wrt_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // This value used to be reserved to 0 - before spec update - AAM
+ // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_LOWER_BOUND = 0;
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 44) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 44;
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Write to Read Time - Different Bank Group (tWRT_Smin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_DBG("%s. Minimum Write to Read Time - Different Bank Group (tWRT_Smin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Minimum Write to Read Time (tWTR_Lmin), same bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Minimum Write to Read Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tWRT_Lmin in MTB units
/// @return fapi2::ReturnCode
-/// @note Byte 43 Bits 7~4, Byte 45 Bits 7~0
+/// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 46
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode
-decoder::min_write_to_read_time_same_bank_group(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::min_twtr_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSN = 43; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 45; // LSB = least significant byte
+ // Lambda expression to retrieve tWRT_Lmin's most nibble byte (MSN)
+ auto tWRT_Lmin_MSN = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 43;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (WRT = Write to Read Time)
- int64_t l_tWRTmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<TWTRMIN_L_MSN_START, TWTRMIN_L_MSN_LEN>(l_out);
- // Attribute variable
- int64_t l_min_wrt_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve tWRT_Lmin's least significant byte (LSB)
+ auto tWRT_Lmin_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 45;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Combining bits to create timing value
- l_buffer_upper_nibble.insert<, >(l_tWRTmin);
- l_buffer_lower_byte.insert<, >(l_tWRTmin);
+ // Extracting desired bits
+ l_buffer.extractToRight<TWTRMIN_L_LSB_START, TWTRMIN_L_LSB_LEN>(l_out);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_twrt(l_target_mcs, &l_min_wrt_times[0][0]) );
+ return l_out;
+ };
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_wrt_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tWRTmin);
+ int64_t l_timing_val = 0;
+ fapi2::buffer<int64_t> l_buffer;
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TWRT, l_target_mcs, l_min_wrt_times );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
-}
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
-///
-/// @brief Connector to SDRAM Bit Mapping
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
-/// @return fapi2::ReturnCode
-/// @note Bytes 60~77
-///
-fapi2::ReturnCode decoder::connector_to_sdram_bit_mapping(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
-{
-// Retrive entire MCS level attribute
-// Update attribute to decoded byte values
-// Update MCS level attribute
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRT_Lmin_MSN(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( tWRT_Lmin_LSB(i_target, i_spd_data) );
+
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 64;
+
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(l_timing_val);
+
+ // JEDEC spec limits for this timing value
+ // This value used to be reserved to 0 - before spec update
+ //constexpr int64_t TIMING_LOWER_BOUND = 1 // from JEDEC
+ constexpr int64_t TIMING_LOWER_BOUND = 0;
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 45) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 45;
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Write to Read Time - Same Bank Group (tWRT_Lmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_DBG("%s. Minimum Write to Read Time - Same Bank Group (tWRT_Lmin) in MTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for Minimum CAS to CAS Delay Time (tCCD_Lmin), same bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCCD_Lmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 117
+/// @note SPD Byte 117
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_min_cas_to_cas_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_tccd_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 117;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ constexpr size_t BYTE_INDEX = 117;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // Retrieve Fine Offset for Minimum CAS to CAS Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(i_spd_data[BYTE_INDEX]);
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for min RAS to CAS Delay Time (tCCD_Lmin)") );
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
-}
+ // Update output value only if range check passes
+ o_value = l_timing_val;
-// Retrive entire MCS level attribute
-// Update attribute to decoded byte values
-// Update MCS level attribute
+ FAPI_DBG("%s. Fine offset for Minimum RAS to CAS Delay Time (tCCD_Lmin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
fapi_try_exit:
-return fapi2::current_err;
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for Minimum Activate to Activate Delay Time(tRRD_Lmin), same bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRRD_Lmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 118
+/// @note SPD Byte 118
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode
-decoder::offset_min_act_to_act_delay_time_diff_bank_gp(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trrd_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 118;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 118;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // Retrieve Fine Offset for Minimum Activate to Activate Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(i_spd_data[BYTE_INDEX]);
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin)") );
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ FAPI_DBG("%s. Fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for Minimum Activate to Activate Delay Time (tRRD_Smin), different bank group
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRRD_Smin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 119
+/// @note SPD Byte 119
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode
-decoder::offset_min_act_to_act_delay_time_same_bank_gp(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trrd_s(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 119;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 119;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // Retrieve Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(i_spd_data[BYTE_INDEX]);
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin)") );
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ FAPI_DBG("%s. Fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for Minimum Active to Active/Refresh Delay Time (tRCmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRCmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 120
+/// @note SPD Byte 120
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode
-decoder::offset_for_min_act_to_act_refresh_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trc(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 120;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 120;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // Retrieve Fine Offset for Minimum Active to Active/Refresh Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(i_spd_data[BYTE_INDEX]);
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin)") );
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // Update output value only if range check passes
+ o_value = l_timing_val;
-// Retrive entire MCS level attribute
-// Update attribute to decoded byte values
-// Update MCS level attribute
+ FAPI_DBG("%s. Fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for Minimum Row Precharge Delay Time (tRPmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRPmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 121
+/// @note SPD Byte 121
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode
-decoder::offset_for_min_row_precharge_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trp(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 121;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 121;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // Retrieve Fine Offset for Minimum Row Precharge Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(i_spd_data[BYTE_INDEX]);
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for Minimum Row Precharge Delay Time (tRPmin)") );
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
-
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
-}
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+ FAPI_DBG("%s. Fine offset for Minimum Row Precharge Delay Time (tRPmin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
+fapi_try_exit:
+ return fapi2::current_err;
+}
///
-/// @brief Fine Offset for Minimum RAS to CAS Delay Time (tRCDmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tRCDmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 122
+/// @note SPD Byte 122
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_min_ras_to_cas_delay_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_trcd(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 122;
+ constexpr size_t BYTE_INDEX = 122;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // Retrieve Fine Offset for SDRAM Minimum RAS to CAS Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(i_spd_data[BYTE_INDEX]);
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for min RAS to CAS Delay Time (tRCDmin)") );
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
+ FAPI_DBG("%s. Fine offset for Minimum RAS to CAS Delay Time (tRCDmin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for Minimum CAS Latency Time (tAAmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tAAmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 123
+/// @note SPD Byte 123
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_min_cas_latency_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_taa(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 123;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 125;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // Retrieve Fine Offset for SDRAM Minimum CAS Latency Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(i_spd_data[BYTE_INDEX]);
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Fine offset for Minimum CAS Latency Time (tAAmin)") );
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
+ FAPI_DBG("%s. Fine offset for Minimum CAS Latency Time (tAAmin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Fine Offset for SDRAM Maximum Cycle Time (tCKAVGmax)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCKmax offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 124
+/// @note SPD Byte 124
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_max_cycle_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_max_tck(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 124;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 124;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
-
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // Retrieve Fine Offset for SDRAM Maximum Cycle Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(i_spd_data[BYTE_INDEX]);
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for max cycle time (tckmax)") );
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
+ FAPI_DBG("%s. Fine offset for Maximum Cycle Time (tCKmax) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Fine Offset for SDRAM Minimum Cycle Time (tCKAVGmin)
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value tCKmin offset in FTB units
/// @return fapi2::ReturnCode
-/// @note Byte 125
+/// @note SPD Byte 125
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::offset_for_min_cycle_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::fine_offset_min_tck(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ int64_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX = 125;
-
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
-
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ constexpr size_t BYTE_INDEX = 125;
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
- // Attribute variable (CCD_L = Minimum CAS to CAS Delay Time, same bank group)
- int64_t l_min_offset_tCCD_L[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
-
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
BYTE_INDEX,
i_spd_data[BYTE_INDEX]);
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_trrd(l_target_mcs, &l_min_offset_tCCD_L[0][0]) );
+ // Retrieve Fine Offset for SDRAM Minimum Cycle Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(i_spd_data[BYTE_INDEX]);
+
+ FAPI_TRY(mss::check::spd::
+ fail_for_invalid_value(i_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Fine offset for Minimum Cycle Time (tCKmin)") );
- // Update attribute to decoded byte values
- l_min_offset_tCCD_L[PORT_NUM][DIMM_NUM] = ns_to_ps( int64_t(i_spd_data[BYTE_INDEX]) );
+ // Update output value only if range check passes
+ o_value = l_timing_val;
- // Update MCS level attribute
- FAPI_ATTR_SET( fapi2::ATTR_EFF_OFFSET_DRAM_TCCD_L, l_target_mcs, l_min_offset_tCCD_L );
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
+ FAPI_DBG("%s. Fine offset for Minimum Cycle Time (tCKmin) in FTB units: %d",
+ mss::c_str(i_target),
+ o_value);
- fapi_try_exit:
- return fapi2::current_err;
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Cyclical Redundancy Code (CRC) for Base Configuration Section
-/// @param[in] const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
-/// uint8_t* i_spd_data
+/// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section
+/// @param[in] i_target FAPI2 DIMM target
+/// @param[in] i_spd_data SPD blob
+/// @param[out] o_value crc value from SPD
/// @return fapi2::ReturnCode
-/// @note Byte 126 (LSB) along with Byte 127 (MSB)
+/// @note SPD Byte 127 & Byte 126
+/// @note Item JC-45-2220.01x
+/// @note Page 53
+/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder::crc_for_base_config_section(const fapi2::Target<TARGET_TYPE_DIMM>& i_target_dimm,
- const uint8_t* i_spd_data)
+fapi2::ReturnCode decoder::cyclical_redundancy_code(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t* i_spd_data,
+ uint16_t& o_value)
{
- // Immutable constants
- const size_t BYTE_INDEX_MSB = 127; // MSN = most significant nibble
- const size_t BYTE_INDEX_LSB = 126; // LSB = least significant byte
+ // Lambda expression to retrieve crc's most significant byte (MSB)
+ auto crc_MSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 127;
+ uint8_t l_out = 0;
- // Targets
- const auto l_target_mcs = find_target<TARGET_TYPE_MCS>(i_target_dimm);
- const auto l_target_port = find_target<TARGET_TYPE_MCA>(i_target_dimm);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Current index
- const auto PORT_NUM = index(l_target_port);
- const auto DIMM_NUM = index(i_target_dimm);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
- // Byte variables used for decoding (WRT = Write to Read Time)
- int64_t l_tWRTmin = 0;
+ // Extracting desired bits
+ l_buffer.extractToRight<CRC_MSB_START, CRC_MSB_LEN>(l_out);
- // Attribute variable
- int64_t l_min_wrt_times[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {0};
+ return l_out;
+ };
- // TODO - update ENUMS to take account to int64_t
+ // Lambda expression to retrieve crc's least significant byte (LSB)
+ auto crc_LSB = [](const fapi2::Target<TARGET_TYPE_DIMM>& i_target, const uint8_t* i_data)
+ {
+ constexpr size_t BYTE_INDEX = 126;
+ uint8_t l_out = 0;
- // Buffers used for bit manipulation
- fapi2::buffer<uint8_t> l_buffer_upper_nibble(i_spd_data[BYTE_INDEX_MSN]);
- fapi2::buffer<uint8_t> l_buffer_lower_byte(i_spd_data[BYTE_INDEX_LSB]);
+ // Trace in the front assists w/ debug
+ FAPI_DBG("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ BYTE_INDEX,
+ i_data[BYTE_INDEX]);
- // Trace print in the front assists w/ debug
- FAPI_INF("%s SPD data at Byte %d: 0x%llX",
- c_str(i_target_dimm),
- BYTE_INDEX,
- i_spd_data[BYTE_INDEX]);
+ fapi2::buffer<uint8_t> l_buffer(i_data[BYTE_INDEX]);
+
+ // Extracting desired bits
+ l_buffer.extractToRight<CRC_LSB_START, CRC_LSB_LEN>(l_out);
+
+ return l_out;
+ };
+
+ fapi2::buffer<uint16_t> l_buffer;
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 0;
+ constexpr size_t MSN_LEN = 8;
+ constexpr size_t LSB_START = 8;
+ constexpr size_t LSB_LEN = 8;
- // Combining bits to create timing value
- l_buffer_upper_nibble.insert<, >(l_tWRTmin);
- l_buffer_lower_byte.insert<, >(l_tWRTmin);
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( crc_MSB(i_target, i_spd_data) ).
+ insertFromRight<LSB_START, LSB_LEN>( crc_LSB(i_target, i_spd_data) );
- // Retrive entire MCS level attribute
- FAPI_TRY( eff_dram_twrt(l_target_mcs, &l_min_wrt_times[0][0]) );
+ // Extract timing value from the buffer into an integral type
+ constexpr size_t OUTPUT_START = 0;
+ constexpr size_t OUTPUT_LEN = 16;
- // Update attribute to decoded byte values (returning picoseconds, currently nanoseconds)
- l_min_wrt_times[PORT_NUM][DIMM_NUM] = ns_to_ps(l_tWRTmin);
+ // This value isn't bounded in the SPD document
+ l_buffer.extractToRight<OUTPUT_START, OUTPUT_LEN>(o_value);
- // Update MCS level attribute (returning picoseconds, currently nanoseconds)
- FAPI_ATTR_SET( fapi2::ATTR_EFF_DRAM_TWRT, l_target_mcs, l_min_wrt_times );
+ FAPI_DBG("%s. Cyclical Redundancy Code (CRC): %d",
+ mss::c_str(i_target),
+ o_value);
- // Printed decoded info
- FAPI_INF("%s",
- c_str(i_target_dimm);
- fapi_try_exit:
- return fapi2::current_err;
+ // Returns "happy" until we can figure out a way to test this - AAM
+ return fapi2::FAPI2_RC_SUCCESS;
}
-#endif
}//spd namespace
}// mss namespace
OpenPOWER on IntegriCloud