diff options
48 files changed, 7528 insertions, 10551 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C index f8d7cfc7c..4e52d5083 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C @@ -22,8 +22,8 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -// *HWP HWP Owner: Jacob Harvey <jlharvey@us.ibm.com> -// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: FSP:HB @@ -37,8 +37,6 @@ // mss lib #include <lib/utils/fake_vpd.H> #include <lib/mss_vpd_decoder.H> -#include <lib/spd/spd_factory.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> #include <generic/memory/lib/spd/common/rcw_settings.H> #include <lib/eff_config/timing.H> #include <lib/dimm/ddr4/mrs_load_ddr4.H> @@ -48,9 +46,9 @@ #include <lib/dimm/eff_dimm.H> #include <lib/dimm/mrs_load.H> #include <lib/shared/mss_kind.H> -#include <generic/memory/lib/spd/common/dimm_module_decoder.H> #include <lib/phy/dp16.H> #include <lib/mss_attribute_accessors_manual.H> +#include <endian.h> namespace mss { @@ -60,6 +58,147 @@ using fapi2::TARGET_TYPE_MCS; using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_MCBIST; +// +// Note SPD mappings included are settings only supported by Nimbus. +// We purposely omit certain settings that exist in the JEDEC SPD spec +// if they are not supported in HW. This simplifies error catching and +// explicitly depicts supported mappings. +// + +// ========================================================= +// Byte 4 maps +// Item JC-45-2220.01x +// Page 18 +// DDR4 SPD Document Release 3 +// Byte 4 (0x004): SDRAM Density and Banks +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::SDRAM_DENSITY_MAP = +{ + // {key byte, capacity in GBs} + {4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G}, + {5, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G}, + {6, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G}, +}; + +// ========================================================= +// Byte 4 maps +// Item JC-45-2220.01x +// Page 18 +// DDR4 SPD Document Release 3 +// Byte 4 (0x004): SDRAM Density and Banks +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > eff_dimm::BANK_ADDR_BITS_MAP = +{ + // {key byte, number of bank address bits} + {0, 2}, + {1, 3} +}; + +// ========================================================= +// Byte 5 maps +// Item JC-45-2220.01x +// Page 18 +// DDR4 SPD Document Release 3 +// Byte 5 (0x005): SDRAM Addressing +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::ROW_ADDRESS_BITS_MAP = +{ + //{key byte,row address bits} + {2, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM14}, + {3, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM15}, + {4, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM16}, + {5, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM17}, + {6, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM18} +}; + +// ========================================================= +// Byte 6 maps +// Item JC-45-2220.01x +// Page 19 +// DDR4 SPD Document Release 3 +// Byte 6 (0x006): Primary SDRAM Package Type +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::PRIM_DIE_COUNT_MAP = +{ + // {key byte, number of die} + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 5}, + {5, 6}, + {6, 7}, + {7, 8} +}; + +// ========================================================= +// Byte 9 maps +// Item JC-45-2220.01x +// Page 21 +// DDR4 SPD Document Release 3 +// Byte 9 (0x009): Other SDRAM Optional Features +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::SOFT_PPR_MAP = +{ + // {key byte, value } + {0, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED}, + {1, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED} +}; + +// ========================================================= +// Byte 10 maps +// Item JC-45-2220.01x +// Page 21-22 +// DDR4 SPD Document Release 3 +// Byte 10 (0x00A): Secondary SDRAM Package Type +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::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} +}; + +// ========================================================= +// Byte 12 maps +// Item JC-45-2220.01x +// Page 23 +// DDR4 SPD Document Release 3 +// Byte 12 (0x00C): Module Organization +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::DEVICE_WIDTH_MAP = +{ + // {key byte, device width (bits)} + {0, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4}, + {1, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8}, + {2, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16}, + {3, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X32}, + // All others reserved +}; + +// ========================================================= +// Byte 13 maps +// Item JC-45-2220.01x +// Page 27 +// DDR4 SPD Document Release 3 +// Byte 13 (0x00D): Module Memory Bus Width +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::BUS_WIDTH_MAP = +{ + // {key byte, bus width (in bits) + {0, 8}, + {1, 16}, + {2, 32}, + {3, 64} + // All others reserved +}; + /// /// @brief bit encodings for RC02 /// From DDR4 Register v1.0 @@ -141,7 +280,7 @@ enum rc0d_encode : uint8_t /// @brief bit encodings for RC0E /// From DDR4 Register v1.0 /// -enum rc0e_encode +enum rc0e_encode : uint8_t { RC0E_PARITY_ENABLE_BIT = 7, RC0E_PARITY_ENABLE = 1, @@ -204,7 +343,7 @@ enum lrdimm_databuffers /// /// @brief encoding for MSS_INVALID_FREQ so we can look up functions based on encoding /// -enum invalid_freq_function_encoding +enum invalid_freq_function_encoding : uint8_t { RC0A = 0x0a, RC3X = 0x30, @@ -214,17 +353,124 @@ enum invalid_freq_function_encoding /// /// @brief encoding for MSS_INVALID_TIMING so we can look up functions based on encoding /// -enum invalid_timing_function_encoding +enum invalid_timing_function_encoding : uint8_t { TRRD_S = 0, TRRD_L = 1, TFAW = 2, }; + ///////////////////////// // Non-member function implementations ///////////////////////// /// +/// @brief Helper function to calculate logical ranks +/// @param[in] i_signal_loading signal loading from SPD +/// @param[in] i_dram_die_count DRAM die count from SPD +/// @param[in] i_master_ranks number of master ranks from SPD +/// +static uint8_t calc_logical_ranks(const uint8_t i_signal_loading, + const uint8_t i_dram_die_count, + const uint8_t i_master_ranks) +{ + // For single-load-stack(3DS) the logical ranks per package ends up being the same as the die count. + // For MONOLITHIC & MULTI_LOAD_STACK + // The die count isn't guaranteed to be 1 (e.g. SDP - 1 die package, DDP - 2 die package). + // Value of 1 has no meaning and is used for calculation purposes as defined by the SPD spec. + const uint8_t l_multiplier = (i_signal_loading == spd::SINGLE_LOAD_STACK) ? i_dram_die_count : 1; + + return (i_master_ranks * l_multiplier); +} + +/// +/// @brief Returns logical ranks in Primary SDRAM type +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::prim_sdram_logical_ranks( uint8_t& o_logical_ranks ) const +{ + uint8_t l_signal_loading = 0; + uint8_t l_master_ranks = 0; + + // Number of master ranks taken from attribute since we need mapped value + // and not the encoded raw value from SPD. + FAPI_TRY( mss::eff_num_master_ranks_per_dimm(iv_dimm, l_master_ranks) ); + FAPI_TRY( iv_spd_decoder.prim_sdram_signal_loading(l_signal_loading) ); + + o_logical_ranks = calc_logical_ranks(l_signal_loading, iv_dram_die_count, l_master_ranks); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function that returns logical ranks in SDRAM type +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::sec_sdram_logical_ranks( uint8_t& o_logical_ranks ) const +{ + uint8_t l_signal_loading = 0; + uint8_t l_master_ranks = 0; + uint8_t l_spd_die_count = 0; + uint8_t l_die_count = 0; + + // Grabbing signal loading + FAPI_TRY( iv_spd_decoder.sec_sdram_signal_loading(l_signal_loading) ); + + // Number of master ranks taken from attribute since we need mapped value + // and not the encoded raw value from SPD. + FAPI_TRY( mss::eff_num_master_ranks_per_dimm(iv_dimm, l_master_ranks) ); + + // Getting die count + FAPI_TRY( iv_spd_decoder.sec_sdram_die_count(l_spd_die_count) ); + + FAPI_ASSERT( mss::find_value_from_key(SEC_DIE_COUNT_MAP, l_spd_die_count, l_die_count), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_die_count) + .set_DATA(l_die_count) + .set_TARGET(iv_dimm), + "Could not a mapped value that matched the key (%d) for %s", + l_spd_die_count, mss::c_str(iv_dimm) ); + + o_logical_ranks = calc_logical_ranks(l_signal_loading, l_die_count, l_master_ranks); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Returns logical ranks per DIMM +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const +{ + uint8_t l_prim_logical_rank_per_dimm = 0; + uint8_t l_rank_mix = 0; + + FAPI_TRY( iv_spd_decoder.rank_mix(l_rank_mix) ); + FAPI_TRY( prim_sdram_logical_ranks(l_prim_logical_rank_per_dimm) ); + + if(l_rank_mix == fapi2::ENUM_ATTR_EFF_DRAM_RANK_MIX_SYMMETRICAL) + { + o_logical_rank_per_dimm = l_prim_logical_rank_per_dimm; + } + else + { + // Rank mix is ASYMMETRICAL + uint8_t l_sec_logical_rank_per_dimm = 0; + FAPI_TRY( sec_sdram_logical_ranks(l_sec_logical_rank_per_dimm) ); + + o_logical_rank_per_dimm = l_prim_logical_rank_per_dimm + l_sec_logical_rank_per_dimm; + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// /// @brief Gets the JEDEC train and range values from the encoded VPD value /// @param[in] i_target - the DIMM target on which to operate /// @param[out] o_range - the JEDEC VREFDQ range @@ -293,28 +539,105 @@ static uint64_t ibt_helper(const uint8_t i_ibt) } /// +/// @brief Helper function to set dram width instance variable +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::set_dram_width_instance() +{ + uint8_t l_spd_device_width = 0; + FAPI_TRY( iv_spd_decoder.device_width(l_spd_device_width), + "Failed accessing device width from SPD %s", mss::c_str(iv_dimm) ); + + FAPI_ASSERT( mss::find_value_from_key(DEVICE_WIDTH_MAP, l_spd_device_width, iv_dram_width), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_device_width) + .set_DATA(iv_dram_width) + .set_FUNCTION(SET_DRAM_WIDTH_INSTANCE) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_spd_device_width, mss::c_str(iv_dimm) ); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function to set dram density instance variable +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::set_dram_density_instance() +{ + uint8_t l_spd_dram_density = 0; + FAPI_TRY( iv_spd_decoder.sdram_density(l_spd_dram_density), "Failed to get dram_density from SPD %s", + mss::c_str(iv_dimm) ); + + FAPI_ASSERT( mss::find_value_from_key(SDRAM_DENSITY_MAP, l_spd_dram_density, iv_dram_density), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_dram_density) + .set_DATA(iv_dram_density) + .set_FUNCTION(SET_DRAM_DENSITY_INSTANCE) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_spd_dram_density, mss::c_str(iv_dimm) ); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function to set dram density instance variable +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::set_prim_dram_die_count_instance() +{ + uint8_t l_decoder_val = 0; + FAPI_TRY( iv_spd_decoder.prim_sdram_die_count(l_decoder_val), + "Failed to get the die count for the dimm %s", mss::c_str(iv_dimm) ); + + FAPI_ASSERT( mss::find_value_from_key(PRIM_DIE_COUNT_MAP, l_decoder_val, iv_dram_die_count), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_decoder_val) + .set_DATA(iv_dram_die_count) + .set_FUNCTION(PRIM_DIE_COUNT) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_decoder_val, mss::c_str(iv_dimm) ); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} +/// /// @brief factory to make an eff_config DIMM object based on dimm kind (type, gen, and revision number) -/// @param[in] i_pDecoder the spd::decoder for the dimm target +/// @param[in] i_spd_decoder the spd::decoder for the dimm target /// @param[out] o_fact_obj a shared pointer of the eff_dimm type /// -fapi2::ReturnCode eff_dimm::eff_dimm_factory ( const std::shared_ptr<spd::decoder>& i_pDecoder, - std::shared_ptr<eff_dimm>& o_fact_obj ) +fapi2::ReturnCode eff_dimm::factory ( const spd::facade& i_spd_decoder, + std::shared_ptr<eff_dimm>& o_fact_obj ) { uint8_t l_type = 0; uint8_t l_gen = 0; uint8_t l_buffer_type = 0; kind_t l_dimm_kind = DEFAULT_KIND; + rcw_settings l_raw_card; fapi2::ReturnCode l_rc; - const auto& l_dimm = i_pDecoder->iv_target; + const auto l_dimm = i_spd_decoder.get_dimm_target(); // Now time to get the three attributes to tell which dimm we're working with. - // Dram_gen and dimm_type are set in the SPD factory and we'll call the SPD decoder to get the reg and buff type - FAPI_TRY( eff_dram_gen(l_dimm, l_gen), "Failed eff_dram_gen() accessor for %s", l_dimm ); - FAPI_TRY( eff_dimm_type(l_dimm, l_type), "Failed eff_dimm_type() accessor for %s", - l_dimm ); - FAPI_TRY( i_pDecoder->iv_module_decoder->register_and_buffer_type(l_buffer_type), - "Failed decoding register and buffer type from SPD for %s", l_dimm ); + // Dram_gen and dimm_type are set in mss_freq and we'll call the SPD decoder to get the reg and buff type + FAPI_TRY( eff_dram_gen(l_dimm, l_gen), "Failed eff_dram_gen() accessor for %s", mss::c_str(l_dimm) ); + FAPI_TRY( eff_dimm_type(l_dimm, l_type), "Failed eff_dimm_type() accessor for %s", mss::c_str(l_dimm) ); + + FAPI_TRY( i_spd_decoder.register_and_buffer_type(l_buffer_type), + "Failed decoding register and buffer type from SPD for %s", mss::c_str(l_dimm) ); + + FAPI_TRY(raw_card_factory(l_dimm, i_spd_decoder, l_raw_card)); l_dimm_kind = mss::dimm_kind(l_type, l_gen); @@ -324,7 +647,7 @@ fapi2::ReturnCode eff_dimm::eff_dimm_factory ( const std::shared_ptr<spd::decode switch (l_buffer_type) { case LRDIMM_DB01: - o_fact_obj = std::make_shared<eff_lrdimm_db01>( i_pDecoder, l_rc ); + o_fact_obj = std::make_shared<eff_lrdimm_db01>( i_spd_decoder, l_raw_card, l_rc ); // Assert that l_rc is good and o_fact_object isn't null FAPI_ASSERT( ((l_rc == fapi2::FAPI2_RC_SUCCESS) && (o_fact_obj != nullptr)), @@ -339,7 +662,7 @@ fapi2::ReturnCode eff_dimm::eff_dimm_factory ( const std::shared_ptr<spd::decode break; case LRDIMM_DB02: - o_fact_obj = std::make_shared<eff_lrdimm_db02>( i_pDecoder, l_rc ); + o_fact_obj = std::make_shared<eff_lrdimm_db02>( i_spd_decoder, l_raw_card, l_rc ); // Assert that l_rc is good and o_fact_object isn't null FAPI_ASSERT( ((l_rc == fapi2::FAPI2_RC_SUCCESS) && (o_fact_obj != nullptr)), @@ -367,7 +690,7 @@ fapi2::ReturnCode eff_dimm::eff_dimm_factory ( const std::shared_ptr<spd::decode break; case KIND_RDIMM_DDR4: - o_fact_obj = std::make_shared<eff_rdimm>( i_pDecoder, l_rc ); + o_fact_obj = std::make_shared<eff_rdimm>( i_spd_decoder, l_raw_card, l_rc ); // Assert that l_rc is good and o_fact_object isn't null FAPI_ASSERT( ((l_rc == fapi2::FAPI2_RC_SUCCESS) && (o_fact_obj != nullptr)), fapi2::MSS_ERROR_CREATING_EFF_CONFIG_DIMM_OBJECT(). @@ -410,7 +733,8 @@ fapi2::ReturnCode eff_dimm::rcd_mfg_id() // Get & update MCS attribute FAPI_TRY( eff_rcd_mfg_id(iv_mcs, &l_mcs_attrs[0][0]), "Failed accessing ATTR_MSS_EFF_RCD_MFG_ID" ); - FAPI_TRY( iv_pDecoder->reg_manufacturer_id_code(l_decoder_val), "Failed getting rcd id code from SPD %s", + FAPI_TRY( iv_spd_decoder.reg_manufacturer_id_code(l_decoder_val), + "Failed getting rcd id code from SPD %s", mss::c_str(iv_dimm) ); switch (l_decoder_val) @@ -451,7 +775,7 @@ fapi2::ReturnCode eff_dimm::register_type() // Get & update MCS attribute FAPI_TRY( eff_register_type(iv_mcs, &l_mcs_attrs[0][0]), "Failed accessing ATTR_MSS_REGISTER_TYPE" ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->register_and_buffer_type(l_decoder_val), + FAPI_TRY( iv_spd_decoder.register_and_buffer_type(l_decoder_val), "Failed getting register_type code from SPD %s", mss::c_str(iv_dimm) ); @@ -475,7 +799,8 @@ fapi2::ReturnCode eff_dimm::register_rev() // Get & update MCS attribute FAPI_TRY( eff_register_rev(iv_mcs, &l_mcs_attrs[0][0]), "Failed accessing ATTR_MSS_REGISTER_REV" ); - FAPI_TRY( iv_pDecoder->register_rev_num(l_decoder_val), "Failed getting register_rev code from SPD %s", + FAPI_TRY( iv_spd_decoder.register_rev_num(l_decoder_val), + "Failed getting register_rev code from SPD %s", mss::c_str(iv_dimm) ); FAPI_INF("%s Register rev is 0x%02x", mss::c_str(iv_dimm), l_decoder_val); @@ -498,9 +823,11 @@ fapi2::ReturnCode eff_dimm::dram_mfg_id() // Get & update MCS attribute FAPI_TRY( eff_dram_mfg_id(iv_mcs, &l_mcs_attrs[0][0]), "Failed accessing ATTR_MSS_EFF_DRAM_MFG_ID" ); - FAPI_TRY( iv_pDecoder->dram_manufacturer_id_code(l_decoder_val), "Failed getting dram id code from SPD %s", + FAPI_TRY( iv_spd_decoder.dram_manufacturer_id_code(l_decoder_val), "Failed getting dram id code from SPD %s", mss::c_str(iv_dimm) ); + endian_swap(l_decoder_val); + switch (l_decoder_val) { case fapi2::ENUM_ATTR_EFF_DRAM_MFG_ID_MICRON: @@ -534,24 +861,12 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::dram_width() { - uint8_t l_decoder_val = 0; uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; // Get & update MCS attribute - FAPI_TRY( iv_pDecoder->device_width(l_decoder_val), "Failed accessing device width from SPD %s", mss::c_str(iv_dimm) ); FAPI_TRY( eff_dram_width(iv_mcs, &l_mcs_attrs[0][0]), "Failed getting EFF_DRAM_WIDTH" ); - // Enforcing NIMBUS restrictions - FAPI_ASSERT( (l_decoder_val == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) || - (l_decoder_val == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4), - fapi2::MSS_INVALID_DRAM_WIDTH() - .set_DRAM_WIDTH(l_decoder_val) - .set_DIMM_TARGET(iv_dimm), - "Unsupported DRAM width with %d for target %s", - l_decoder_val, - mss::c_str(iv_dimm)); - - l_mcs_attrs[iv_port_index][iv_dimm_index] = l_decoder_val; + l_mcs_attrs[iv_port_index][iv_dimm_index] = iv_dram_width; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_WIDTH, iv_mcs, l_mcs_attrs), "Failed setting ATTR_EFF_DRAM_WIDTH" ); fapi_try_exit: @@ -564,17 +879,12 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::dram_density() { - uint8_t l_decoder_val = 0; - FAPI_TRY( iv_pDecoder->sdram_density(l_decoder_val), "Failed to get dram_density from SPD %s", mss::c_str(iv_dimm) ); - // Get & update MCS attribute - { - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dram_density(iv_mcs, &l_mcs_attrs[0][0]), "Failed to get ATTR_MSS_EFF_DRAM_DENSITY" ); + uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dram_density(iv_mcs, &l_mcs_attrs[0][0]), "Failed to get ATTR_MSS_EFF_DRAM_DENSITY" ); - l_mcs_attrs[iv_port_index][iv_dimm_index] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DENSITY, iv_mcs, l_mcs_attrs), "Failed to set ATTR_EFF_DRAM_DENSITY" ); - } + l_mcs_attrs[iv_port_index][iv_dimm_index] = iv_dram_density; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DENSITY, iv_mcs, l_mcs_attrs), "Failed to set ATTR_EFF_DRAM_DENSITY" ); fapi_try_exit: return fapi2::current_err; @@ -591,8 +901,8 @@ fapi2::ReturnCode eff_dimm::ranks_per_dimm() // Get & update MCS attribute FAPI_TRY( eff_num_ranks_per_dimm(iv_mcs, &l_attrs_ranks_per_dimm[0][0]), "Failed to get EFF_NUM_RANKS_PER_DIMM" ); - FAPI_TRY( iv_pDecoder->logical_ranks_per_dimm(l_ranks_per_dimm), - "Failed to get logical_ranks_per_dimm from SPD %s", mss::c_str(iv_dimm) ); + FAPI_TRY( logical_ranks_per_dimm(l_ranks_per_dimm), + "Failed to get logical_ranks_per_dimm %s", mss::c_str(iv_dimm) ); l_attrs_ranks_per_dimm[iv_port_index][iv_dimm_index] = l_ranks_per_dimm; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_RANKS_PER_DIMM, iv_mcs, l_attrs_ranks_per_dimm), @@ -608,15 +918,12 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::prim_die_count() { - uint8_t l_die_count = 0; uint8_t l_attr[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; // Get & update MCS attribute FAPI_TRY( eff_prim_die_count(iv_mcs, &l_attr[0][0]), "Failed to get EFF_PRIM_DIE_COUNT" ); - FAPI_TRY( iv_pDecoder->prim_sdram_die_count(l_die_count), - "Failed to get the die count for the dimm %s", mss::c_str(iv_dimm) ); - l_attr[iv_port_index][iv_dimm_index] = l_die_count; + l_attr[iv_port_index][iv_dimm_index] = iv_dram_die_count; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_PRIM_DIE_COUNT, iv_mcs, l_attr), "Failed to set ATTR_EFF_PRIM_DIE_COUNT" ); @@ -633,9 +940,9 @@ fapi2::ReturnCode eff_dimm::primary_stack_type() uint8_t l_stack_type = 0; uint8_t l_package_type = 0; - FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(l_stack_type), + FAPI_TRY( iv_spd_decoder.prim_sdram_signal_loading(l_stack_type), "Failed to get dram_signal_loading from SPD %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->prim_sdram_package_type(l_package_type), + FAPI_TRY( iv_spd_decoder.prim_sdram_package_type(l_package_type), "Failed to get prim_sdram_package_type from SPD %s", mss::c_str(iv_dimm) ); // Check to see if monolithic DRAM/ SDP @@ -700,14 +1007,24 @@ fapi2::ReturnCode eff_dimm::dimm_size() // Retrieve values needed to calculate dimm size uint8_t l_bus_width = 0; - uint8_t l_sdram_width = 0; - uint8_t l_sdram_density = 0; uint8_t l_logical_rank_per_dimm = 0; - FAPI_TRY( iv_pDecoder->device_width(l_sdram_width), "Failed to get device width from SPD %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->prim_bus_width(l_bus_width), "Failed to get prim bus width from SPD %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->sdram_density(l_sdram_density), "Failed to get dram density from SPD %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->logical_ranks_per_dimm(l_logical_rank_per_dimm), + { + uint8_t l_spd_bus_width = 0; + FAPI_TRY( iv_spd_decoder.prim_bus_width(l_spd_bus_width), "Failed to get prim bus width from SPD %s", + mss::c_str(iv_dimm) ); + + FAPI_ASSERT( mss::find_value_from_key(BUS_WIDTH_MAP, l_spd_bus_width, l_bus_width), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_bus_width) + .set_DATA(l_bus_width) + .set_FUNCTION(DIMM_SIZE) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_spd_bus_width, mss::c_str(iv_dimm) ); + } + + FAPI_TRY( logical_ranks_per_dimm(l_logical_rank_per_dimm), "Failed to get logical ranks from SPD %s", mss::c_str(iv_dimm) ); // Let's sort the dimm size vector just to be super duper safe @@ -716,9 +1033,9 @@ fapi2::ReturnCode eff_dimm::dimm_size() // Double checking to avoid divide by zero errors // If this fails, there was a problem with the check in SPD function - FAPI_ASSERT( l_sdram_density != 0, + FAPI_ASSERT( iv_dram_density != 0, fapi2::MSS_BAD_SDRAM_DENSITY_DECODER() - .set_DRAM_DENSITY(l_sdram_density) + .set_DRAM_DENSITY(iv_dram_density) .set_DIMM_TARGET(iv_dimm), "SPD decoder messed up and returned a 0. Should have been caught already %s", mss::c_str(iv_dimm)); @@ -726,23 +1043,23 @@ fapi2::ReturnCode eff_dimm::dimm_size() // Calculate dimm size // Formula from SPD Spec (seriously, they don't have parenthesis in the spec) // Total = SDRAM Capacity / 8 * Primary Bus Width / SDRAM Width * Logical Ranks per DIMM - const uint32_t l_dimm_size = (l_sdram_density * l_bus_width * l_logical_rank_per_dimm) / (8 * l_sdram_width); + const uint32_t l_dimm_size = (iv_dram_density * l_bus_width * l_logical_rank_per_dimm) / (8 * iv_dram_width); FAPI_ASSERT( (std::binary_search(l_dimm_sizes.begin(), l_dimm_sizes.end(), l_dimm_size) == true), fapi2::MSS_INVALID_CALCULATED_DIMM_SIZE() .set_CALCULATED_SIZE(l_dimm_size) - .set_SDRAM_WIDTH(l_sdram_width) + .set_SDRAM_WIDTH(iv_dram_width) .set_BUS_WIDTH(l_bus_width) - .set_DRAM_DENSITY(l_sdram_density) + .set_DRAM_DENSITY(iv_dram_density) .set_LOGICAL_RANKS(l_logical_rank_per_dimm) .set_DIMM_TARGET(iv_dimm), "Recieved an invalid dimm size (%d) for calculated DIMM_SIZE for target %s" - "(l_sdram_density %d * l_bus_width %d * l_logical_rank_per_dimm %d) / (8 * l_sdram_width %d", + "(iv_dram_density %d * l_bus_width %d * l_logical_rank_per_dimm %d) / (8 * iv_dram_width %d", l_dimm_size, mss::c_str(iv_dimm), - l_sdram_width, + iv_dram_width, l_bus_width, - l_sdram_density, + iv_dram_density, l_logical_rank_per_dimm); // Get & update MCS attribute @@ -820,7 +1137,7 @@ fapi2::ReturnCode eff_dimm::dram_trefi() // Calculate nck FAPI_TRY( spd::calc_nck( l_trefi_in_ps, static_cast<uint64_t>(iv_tCK_in_ps), - INVERSE_DDR4_CORRECTION_FACTOR, + spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trefi_in_nck), "Error in calculating tREFI for target %s, with value of l_trefi_in_ps: %d", mss::c_str(iv_dimm), l_trefi_in_ps); @@ -866,19 +1183,19 @@ fapi2::ReturnCode eff_dimm::dram_trfc() switch(iv_refresh_mode) { case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL: - FAPI_TRY( iv_pDecoder->min_trfc1(l_trfc_mtb), + FAPI_TRY( iv_spd_decoder.min_trfc1(l_trfc_mtb), "Failed to decode SPD for tRFC1" ); break; case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_2X: case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_2X: - FAPI_TRY( iv_pDecoder->min_trfc2(l_trfc_mtb), + FAPI_TRY( iv_spd_decoder.min_trfc2(l_trfc_mtb), "Failed to decode SPD for tRFC2" ); break; case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_4X: case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_4X: - FAPI_TRY( iv_pDecoder->min_trfc4(l_trfc_mtb), + FAPI_TRY( iv_spd_decoder.min_trfc4(l_trfc_mtb), "Failed to decode SPD for tRFC4" ); break; @@ -916,7 +1233,7 @@ fapi2::ReturnCode eff_dimm::dram_trfc() "Failed to retrieve tRFC attribute" ); // Calculate nck - FAPI_TRY( spd::calc_nck(l_trfc_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_in_nck), + FAPI_TRY( spd::calc_nck(l_trfc_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_in_nck), "Error in calculating l_tRFC for target %s, with value of l_trfc_in_ps: %d", mss::c_str(iv_dimm), l_trfc_in_ps); FAPI_INF("tCK (ps): %d, tRFC (ps): %d, tRFC (nck): %d", @@ -943,27 +1260,23 @@ fapi_try_exit: fapi2::ReturnCode eff_dimm::dram_trfc_dlr() { - uint8_t l_density = 0; uint64_t l_tCK_in_ps = 0; uint64_t l_trfc_dlr_in_ps = 0; uint8_t l_trfc_dlr_in_nck = 0; std::vector<uint8_t> l_mcs_attrs_trfc_dlr(PORTS_PER_MCS, 0); // Retrieve map params - FAPI_TRY( iv_pDecoder->sdram_density(l_density), "Failed to get sdram density"); - FAPI_TRY( mss::mrw_fine_refresh_mode(iv_refresh_mode), "Failed to get MRW attribute for fine refresh mode" ); - FAPI_INF("Retrieved SDRAM density: %d, fine refresh mode: %d", - l_density, iv_refresh_mode); + iv_dram_density, iv_refresh_mode); // Calculate refresh cycle time in ps - FAPI_TRY( calc_trfc_dlr(iv_dimm, iv_refresh_mode, l_density, l_trfc_dlr_in_ps), "Failed calc_trfc_dlr()" ); + FAPI_TRY( calc_trfc_dlr(iv_dimm, iv_refresh_mode, iv_dram_density, l_trfc_dlr_in_ps), "Failed calc_trfc_dlr()" ); // Calculate clock period (tCK) from selected freq from mss_freq FAPI_TRY( clock_period(iv_dimm, l_tCK_in_ps), "Failed to calculate clock period (tCK)"); // Calculate refresh cycle time in nck - FAPI_TRY( spd::calc_nck(l_trfc_dlr_in_ps, l_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_dlr_in_nck)); + FAPI_TRY( spd::calc_nck(l_trfc_dlr_in_ps, l_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_dlr_in_nck)); FAPI_INF("tCK (ps): %d, tRFC_DLR (ps): %d, tRFC_DLR (nck): %d", l_tCK_in_ps, l_trfc_dlr_in_ps, l_trfc_dlr_in_nck); @@ -996,7 +1309,7 @@ fapi2::ReturnCode eff_dimm::rcd_mirror_mode() FAPI_TRY( eff_dimm_rcd_mirror_mode(iv_mcs, &l_attrs_mirror_mode[0][0]) ); // Update MCS attribute - FAPI_TRY( iv_pDecoder->iv_module_decoder->register_to_dram_addr_mapping(l_mirror_mode) ); + FAPI_TRY( iv_spd_decoder.register_to_dram_addr_mapping(l_mirror_mode) ); l_attrs_mirror_mode[iv_port_index][iv_dimm_index] = l_mirror_mode; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_RCD_MIRROR_MODE, iv_mcs, l_attrs_mirror_mode) ); @@ -1012,10 +1325,20 @@ fapi_try_exit: fapi2::ReturnCode eff_dimm::dram_bank_bits() { uint8_t l_bank_bits = 0; + uint8_t l_decoder_val = 0; uint8_t l_attrs_bank_bits[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; FAPI_TRY( eff_dram_bank_bits(iv_mcs, &l_attrs_bank_bits[0][0]) ); - FAPI_TRY( iv_pDecoder->bank_bits(l_bank_bits) ); + FAPI_TRY( iv_spd_decoder.bank_bits(l_decoder_val) ); + + FAPI_ASSERT( mss::find_value_from_key(BANK_ADDR_BITS_MAP, l_decoder_val, l_bank_bits), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_decoder_val) + .set_DATA(l_bank_bits) + .set_FUNCTION(DRAM_BANK_BITS) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_decoder_val, mss::c_str(iv_dimm) ); l_attrs_bank_bits[iv_port_index][iv_dimm_index] = l_bank_bits; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_BANK_BITS, iv_mcs, l_attrs_bank_bits) ); @@ -1030,11 +1353,21 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::dram_row_bits() { + uint8_t l_decoder_val = 0; uint8_t l_row_bits = 0; uint8_t l_attrs_row_bits[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; FAPI_TRY( eff_dram_row_bits(iv_mcs, &l_attrs_row_bits[0][0]) ); - FAPI_TRY( iv_pDecoder->row_address_bits(l_row_bits) ); + FAPI_TRY( iv_spd_decoder.row_address_bits(l_decoder_val) ); + + FAPI_ASSERT( mss::find_value_from_key(ROW_ADDRESS_BITS_MAP, l_decoder_val, l_row_bits), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_decoder_val) + .set_DATA(l_row_bits) + .set_FUNCTION(DRAM_ROW_BITS) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_decoder_val, mss::c_str(iv_dimm) ); l_attrs_row_bits[iv_port_index][iv_dimm_index] = l_row_bits; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_ROW_BITS, iv_mcs, l_attrs_row_bits) ); @@ -1051,27 +1384,13 @@ fapi_try_exit: fapi2::ReturnCode eff_dimm::dram_dqs_time() { uint8_t l_attrs_dqs_time[PORTS_PER_MCS] = {}; - uint8_t l_dram_width = 0; - - // Get the DRAM width - FAPI_TRY( iv_pDecoder->device_width(l_dram_width) ); // Get & update MCS attribute FAPI_TRY( eff_dram_tdqs(iv_mcs, &l_attrs_dqs_time[0]) ); - FAPI_INF("SDRAM width: %d for target %s", l_dram_width, mss::c_str(iv_dimm)); - - // Enforcing current NIMBUS standards. - FAPI_ASSERT( (l_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) || - (l_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4), - fapi2::MSS_INVALID_DRAM_WIDTH() - .set_DRAM_WIDTH(l_dram_width) - .set_DIMM_TARGET(iv_dimm), - "Invalid DRAM width with %d for target %s", - l_dram_width, - mss::c_str(iv_dimm)); + FAPI_INF("SDRAM width: %d for target %s", iv_dram_width, mss::c_str(iv_dimm)); // Only possible dram width are x4, x8. If x8, tdqs is available, else not available - l_attrs_dqs_time[iv_port_index] = (l_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? + l_attrs_dqs_time[iv_port_index] = (iv_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? fapi2::ENUM_ATTR_EFF_DRAM_TDQS_ENABLE : fapi2::ENUM_ATTR_EFF_DRAM_TDQS_DISABLE; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TDQS, iv_mcs, l_attrs_dqs_time) ); @@ -1098,9 +1417,9 @@ fapi2::ReturnCode eff_dimm::dram_tccd_l() int64_t l_tccd_mtb = 0; int64_t l_tccd_ftb = 0; - FAPI_TRY( iv_pDecoder->min_tccd_l(l_tccd_mtb), + FAPI_TRY( iv_spd_decoder.min_tccd_l(l_tccd_mtb), "Failed min_tccd_l() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_tccd_l(l_tccd_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_tccd_l(l_tccd_ftb), "Failed fine_offset_min_tccd_l() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tCCD_L (MTB): %ld, tCCD_L(FTB): %ld", @@ -1119,7 +1438,7 @@ fapi2::ReturnCode eff_dimm::dram_tccd_l() "Failed to retrieve tCCD attribute" ); // Calculate nck - FAPI_TRY( spd::calc_nck(l_tccd_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_tccd_in_nck), + FAPI_TRY( spd::calc_nck(l_tccd_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_tccd_in_nck), "Error in calculating tccd for target %s, with value of l_tccd_in_ps: %d", mss::c_str(iv_dimm), l_tccd_in_ps); FAPI_INF("tCK (ps): %d, tCCD_L (ps): %d, tCCD_L (nck): %d", @@ -1151,7 +1470,7 @@ fapi2::ReturnCode eff_dimm::dimm_rc00() FAPI_TRY( eff_dimm_ddr4_rc00(iv_mcs, &l_attrs_dimm_rc00[0][0]) ); // Update MCS attribute - l_attrs_dimm_rc00[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc00; + l_attrs_dimm_rc00[iv_port_index][iv_dimm_index] = iv_raw_card.iv_rc00; FAPI_INF("%s: RC00 settting: 0x%02x", mss::c_str(iv_dimm), l_attrs_dimm_rc00[iv_port_index][iv_dimm_index] ); FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC00, iv_mcs, l_attrs_dimm_rc00) ); @@ -1172,7 +1491,7 @@ fapi2::ReturnCode eff_dimm::dimm_rc01() FAPI_TRY( eff_dimm_ddr4_rc01(iv_mcs, &l_attrs_dimm_rc01[0][0]) ); // Update MCS attribute - l_attrs_dimm_rc01[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc01; + l_attrs_dimm_rc01[iv_port_index][iv_dimm_index] = iv_raw_card.iv_rc01; FAPI_INF("%s: RC01 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc01[iv_port_index][iv_dimm_index] ); FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC01, iv_mcs, l_attrs_dimm_rc01) ); @@ -1218,8 +1537,8 @@ fapi2::ReturnCode eff_dimm::dimm_rc03() uint8_t l_cs_output_drive = 0; uint8_t l_ca_output_drive = 0; - FAPI_TRY( iv_pDecoder->iv_module_decoder->cs_signal_output_driver(l_cs_output_drive) ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->ca_signal_output_driver(l_ca_output_drive) ); + FAPI_TRY( iv_spd_decoder.cs_signal_output_driver(l_cs_output_drive) ); + FAPI_TRY( iv_spd_decoder.ca_signal_output_driver(l_ca_output_drive) ); FAPI_INF( "%s: Retrieved register output drive, for CA: %d, CS: %d", mss::c_str(iv_dimm), l_ca_output_drive, l_cs_output_drive ); @@ -1259,8 +1578,8 @@ fapi2::ReturnCode eff_dimm::dimm_rc04() fapi2::buffer<uint8_t> l_buffer; - FAPI_TRY( iv_pDecoder->iv_module_decoder->odt_signal_output_driver(l_odt_output_drive) ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->cke_signal_output_driver(l_cke_output_drive) ); + FAPI_TRY( iv_spd_decoder.odt_signal_output_driver(l_odt_output_drive) ); + FAPI_TRY( iv_spd_decoder.cke_signal_output_driver(l_cke_output_drive) ); FAPI_INF( "%s: Retrieved signal driver output, for CKE: %d, ODT: %d", mss::c_str(iv_dimm), l_cke_output_drive, l_odt_output_drive ); @@ -1301,8 +1620,8 @@ fapi2::ReturnCode eff_dimm::dimm_rc05() fapi2::buffer<uint8_t> l_buffer; - FAPI_TRY( iv_pDecoder->iv_module_decoder->a_side_clk_output_driver(l_a_side_output_drive) ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->b_side_clk_output_driver(l_b_side_output_drive) ); + FAPI_TRY( iv_spd_decoder.a_side_clk_output_driver(l_a_side_output_drive) ); + FAPI_TRY( iv_spd_decoder.b_side_clk_output_driver(l_b_side_output_drive) ); FAPI_INF( "%s: Retrieved register output drive for clock, b-side (Y0,Y2): %d, a-side (Y1,Y3): %d", mss::c_str(iv_dimm), l_b_side_output_drive, l_a_side_output_drive ); @@ -1718,15 +2037,15 @@ fapi2::ReturnCode eff_dimm::dimm_rc0d() constexpr uint8_t l_cs_mode = rc0d_encode::DIRECT_CS_MODE; uint8_t l_mirror_mode = 0; uint8_t l_dimm_type = 0; - uint8_t l_module_type = 0; + uint8_t l_rc0d_dimm_type = 0; - FAPI_TRY( spd::base_module_type(iv_dimm, iv_pDecoder->iv_spd_data, l_module_type) ); + FAPI_TRY(mss::eff_dimm_type(iv_dimm, l_dimm_type)); - l_dimm_type = (l_module_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? - rc0d_encode::RDIMM : - rc0d_encode::LRDIMM; + l_rc0d_dimm_type = (l_dimm_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? + rc0d_encode::RDIMM : + rc0d_encode::LRDIMM; - FAPI_TRY( iv_pDecoder->iv_module_decoder->register_to_dram_addr_mapping(l_mirror_mode) ); + FAPI_TRY( iv_spd_decoder.register_to_dram_addr_mapping(l_mirror_mode) ); // Lets construct encoding byte for RCD setting { @@ -1743,7 +2062,7 @@ fapi2::ReturnCode eff_dimm::dimm_rc0d() constexpr size_t MIRROR_LEN = 1; l_buffer.insertFromRight<CS_START, CS_LEN>(l_cs_mode) - .insertFromRight<DIMM_TYPE_START, DIMM_TYPE_LEN>(l_dimm_type) + .insertFromRight<DIMM_TYPE_START, DIMM_TYPE_LEN>(l_rc0d_dimm_type) .insertFromRight<MIRROR_START, MIRROR_LEN>(l_mirror_mode); } @@ -1751,7 +2070,6 @@ fapi2::ReturnCode eff_dimm::dimm_rc0d() FAPI_TRY( eff_dimm_ddr4_rc0d(iv_mcs, &l_attrs_dimm_rc0d[0][0]) ); // Update MCS attribute - FAPI_TRY( spd::base_module_type(iv_dimm, iv_pDecoder->iv_spd_data, l_dimm_type) ); l_attrs_dimm_rc0d[iv_port_index][iv_dimm_index] = l_buffer; FAPI_INF( "%s: RC0D setting: 0x%02x", mss::c_str(iv_dimm), l_attrs_dimm_rc0d[iv_port_index][iv_dimm_index] ); @@ -2183,7 +2501,7 @@ fapi2::ReturnCode eff_dimm::dram_twr() constexpr int64_t l_twr_ftb = 0; int64_t l_twr_mtb = 0; - FAPI_TRY( iv_pDecoder->min_twr(l_twr_mtb), + FAPI_TRY( iv_spd_decoder.min_twr(l_twr_mtb), "Failed min_twr() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tWR (MTB): %ld, tWR(FTB): %ld", @@ -2198,7 +2516,7 @@ fapi2::ReturnCode eff_dimm::dram_twr() uint8_t l_twr_in_nck = 0; // Calculate tNCK - FAPI_TRY( spd::calc_nck(l_twr_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twr_in_nck), + FAPI_TRY( spd::calc_nck(l_twr_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_twr_in_nck), "Error in calculating l_twr_in_nck for target %s, with value of l_twr_in_ps: %d", mss::c_str(iv_dimm), l_twr_in_ps); FAPI_INF( "tCK (ps): %d, tWR (ps): %d, tWR (nck): %d for target: %s", @@ -2269,20 +2587,18 @@ fapi2::ReturnCode eff_dimm::dram_cwl() // Taken from DDR4 JEDEC spec 1716.78C // Proposed DDR4 Full spec update(79-4A) // Page 26, Table 7 - static std::pair<uint64_t, uint8_t> CWL_TABLE_1 [6] = + static constexpr std::pair<uint64_t, uint8_t> CWL_TABLE_1 [] = { - {1600, 9}, - {1866, 10}, - {2133, 11}, - {2400, 12}, - {2666, 14}, - {3200, 16}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT1866, 10}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2133, 11}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2400, 12}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2666, 14}, }; - static std::pair<uint64_t, uint8_t> CWL_TABLE_2 [3] = + + static constexpr std::pair<uint64_t, uint8_t> CWL_TABLE_2 [] = { - {2400, 14}, - {2666, 16}, - {3200, 18}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2400, 14}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2666, 16}, }; std::vector<uint8_t> l_attrs_cwl(PORTS_PER_MCS, 0); @@ -2744,7 +3060,7 @@ fapi2::ReturnCode eff_dimm::post_package_repair() uint8_t l_attrs_dram_ppr[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; FAPI_TRY( eff_dram_ppr(iv_mcs, &l_attrs_dram_ppr[0][0]) ); - FAPI_TRY( iv_pDecoder->post_package_repair(l_decoder_val) ); + FAPI_TRY( iv_spd_decoder.post_package_repair(l_decoder_val) ); l_attrs_dram_ppr[iv_port_index][iv_dimm_index] = l_decoder_val; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_PPR, iv_mcs, l_attrs_dram_ppr), @@ -2755,6 +3071,53 @@ fapi_try_exit: } /// +/// @brief Determines & sets effective config for soft post package repair +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::soft_post_package_repair() +{ + uint8_t l_sppr_decoder_val = 0; + uint8_t l_rev_decoder_val = 0; + + uint8_t l_sppr = 0; + uint8_t l_attrs_dram_soft_ppr[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + FAPI_TRY( eff_dram_soft_ppr(iv_mcs, &l_attrs_dram_soft_ppr[0][0]) ); + + FAPI_TRY( iv_spd_decoder.soft_post_package_repair(l_sppr_decoder_val) ); + FAPI_TRY( iv_spd_decoder.revision(l_rev_decoder_val) ); + + if(l_rev_decoder_val == spd::rev::V1_0 && + l_sppr_decoder_val == fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED) + { + // Lab observes DIMMs that are SPD rev 1.0 but have sPPR enabled that is considered + // invalid per the SPD spec. For backward compatability of those DIMMs (known past vendor issue) + // we set it to a valid value. + FAPI_INF("Invalid sPPR (0x%02x) for SPD rev 0x%02x on %s. Setting sPPR to 0x%02x", + l_sppr_decoder_val, l_rev_decoder_val, mss::c_str(iv_dimm), + fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED); + + l_sppr_decoder_val = fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED; + } + + FAPI_ASSERT( mss::find_value_from_key(SOFT_PPR_MAP, l_sppr_decoder_val, l_sppr), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_sppr_decoder_val) + .set_DATA(l_sppr) + .set_FUNCTION(SOFT_POST_PACKAGE_REPAIR) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_sppr_decoder_val, mss::c_str(iv_dimm) ); + + l_attrs_dram_soft_ppr[iv_port_index][iv_dimm_index] = l_sppr; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_SOFT_PPR, iv_mcs, l_attrs_dram_soft_ppr), + "Failed setting attribute for DRAM_SOFT_PPR"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// /// @brief Determines & sets effective config for rd_preamble_train /// @return fapi2::FAPI2_RC_SUCCESS if okay /// @@ -3197,10 +3560,10 @@ fapi2::ReturnCode eff_dimm::dram_trp() int64_t l_trp_mtb = 0; int64_t l_trp_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trp(l_trp_mtb), + FAPI_TRY( iv_spd_decoder.min_trp(l_trp_mtb), "Failed min_trp() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trp(l_trp_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trp(l_trp_ftb), "Failed fine_offset_min_trp() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tRP (MTB): %ld, tRP(FTB): %ld", @@ -3221,7 +3584,7 @@ fapi2::ReturnCode eff_dimm::dram_trp() uint8_t l_trp_in_nck = 0; // Calculate nck - FAPI_TRY( spd::calc_nck(l_trp_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trp_in_nck), + FAPI_TRY( spd::calc_nck(l_trp_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trp_in_nck), "Error in calculating dram_tRP nck for target %s, with value of l_trp_in_ps: %d", mss::c_str(iv_dimm), l_trp_in_ps); FAPI_INF( "tCK (ps): %d, tRP (ps): %d, tRP (nck): %d for target: %s", @@ -3259,10 +3622,10 @@ fapi2::ReturnCode eff_dimm::dram_trcd() int64_t l_trcd_mtb = 0; int64_t l_trcd_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trcd(l_trcd_mtb), + FAPI_TRY( iv_spd_decoder.min_trcd(l_trcd_mtb), "Failed min_trcd() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trcd(l_trcd_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trcd(l_trcd_ftb), "Failed fine_offset_min_trcd() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCD (MTB): %ld, tRCD (FTB): %ld", @@ -3276,7 +3639,7 @@ fapi2::ReturnCode eff_dimm::dram_trcd() uint8_t l_trcd_in_nck = 0; // Calculate nck - FAPI_TRY( spd::calc_nck(l_trcd_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trcd_in_nck), + FAPI_TRY( spd::calc_nck(l_trcd_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trcd_in_nck), "Error in calculating trcd for target %s, with value of l_trcd_in_ps: %d", mss::c_str(iv_dimm), l_trcd_in_ps); FAPI_INF("tCK (ps): %d, tRCD (ps): %d, tRCD (nck): %d for target: %s", @@ -3309,10 +3672,10 @@ fapi2::ReturnCode eff_dimm::dram_trc() int64_t l_trc_mtb = 0; int64_t l_trc_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trc(l_trc_mtb), + FAPI_TRY( iv_spd_decoder.min_trc(l_trc_mtb), "Failed min_trc() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trc(l_trc_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trc(l_trc_ftb), "Failed fine_offset_min_trc() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCmin (MTB): %ld, tRCmin(FTB): %ld", @@ -3326,7 +3689,7 @@ fapi2::ReturnCode eff_dimm::dram_trc() uint8_t l_trc_in_nck = 0; // Calculate nck - FAPI_TRY( spd::calc_nck(l_trc_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trc_in_nck), + FAPI_TRY( spd::calc_nck(l_trc_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trc_in_nck), "Error in calculating trc for target %s, with value of l_trc_in_ps: %d", mss::c_str(iv_dimm), l_trc_in_ps ); @@ -3360,7 +3723,7 @@ fapi2::ReturnCode eff_dimm::dram_twtr_l() constexpr int64_t l_twtr_l_ftb = 0; int64_t l_twtr_l_mtb = 0; - FAPI_TRY( iv_pDecoder->min_twtr_l(l_twtr_l_mtb) ); + FAPI_TRY( iv_spd_decoder.min_twtr_l(l_twtr_l_mtb) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld", mss::c_str(iv_dimm), iv_mtb, iv_ftb, l_twtr_l_mtb, l_twtr_l_ftb ); @@ -3374,7 +3737,7 @@ fapi2::ReturnCode eff_dimm::dram_twtr_l() int8_t l_twtr_l_in_nck = 0; // Calculate nck - FAPI_TRY( spd::calc_nck(l_twtr_l_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_l_in_nck), + FAPI_TRY( spd::calc_nck(l_twtr_l_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_l_in_nck), "Error in calculating tWTR_L for target %s, with value of l_twtr_in_ps: %d", mss::c_str(iv_dimm), l_twtr_l_in_ps ); FAPI_INF( "tCK (ps): %d, tWTR_L (ps): %d, tWTR_L (nck): %d for target: %s", @@ -3407,7 +3770,7 @@ fapi2::ReturnCode eff_dimm::dram_twtr_s() constexpr int64_t l_twtr_s_ftb = 0; int64_t l_twtr_s_mtb = 0; - FAPI_TRY( iv_pDecoder->min_twtr_s(l_twtr_s_mtb) ); + FAPI_TRY( iv_spd_decoder.min_twtr_s(l_twtr_s_mtb) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld", mss::c_str(iv_dimm), iv_mtb, iv_ftb, l_twtr_s_mtb, l_twtr_s_ftb ); @@ -3420,7 +3783,7 @@ fapi2::ReturnCode eff_dimm::dram_twtr_s() uint8_t l_twtr_s_in_nck = 0; // Calculate nck - FAPI_TRY( spd::calc_nck(l_twtr_s_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_s_in_nck), + FAPI_TRY( spd::calc_nck(l_twtr_s_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_s_in_nck), "Error in calculating tWTR_S for target %s, with value of l_twtr_in_ps: %d", mss::c_str(iv_dimm), l_twtr_s_in_ps); FAPI_INF("tCK (ps): %d, tWTR_S (ps): %d, tWTR_S (nck): %d for target: %s", @@ -3449,7 +3812,7 @@ fapi2::ReturnCode eff_dimm::nibble_map() uint8_t l_attr[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_DQ_NIBBLES] = {}; std::vector<uint8_t> l_nibble_bitmap; - FAPI_TRY( iv_pDecoder->nibble_map(l_nibble_bitmap) ); + FAPI_TRY( iv_spd_decoder.nibble_map(l_nibble_bitmap) ); // Sanity check we retrieved a vector w/the right size FAPI_ASSERT( l_nibble_bitmap.size() == MAX_DQ_NIBBLES, @@ -3482,7 +3845,7 @@ fapi2::ReturnCode eff_dimm::package_rank_map() uint8_t l_attr[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_DQ_NIBBLES] = {}; std::vector<uint8_t> l_package_rank_map; - FAPI_TRY( iv_pDecoder->package_rank_map(l_package_rank_map) ); + FAPI_TRY( iv_spd_decoder.package_rank_map(l_package_rank_map) ); // Sanity check we retrieved a vector w/the right size FAPI_ASSERT( l_package_rank_map.size() == MAX_DQ_NIBBLES, @@ -3540,17 +3903,16 @@ fapi2::ReturnCode eff_dimm::dram_trrd_s() uint64_t l_trrd_s_in_nck = 0; int64_t l_trrd_s_in_ps = 0; uint64_t l_jedec_trrd = 0; - uint8_t l_dram_width = 0; // Calculate tRRD_S { int64_t l_trrd_s_mtb = 0; int64_t l_trrd_s_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trrd_s(l_trrd_s_mtb), + FAPI_TRY( iv_spd_decoder.min_trrd_s(l_trrd_s_mtb), "Failed min_trrd_s() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trrd_s(l_trrd_s_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trrd_s(l_trrd_s_ftb), "Failed fine_offset_min_trrd_s() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, trrd_s (MTB): %ld", @@ -3569,16 +3931,13 @@ fapi2::ReturnCode eff_dimm::dram_trrd_s() FAPI_DBG("TRRD_S in ps is %d", l_trrd_s_in_ps); - FAPI_TRY( spd::calc_nck(l_trrd_s_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_s_in_nck), + FAPI_TRY( spd::calc_nck(l_trrd_s_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_s_in_nck), "Error in calculating l_tFAW for target %s, with value of l_trrd_s_in_ps: %d", mss::c_str(iv_dimm), l_trrd_s_in_nck); } - FAPI_TRY( iv_pDecoder->device_width(l_dram_width), - "Failed device_width()"); - - FAPI_TRY( trrd_s( iv_dimm, l_dram_width, l_jedec_trrd) ); + FAPI_TRY( trrd_s( iv_dimm, iv_dram_width, l_jedec_trrd) ); // Taking the worst case between the required minimum JEDEC value and the proposed value from SPD if (l_jedec_trrd != l_trrd_s_in_nck) @@ -3587,14 +3946,14 @@ fapi2::ReturnCode eff_dimm::dram_trrd_s() mss::c_str(iv_dimm), l_jedec_trrd, l_trrd_s_in_nck, - l_dram_width, + iv_dram_width, iv_freq); l_trrd_s_in_nck = std::max( l_jedec_trrd, l_trrd_s_in_nck); } FAPI_INF("SDRAM width: %d, tFAW (nck): %d for target: %s", - l_dram_width, l_trrd_s_in_nck, mss::c_str(iv_dimm)); + iv_dram_width, l_trrd_s_in_nck, mss::c_str(iv_dimm)); // Get & update MCS attribute FAPI_TRY( eff_dram_trrd_s(iv_mcs, l_attrs_dram_trrd_s.data()) ); @@ -3619,17 +3978,16 @@ fapi2::ReturnCode eff_dimm::dram_trrd_l() std::vector<uint8_t> l_attrs_dram_trrd_l(PORTS_PER_MCS, 0); uint64_t l_trrd_l_in_nck = 0; int64_t l_trrd_l_in_ps = 0; - uint8_t l_dram_width = 0; uint64_t l_jedec_trrd = 0; // Calculate tRRD_L { int64_t l_trrd_l_mtb = 0; int64_t l_trrd_l_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trrd_l(l_trrd_l_mtb), + FAPI_TRY( iv_spd_decoder.min_trrd_l(l_trrd_l_mtb), "Failed min_trrd_l() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trrd_l(l_trrd_l_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trrd_l(l_trrd_l_ftb), "Failed fine_offset_min_trrd_l() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, trrd_l (MTB): %ld", @@ -3649,16 +4007,13 @@ fapi2::ReturnCode eff_dimm::dram_trrd_l() FAPI_DBG("TRRD_L in ps is %d", l_trrd_l_in_ps); - FAPI_TRY( spd::calc_nck(l_trrd_l_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_l_in_nck), + FAPI_TRY( spd::calc_nck(l_trrd_l_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_l_in_nck), "Error in calculating l_tFAW for target %s, with value of l_trrd_l_in_ps: %d", mss::c_str(iv_dimm), l_trrd_l_in_nck); } - FAPI_TRY( iv_pDecoder->device_width(l_dram_width), - "Failed device_width()"); - - FAPI_TRY( trrd_l( iv_dimm, l_dram_width, l_jedec_trrd) ); + FAPI_TRY( trrd_l( iv_dimm, iv_dram_width, l_jedec_trrd) ); // Taking the worst case between the required minimum JEDEC value and the proposed value from SPD if (l_jedec_trrd != l_trrd_l_in_nck) @@ -3667,14 +4022,14 @@ fapi2::ReturnCode eff_dimm::dram_trrd_l() mss::c_str(iv_dimm), l_jedec_trrd, l_trrd_l_in_nck, - l_dram_width, + iv_dram_width, iv_freq); l_trrd_l_in_nck = std::max( l_jedec_trrd, l_trrd_l_in_nck); } FAPI_INF("SDRAM width: %d, tFAW (nck): %d for target: %s", - l_dram_width, l_trrd_l_in_nck, mss::c_str(iv_dimm)); + iv_dram_width, l_trrd_l_in_nck, mss::c_str(iv_dimm)); // Get & update MCS attribute FAPI_TRY( eff_dram_trrd_l(iv_mcs, l_attrs_dram_trrd_l.data()) ); @@ -3726,14 +4081,13 @@ fapi2::ReturnCode eff_dimm::dram_tfaw() uint64_t l_tfaw_in_nck = 0; uint64_t l_jedec_tfaw_in_nck = 0; int64_t l_tfaw_in_ps = 0; - uint8_t l_dram_width = 0; int64_t l_tfaw_ftb = 0; // Calculate tFAW { int64_t l_tfaw_mtb = 0; - FAPI_TRY( iv_pDecoder->min_tfaw(l_tfaw_mtb), + FAPI_TRY( iv_spd_decoder.min_tfaw(l_tfaw_mtb), "Failed min_tfaw() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tfaw (MTB): %ld", @@ -3752,16 +4106,13 @@ fapi2::ReturnCode eff_dimm::dram_tfaw() FAPI_DBG("%s TFAW in ps is %d", mss::c_str(iv_dimm), l_tfaw_in_ps); - FAPI_TRY( spd::calc_nck(l_tfaw_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_tfaw_in_nck), + FAPI_TRY( spd::calc_nck(l_tfaw_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_tfaw_in_nck), "Error in calculating l_tFAW for target %s, with value of l_tfaw_in_ps: %d", mss::c_str(iv_dimm), l_tfaw_in_nck); } - FAPI_TRY( iv_pDecoder->device_width(l_dram_width), - "Failed device_width()"); - - FAPI_TRY( mss::tfaw(iv_dimm, l_dram_width, l_jedec_tfaw_in_nck), "Failed tfaw()" ); + FAPI_TRY( mss::tfaw(iv_dimm, iv_dram_width, l_jedec_tfaw_in_nck), "Failed tfaw()" ); // Taking the worst case between the required minimum JEDEC value and the proposed value from SPD if (l_jedec_tfaw_in_nck != l_tfaw_in_nck) @@ -3770,14 +4121,14 @@ fapi2::ReturnCode eff_dimm::dram_tfaw() mss::c_str(iv_dimm), l_jedec_tfaw_in_nck, l_tfaw_in_nck, - l_dram_width, + iv_dram_width, iv_freq); l_tfaw_in_nck = std::max(l_jedec_tfaw_in_nck, l_tfaw_in_nck); } FAPI_INF("SDRAM width: %d, tFAW (nck): %d for target: %s", - l_dram_width, l_tfaw_in_nck, mss::c_str(iv_dimm)); + iv_dram_width, l_tfaw_in_nck, mss::c_str(iv_dimm)); // Get & update MCS attribute FAPI_TRY( eff_dram_tfaw(iv_mcs, l_attrs_dram_tfaw.data()) ); @@ -3842,7 +4193,7 @@ fapi2::ReturnCode eff_dimm::dram_tras() // addition with negative integers. FAPI_TRY( spd::calc_nck(l_tras_in_ps, static_cast<uint64_t>(iv_tCK_in_ps), - INVERSE_DDR4_CORRECTION_FACTOR, + spd::INVERSE_DDR4_CORRECTION_FACTOR, l_tras_in_nck), "Error in calculating tras_l for target %s, with value of l_twtr_in_ps: %d", mss::c_str(iv_dimm), l_tras_in_ps); @@ -3878,7 +4229,7 @@ fapi2::ReturnCode eff_dimm::dram_trtp() uint8_t l_calc_trtp_in_nck = 0; // Calculate nck - FAPI_TRY( spd::calc_nck(l_max_trtp_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_calc_trtp_in_nck), + FAPI_TRY( spd::calc_nck(l_max_trtp_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_calc_trtp_in_nck), "Error in calculating trtp for target %s, with value of l_twtr_in_ps: %d", mss::c_str(iv_dimm), l_max_trtp_in_ps); @@ -3974,7 +4325,7 @@ fapi2::ReturnCode eff_lrdimm::dram_rtt_nom() FAPI_TRY( eff_dram_rtt_nom(iv_mcs, &l_mcs_attrs[0][0][0]) ); // Get the value from the LRDIMM SPD - FAPI_TRY( iv_pDecoder->iv_module_decoder->dram_rtt_nom(iv_freq, l_decoder_val)); + FAPI_TRY( iv_spd_decoder.dram_rtt_nom(iv_freq, l_decoder_val)); // Plug into every rank position for the attribute so it'll fit the same style as the RDIMM value // Same value for every rank for LRDIMMs @@ -4057,7 +4408,7 @@ fapi2::ReturnCode eff_lrdimm::dram_rtt_wr() uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; // Get the value from the LRDIMM SPD - FAPI_TRY( iv_pDecoder->iv_module_decoder->dram_rtt_wr(iv_freq, l_decoder_val)); + FAPI_TRY( iv_spd_decoder.dram_rtt_wr(iv_freq, l_decoder_val)); // Plug into every rank position for the attribute so it'll fit the same style as the RDIMM value // Same value for every rank for LRDIMMs @@ -4090,10 +4441,10 @@ fapi2::ReturnCode eff_rdimm::dram_rtt_park() // for mss::index 1. So this doesn't correspond directly with the table in the JEDEC spec, // as that's not in "denominator order." constexpr uint64_t RTT_PARK_COUNT = 8; - // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 - constexpr uint8_t rtt_park_map[RTT_PARK_COUNT] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; + // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 + constexpr uint8_t const rtt_park_map[RTT_PARK_COUNT] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; - uint8_t l_rtt_park[MAX_RANK_PER_DIMM]; + uint8_t l_rtt_park[MAX_RANK_PER_DIMM] = {}; FAPI_TRY( mss::vpd_mt_dram_rtt_park(iv_dimm, &(l_rtt_park[0])) ); FAPI_TRY( eff_dram_rtt_park(iv_mcs, &l_mcs_attrs[0][0][0]) ); @@ -4133,8 +4484,8 @@ fapi2::ReturnCode eff_lrdimm::dram_rtt_park() FAPI_TRY( eff_dram_rtt_park(iv_mcs, &l_mcs_attrs[0][0][0]) ); // Get the value from the LRDIMM SPD - FAPI_TRY( iv_pDecoder->iv_module_decoder->dram_rtt_park_ranks0_1(iv_freq, l_decoder_val_01) ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->dram_rtt_park_ranks2_3(iv_freq, l_decoder_val_23) ); + FAPI_TRY( iv_spd_decoder.dram_rtt_park_ranks0_1(iv_freq, l_decoder_val_01) ); + FAPI_TRY( iv_spd_decoder.dram_rtt_park_ranks2_3(iv_freq, l_decoder_val_23) ); // Setting the four rank values for this dimm // Rank 0 and 1 have the same value, l_decoder_val_01 @@ -4457,7 +4808,7 @@ fapi2::ReturnCode eff_lrdimm::dimm_bc04() // So the encoding from the SPD is the same as the encoding for the buffer control encoding // Simple grab and insert // Value is checked in decoder function for validity - FAPI_TRY( iv_pDecoder->iv_module_decoder->data_buffer_mdq_rtt(iv_freq, l_decoder_val) ); + FAPI_TRY( iv_spd_decoder.data_buffer_mdq_rtt(iv_freq, l_decoder_val) ); // Update MCS attribute @@ -4485,7 +4836,7 @@ fapi2::ReturnCode eff_lrdimm::dimm_bc05() FAPI_TRY( eff_dimm_ddr4_bc05(iv_mcs, &l_attrs_dimm_bc05[0][0]) ); // Same as BC04, grab from SPD and put into BC - FAPI_TRY( iv_pDecoder->iv_module_decoder->data_buffer_mdq_drive_strength(iv_freq, l_decoder_val) ); + FAPI_TRY( iv_spd_decoder.data_buffer_mdq_drive_strength(iv_freq, l_decoder_val) ); l_attrs_dimm_bc05[iv_port_index][iv_dimm_index] = l_decoder_val; FAPI_INF("%s: BC05 settting (MDQ Drive Strenght): %d", mss::c_str(iv_dimm), @@ -4509,15 +4860,14 @@ fapi2::ReturnCode eff_lrdimm::dimm_bc07() // Map for the bc07 attribute, Each bit and its position represents one rank // 0b0 == enabled, 0b1 == disabled // 1 rank 2 rank 3 rank 4 rank - constexpr uint8_t dram_map [MAX_RANK_PER_DIMM] = {0b1110, 0b1100, 0b1000, 0b0000}; - + constexpr uint8_t const dram_map [MAX_RANK_PER_DIMM] = {0b1110, 0b1100, 0b1000, 0b0000}; uint8_t l_ranks_per_dimm = 0; // Retrieve MCS attribute data uint8_t l_attrs_dimm_bc07[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( iv_pDecoder->num_package_ranks_per_dimm(l_ranks_per_dimm) ); - + // It is safe to use the attribute accessor directly since it is set in mss_freq + FAPI_TRY( eff_num_master_ranks_per_dimm(iv_dimm, l_ranks_per_dimm) ); FAPI_TRY( eff_dimm_ddr4_bc07(iv_mcs, &l_attrs_dimm_bc07[0][0]) ); // Subtract so 1 rank == 0, 2 rank == 1, etc. For array mss::indexing diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.H index 85d36d904..7e33c0bdb 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.H @@ -28,14 +28,19 @@ // *HWP Level: 3 // *HWP Consumed by: FSP:HB - #ifndef _MSS_EFF_DIMM_H_ #define _MSS_EFF_DIMM_H_ #include <fapi2.H> #include <lib/shared/mss_kind.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> +#include <lib/shared/mss_const.H> +#include <generic/memory/lib/spd/spd_facade.H> +#include <generic/memory/lib/spd/common/rcw_settings.H> +#include <lib/spd/spd_factory.H> #include <lib/eff_config/timing.H> +#include <generic/memory/lib/data_engine/pre_data_init.H> +#include <generic/memory/lib/spd/spd_utils.H> + namespace mss { @@ -65,11 +70,15 @@ class eff_dimm size_t iv_dimm_index; int64_t iv_ftb; // fine timebase int64_t iv_mtb; // medium timebase + rcw_settings iv_raw_card; + uint8_t iv_dram_width; + uint8_t iv_dram_die_count; public: uint64_t iv_freq; int64_t iv_tCK_in_ps; - const std::shared_ptr<spd::decoder> iv_pDecoder; + spd::facade iv_spd_decoder; + uint8_t iv_dram_density; // Assists testing with write ability on these MRW // settings that are normally NOT writable @@ -91,34 +100,48 @@ class eff_dimm }; + // eff_config SPD raw values to attribute mappings + static const std::vector<std::pair<uint8_t, uint8_t> > DEVICE_WIDTH_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > SDRAM_DENSITY_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > SOFT_PPR_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_MAP; + static const std::vector< std::pair<uint8_t, uint8_t> > BANK_ADDR_BITS_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > ROW_ADDRESS_BITS_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_DIE_COUNT_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > SEC_DIE_COUNT_MAP; + //Delete the default eff_dimm () = delete; /// /// @brief constructor for the base eff_dimm class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// - eff_dimm( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_dimm( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ): - iv_pDecoder(i_pDecoder) + iv_raw_card(i_rcw), + iv_spd_decoder(i_spd_decoder) { - FAPI_DBG("Constructing eff_dimm object"); - iv_dimm = iv_pDecoder->iv_target; + // Targeting and index info + iv_dimm = i_spd_decoder.get_dimm_target(); + FAPI_DBG("Constructing eff_dimm object for %s", mss::c_str(iv_dimm)); + iv_mca = find_target<fapi2::TARGET_TYPE_MCA>(iv_dimm); iv_mcs = find_target<fapi2::TARGET_TYPE_MCS>(iv_dimm); iv_port_index = mss::index(iv_mca); iv_dimm_index = mss::index(iv_dimm); - FAPI_TRY( iv_pDecoder->medium_timebase(iv_mtb), "Failed medium timebase in eff_dimm()" ); - FAPI_TRY( iv_pDecoder->fine_timebase(iv_ftb), "Failed medium timebase in eff_dimm()" ); - + // Set widely used parameters + FAPI_TRY( spd::get_timebases(iv_spd_decoder, iv_mtb, iv_ftb) ); + FAPI_TRY( set_dram_width_instance() ); + FAPI_TRY( set_prim_dram_die_count_instance() ); + FAPI_TRY( set_dram_density_instance() ); FAPI_TRY( clock_period(iv_dimm, iv_tCK_in_ps), "Failed to calculate clock period (tCK)" ); - FAPI_TRY( mss::mrw_refresh_rate_request(iv_refresh_rate_request), "Failed mrw_temp_refresh_rate_request()" ); FAPI_TRY( mss::mrw_fine_refresh_mode(iv_refresh_mode), "Failed mrw_fine_refresh_mode()" ); - FAPI_TRY( mss::freq(find_target<fapi2::TARGET_TYPE_MCBIST>(iv_dimm), iv_freq), "Failed accessing mss::freq in eff_dimm"); @@ -139,20 +162,20 @@ class eff_dimm /// /// @brief factory to make an eff_config DIMM object based on dimm kind (type, gen, and revision number) - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_fact_obj a shared pointer of the eff_dimm type /// - static fapi2::ReturnCode eff_dimm_factory ( const std::shared_ptr<spd::decoder>& i_pDecoder, - std::shared_ptr<eff_dimm>& o_fact_obj); + static fapi2::ReturnCode factory ( const spd::facade& i_spd_decoder, + std::shared_ptr<eff_dimm>& o_fact_obj); /// - /// @brief Determines & sets effective config for buffer and rev density + /// @brief Determines & sets effective config for buffer and rev type /// @param[in] i_target FAPI2 target - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @return fapi2::FAPI2_RC_SUCCESS if okay /// static fapi2::ReturnCode register_and_buffer_type( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::shared_ptr<spd::decoder>& i_pDecoder ); + const spd::facade& i_spd_decoder ); /// /// @brief Default destructor @@ -567,6 +590,12 @@ class eff_dimm fapi2::ReturnCode post_package_repair(); /// + /// @brief Determines & sets effective config for Soft Post Package Repair + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode soft_post_package_repair(); + + /// /// @brief Determines & sets effective config for rd_preamble_train /// @return fapi2::FAPI2_RC_SUCCESS if okay /// @@ -916,6 +945,46 @@ class eff_dimm /// virtual fapi2::ReturnCode dimm_bc0f() = 0; + private: + + /// + /// @brief Returns Logical ranks in Primary SDRAM type + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode prim_sdram_logical_ranks( uint8_t& o_logical_ranks ) const; + + /// + /// @brief Helper function that returns Logical ranks in SDRAM type + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode sec_sdram_logical_ranks( uint8_t& o_logical_ranks ) const; + + /// + /// @brief Returns Logical ranks per DIMM + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const; + + /// + /// @brief Helper function to set dram width instance variable + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode set_dram_width_instance(); + + /// + /// @brief Helper function to set dram density instance variable + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode set_dram_density_instance(); + + /// + /// @brief Helper function to set dram density instance variable + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode set_prim_dram_die_count_instance(); }; /// @@ -928,16 +997,17 @@ class eff_lrdimm : public eff_dimm public: /// /// @brief constructor for the eff_lrdimm class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// @note calls eff_dimm ctor /// - eff_lrdimm( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_lrdimm( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ): - eff_dimm ( i_pDecoder, o_rc ) + eff_dimm ( i_spd_decoder, i_rcw, o_rc ) { - FAPI_DBG("Constructing LRDIMM"); + FAPI_DBG("Constructing LRDIMM for %s", mss::c_str(iv_dimm)); } /// @@ -1070,16 +1140,17 @@ class eff_lrdimm_db01 : public eff_lrdimm /// /// @brief constructor for the eff_lrdimm_db01 (LRDIMM DataBuffer 1) class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// @note calls eff_dimm ctor /// - eff_lrdimm_db01( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_lrdimm_db01( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ) : - eff_lrdimm( i_pDecoder, o_rc ) + eff_lrdimm( i_spd_decoder, i_rcw, o_rc ) { - FAPI_DBG("Constructing LRDIMM_DB01"); + FAPI_DBG("Constructing LRDIMM_DB01 for %s", mss::c_str(iv_dimm)) } /// @@ -1126,16 +1197,17 @@ class eff_lrdimm_db02 : public eff_lrdimm /// /// @brief constructor for the eff_lrdimm_db02 (LRDIMM DataBuffer 2) class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// @note calls eff_dimm ctor /// - eff_lrdimm_db02( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_lrdimm_db02( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ) : - eff_lrdimm( i_pDecoder, o_rc ) + eff_lrdimm( i_spd_decoder, i_rcw, o_rc ) { - FAPI_DBG("Constructing LRDIMM_DB02"); + FAPI_DBG("Constructing LRDIMM_DB02 for %s", mss::c_str(iv_dimm)); } /// @@ -1179,16 +1251,17 @@ class eff_rdimm : public eff_dimm /// /// @brief constructor for the eff_rdimm_db01 (LRDIMM DataBuffer 1) class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// @note calls eff_dimm ctor /// - eff_rdimm( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_rdimm( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ) : - eff_dimm( i_pDecoder, o_rc ) + eff_dimm( i_spd_decoder, i_rcw, o_rc ) { - FAPI_DBG("Constructing RDIMM"); + FAPI_DBG("Constructing RDIMM for %s", mss::c_str(iv_dimm)); } /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C index ef49471e9..aeb61f126 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -25,9 +25,8 @@ /// @file attr_setters.C /// @brief Create setter functions for mss attributes /// -// *HWP HWP Owner: Jacob Harvey <jlharvey@us.ibm.com> +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> // *HWP HWP Backup: Andre A. Marin <aamarin@us.ibm.com> -// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com> // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: HB:FSP @@ -35,27 +34,62 @@ #include <fapi2.H> #include <generic/memory/lib/utils/find.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> +#include <generic/memory/lib/data_engine/pre_data_init.H> namespace mss { + /// /// @brief Set ATTR_MSS_VOLT_VDDR and ATTR_MSS_VOLT_VPP /// @param[in] i_target_mcs the MCS target -/// @param[in] l_selected_dram_voltage the voltage in millivolts for nominal voltage -/// @param[in] l_selected_dram_voltage_vpp voltage in millivolts for the VPP +/// @param[in] i_selected_dram_voltage the voltage in millivolts for nominal voltage +/// @param[in] i_selected_dram_voltage_vpp voltage in millivolts for the VPP +/// @note dram_voltage and dram_voltage_vpp are not const due to FAPI_ATTR_SET template deduction /// @return FAPI2_RC_SUCCESS iff ok /// - fapi2::ReturnCode set_voltage_attributes(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs, - uint32_t l_selected_dram_voltage, - uint32_t l_selected_dram_voltage_vpp) + uint32_t i_selected_dram_voltage, + uint32_t i_selected_dram_voltage_vpp) { const auto l_target_mcbist = find_target<fapi2::TARGET_TYPE_MCBIST>(i_target_mcs); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VOLT_VDDR, l_target_mcbist, l_selected_dram_voltage) ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VOLT_VPP, l_target_mcbist, l_selected_dram_voltage_vpp) ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VOLT_VDDR, l_target_mcbist, i_selected_dram_voltage) ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VOLT_VPP, l_target_mcbist, i_selected_dram_voltage_vpp) ); fapi_try_exit: return fapi2::current_err; } + +/// +/// @brief Sets pre_eff_config attributes +/// @param[in] i_target the DIMM target +/// @param[in] i_spd_decoder SPD decoder +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode set_pre_init_attrs( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const spd::facade& i_spd_decoder ) +{ + fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); + mss::pre_data_engine<mss::NIMBUS> l_data_engine(i_target, i_spd_decoder, l_rc); + FAPI_TRY(l_rc, "Failed to instantiate pre_data_engine object for %s", spd::c_str(i_target)); + + // Set attributes needed before eff_config + // DIMM type and DRAM gen are needed for c_str to aid debugging + FAPI_TRY(l_data_engine.set_dimm_type(), "Failed to set DIMM type %s", spd::c_str(i_target) ); + FAPI_TRY(l_data_engine.set_dram_gen(), "Failed to set DRAM gen %s", spd::c_str(i_target) ); + + // Hybrid and hybrid media help detect hybrid modules, specifically NVDIMMs for Nimbus + FAPI_TRY(l_data_engine.set_hybrid(), "Failed to set Hybrid %s", spd::c_str(i_target) ); + FAPI_TRY(l_data_engine.set_hybrid_media(), "Failed to set Hybrid Media %s", spd::c_str(i_target) ); + + // Number of master ranks needed for VPD decoding + // and dimm_ranks_configured is a PRD attr... + FAPI_TRY(l_data_engine.set_master_ranks(), "Failed to set Master ranks %s", spd::c_str(i_target) ); + FAPI_TRY(l_data_engine.set_dimm_ranks_configured(), "Failed to set DIMM ranks configured %s", spd::c_str(i_target) ); + +fapi_try_exit: + return fapi2::current_err; +} + } // mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H index 793d92fc9..976c1077d 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -27,37 +27,41 @@ /// @file attr_setters.H /// @brief Create setter functions for mss attributes /// -// *HWP HWP Owner: Jacob Harvey <jlharvey@us.ibm.com> +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> // *HWP HWP Backup: Andre A. Marin <aamarin@us.ibm.com> -// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com> // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: HB:FSP - - - #ifndef _MSS_ATTR_SETTERS_H_ #define _MSS_ATTR_SETTERS_H_ #include <fapi2.H> - - +#include <generic/memory/lib/spd/spd_facade.H> namespace mss { + /// /// @brief Set ATTR_MSS_VOLT_VDDR and ATTR_MSS_VOLT_VPP /// @param[in] i_target_mcs the MCS target -/// @param[in] l_selected_dram_voltage the voltage in millivolts for nominal voltage -/// @param[in] l_selected_dram_voltage_vpp voltage in millivolts for the VPP +/// @param[in] i_selected_dram_voltage the voltage in millivolts for nominal voltage +/// @param[in] i_selected_dram_voltage_vpp voltage in millivolts for the VPP +/// @note dram_voltage and dram_voltage_vpp are not const due to FAPI_ATTR_SET template deduction /// @return FAPI2_RC_SUCCESS iff ok /// - fapi2::ReturnCode set_voltage_attributes(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs, - uint32_t l_selected_dram_voltage, - uint32_t l_selected_dram_voltage_vpp); + uint32_t i_selected_dram_voltage, + uint32_t i_selected_dram_voltage_vpp); +/// +/// @brief Sets pre_eff_config attributes +/// @param[in] i_target the DIMM target +/// @param[in] i_spd_decoder SPD decoder +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode set_pre_init_attrs( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const spd::facade& i_spd_decoder ); } // mss #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C new file mode 100644 index 000000000..7cf3b7b3d --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C @@ -0,0 +1,239 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2018 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/// +/// @file nimbus_pre_data_engine.C +/// @brief pre_data_engine implimentation for Nimbus +/// +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: CI + +#include <generic/memory/lib/utils/index.H> +#include <lib/mss_attribute_accessors.H> +#include <lib/eff_config/attr_setters.H> +#include <generic/memory/lib/data_engine/pre_data_init.H> +#include <generic/memory/lib/utils/find.H> + +namespace mss +{ + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 2 (0x002): Key Byte / DRAM Device Type +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::DRAM_GEN_MAP = +{ + //{key value, dram gen} + {0x0C, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4} + // Other key bytes reserved or not supported +}; + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 3 (0x003): Key Byte / Module Type - Hybrid +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::HYBRID_MAP = +{ + //{key byte, dimm type} + {0, fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID}, + {1, fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID}, + // All others reserved or not supported +}; + + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 3 (0x003): Key Byte / Module Type - Hybrid +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::HYBRID_MEMORY_TYPE_MAP = +{ + + //{key byte, dimm type} + {0, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE}, + {1, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM}, + // All others reserved or not supported +}; + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 3 (0x003): Key Byte / Module Type +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::BASE_MODULE_TYPE_MAP = +{ + //{key byte, dimm type} + {1, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM}, + {2, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM}, + {4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM}, + // All others reserved or not supported +}; + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 12 (0x00C): Module Organization +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::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}, +}; + +/// +/// @brief ctor +/// @param[in] i_target the DIMM target +/// @param[in] i_spd_data SPD data +/// @param[out] o_rc ReturnCode for failure to init object +/// +pre_data_engine<NIMBUS>::pre_data_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const spd::facade& i_spd_data, + fapi2::ReturnCode& o_rc): + iv_dimm(i_target), + iv_spd_data(i_spd_data) +{ + // Sets up commonly used member variables + uint8_t l_master_ranks = 0; + FAPI_TRY(iv_spd_data.num_package_ranks_per_dimm(l_master_ranks)); + FAPI_TRY(lookup_table_check(i_target, NUM_PACKAGE_RANKS_MAP, PRE_DATA_ENGINE_CTOR, l_master_ranks, iv_master_ranks)); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; + return; +} + +/// +/// @brief Set ATTR_EFF_DIMM_TYPE +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dimm_type() +{ + uint8_t l_base_module_type = 0; + uint8_t l_dimm_type = 0; + + FAPI_TRY(iv_spd_data.base_module(l_base_module_type)); + FAPI_TRY(lookup_table_check(iv_dimm, BASE_MODULE_TYPE_MAP, SET_ATTR_DIMM_TYPE, l_base_module_type, l_dimm_type)); + FAPI_TRY( (set_field<NIMBUS, DIMM_TYPE>(iv_dimm, l_dimm_type)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set ATTR_EFF_DRAM_GEN +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dram_gen() +{ + uint8_t l_device_type = 0; + uint8_t l_dram_gen = 0; + + FAPI_TRY(iv_spd_data.device_type(l_device_type)); + FAPI_TRY(lookup_table_check(iv_dimm, DRAM_GEN_MAP, SET_ATTR_DRAM_GEN, l_device_type, l_dram_gen)); + + FAPI_TRY( (set_field<NIMBUS, DRAM_GEN>(iv_dimm, l_dram_gen)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set ATTR_EFF_HYBRID +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_hybrid() +{ + uint8_t l_spd_hybrid_type = 0; + uint8_t l_hybrid = 0; + + FAPI_TRY(iv_spd_data.hybrid(l_spd_hybrid_type)); + FAPI_TRY(lookup_table_check(iv_dimm, HYBRID_MAP, SET_ATTR_HYBRID, l_spd_hybrid_type, l_hybrid)); + + FAPI_TRY( (set_field<NIMBUS, HYBRID>(iv_dimm, l_hybrid)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set ATTR_EFF_HYBRID_MEMORY_TYPE +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_hybrid_media() +{ + uint8_t l_hybrid_media = 0; + uint8_t l_spd_hybrid_media = 0; + + FAPI_TRY(iv_spd_data.hybrid_media(l_spd_hybrid_media)); + FAPI_TRY(lookup_table_check(iv_dimm, HYBRID_MAP, SET_ATTR_HYBRID, l_spd_hybrid_media, l_hybrid_media)); + + FAPI_TRY( (set_field<NIMBUS, HYBRID_MEDIA>(iv_dimm, l_hybrid_media)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_master_ranks() +{ + FAPI_TRY( (set_field<NIMBUS, MRANKS>(iv_dimm, iv_master_ranks)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Sets ATTR_EFF_DIMM_RANKS_CONFIGED +/// @return FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dimm_ranks_configured() +{ + // Set configed ranks. Set the bit representing the master rank configured (0 being left most.) So, + // a 4R DIMM would be 0b11110000 (0xF0). This is used by PRD. + fapi2::buffer<uint8_t> l_ranks_configed; + + FAPI_TRY( l_ranks_configed.setBit(0, iv_master_ranks), + "%s. Failed to setBit", spd::c_str(iv_dimm) ); + + FAPI_TRY( (set_field<NIMBUS, DIMM_RANKS_CNFG>(iv_dimm, uint8_t(l_ranks_configed))) ); + +fapi_try_exit: + return fapi2::current_err; +} + +}//mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H index cb500c798..b4a715fb7 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H @@ -38,6 +38,7 @@ #include <cstdint> #include <fapi2.H> #include <generic/memory/lib/utils/find.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> #include <lib/utils/conversions.H> namespace mss @@ -62,17 +63,6 @@ enum functions TDLLK = 11, }; -enum guard_band : uint16_t -{ - // Used for caclulating spd timing values - from JEDEC rounding algorithm - // Correction factor is 1% (for DDR3) or 2.5% (for DDR4) - // when doing integer math, we add-in the inverse correction factor - // Formula used for derivation: - // Guardband = 1000 * (1000* correction_factor) - 1 - INVERSE_DDR3_CORRECTION_FACTOR = 989, ///< DDR3 correction factor - INVERSE_DDR4_CORRECTION_FACTOR = 974, ///< DDR4 correction factor -}; - enum refresh_rate : uint8_t { REF1X = 1, ///< Refresh rate 1X @@ -84,96 +74,6 @@ namespace spd { /// -/// @brief Calculates timing value -/// @param[in] i_timing_mtb timing value in MTB units -/// @param[in] i_mtb_multiplier SPD medium timebase -/// @param[in] i_timing_ftb fine offset of timing value -/// @param[in] i_ftb_multiplier SPD fine timebase -/// @return the timing value in picoseconds -/// -inline int64_t calc_timing_from_timebase(const int64_t i_timing_mtb, - const int64_t i_mtb_multiplier, - const int64_t i_timing_ftb, - const int64_t i_ftb_multiplier) -{ - // JEDEC algorithm - const int64_t l_timing_val = i_timing_mtb * i_mtb_multiplier; - const int64_t l_fine_offset = i_timing_ftb * i_ftb_multiplier; - - return l_timing_val + l_fine_offset; -} - -/// -/// @brief Helper to compute JEDEC's SPD rounding algorithm -/// to convert ps to nCK -/// @tparam T input type -/// @tparam OT output type -/// @param[in] i_timing_in_ps timing parameter in ps -/// @param[in] i_tck_in_ps clock period in ps -/// @param[in] i_inverse_corr_factor inverse correction factor (defined by JEDEC) -/// @param[out] o_value_nck the end calculation in nck -/// @return true if overflow didn't occur, false otherwise -/// @note DDR4 SPD Contents Rounding Algorithm -/// @note Item 2220.46 -/// -template<typename T, typename OT> -static inline bool jedec_spd_rounding_alg(const T& i_timing_in_ps, - const T& i_tck_in_ps, - const guard_band i_inverse_corr_factor, - OT& o_val_nck) -{ - // Preliminary nCK calculation, scaled by 1000 per JDEC algorithm - T l_temp_nck = (i_timing_in_ps * CONVERT_PS_IN_A_NS) / (i_tck_in_ps == 0 ? 1 : i_tck_in_ps); - l_temp_nck += i_inverse_corr_factor; - l_temp_nck = l_temp_nck / CONVERT_PS_IN_A_NS; - - // Check for overflow - // static_cast needed for HB compiler that complains about - // comparision of two different integral types - o_val_nck = l_temp_nck; - - FAPI_DBG("Input timing (ps) %d, tCK (ps) %d, temp output %d, output (nCK) %d", - i_timing_in_ps, i_tck_in_ps, l_temp_nck, o_val_nck); - - return (static_cast<T>(o_val_nck) == l_temp_nck); -} - -/// -/// @brief Returns clock cycles based on input application period -/// @tparam T input type -/// @tparam OT output type -/// @param[in] i_timing_in_ps timing parameter in ps -/// @param[in] i_tck_in_ps clock period in ps -/// @param[in] i_inverse_corr_factor inverse correction factor (defined by JEDEC) -/// @param[out] o_value_nck the end calculation in nck -/// @return FAPI2_RC_SUCCESS iff okay -/// @note DDR4 SPD Contents Rounding Algorithm -/// @note Item 2220.46 -/// -template<typename T, typename OT> -inline fapi2::ReturnCode calc_nck(const T& i_timing_in_ps, - const T& i_tck_in_ps, - const guard_band i_inverse_corr_factor, - OT& o_val_nck) -{ - FAPI_ASSERT( jedec_spd_rounding_alg(i_timing_in_ps, - i_tck_in_ps, - i_inverse_corr_factor, - o_val_nck), - fapi2::MSS_INVALID_CAST_CALC_NCK(). - set_TIMING_PS(i_timing_in_ps). - set_NCK_NS(i_tck_in_ps). - set_CORRECTION_FACTOR(i_inverse_corr_factor), - "Overflow occured. Returned data is %d", o_val_nck); - - // If we don't assert, we don't know what's in current_err ... - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// /// @brief Returns clock cycles form picoseconds based on speed bin /// Uses SPD rounding algorithm for DDR4 /// @tparam T the target type from which to get the mt/s @@ -201,7 +101,7 @@ inline OT ps_to_nck( const fapi2::Target<T>& i_target, const OT& i_timing_in_ps) FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps), "Failed freq() accessor" ); - FAPI_TRY( calc_nck(i_timing_in_ps, l_tck_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_temp_nck), + FAPI_TRY( calc_nck(i_timing_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_temp_nck), "Failed calc_nck()" ); return l_temp_nck; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C index b81796771..1e1494560 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C @@ -42,8 +42,9 @@ // mss lib #include <lib/freq/cas_latency.H> -#include <lib/spd/spd_factory.H> +#include <generic/memory/lib/data_engine/pre_data_init.H> #include <lib/eff_config/timing.H> +#include <generic/memory/lib/spd/spd_utils.H> #include <generic/memory/lib/utils/find.H> #include <lib/utils/checker.H> @@ -66,7 +67,7 @@ namespace mss /// @param[out] o_rc returns FAPI2_RC_SUCCESS if constructor initialzed successfully /// cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, - const std::vector< std::shared_ptr<spd::decoder> >& i_caches, + const std::vector< spd::facade >& i_caches, const std::vector<uint32_t>& i_supported_freqs, fapi2::ReturnCode& o_rc): iv_dimm_list_empty(false), @@ -88,16 +89,16 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, for ( const auto& l_cache : i_caches ) { // Retrieve timing values from the SPD - const auto l_target = l_cache->iv_target; + const auto l_target = l_cache.get_dimm_target(); uint64_t l_taa_min_in_ps = 0; uint64_t l_tckmax_in_ps = 0; uint64_t l_tck_min_in_ps = 0; FAPI_TRY( get_taamin(l_cache, l_taa_min_in_ps), "%s. Failed to get tAAmin", mss::c_str(l_target) ); - FAPI_TRY( get_tckmax(l_cache, l_tckmax_in_ps), + FAPI_TRY( spd::get_tckmax(l_cache, l_tckmax_in_ps), "%s. Failed to get tCKmax", mss::c_str(l_target) ); - FAPI_TRY( get_tckmin(l_cache, l_tck_min_in_ps), + FAPI_TRY( spd::get_tckmin(l_cache, l_tck_min_in_ps), "%s. Failed to get tCKmin", mss::c_str(l_target) ); // Determine largest tAAmin value @@ -114,7 +115,7 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, if( iv_is_3ds != loading::IS_3DS) { uint8_t l_stack_type = 0; - FAPI_TRY( l_cache->prim_sdram_signal_loading(l_stack_type) ); + FAPI_TRY( l_cache.prim_sdram_signal_loading(l_stack_type) ); // Is there a more algorithmic efficient approach? - AAM iv_is_3ds = (l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) ? @@ -124,7 +125,7 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, { // Retrieve dimm supported cas latencies from SPD uint64_t l_dimm_supported_cl = 0; - FAPI_TRY( l_cache->supported_cas_latencies(l_dimm_supported_cl), + FAPI_TRY( l_cache.supported_cas_latencies(l_dimm_supported_cl), "%s. Failed to get supported CAS latency", mss::c_str(l_target) ); // Bitwise ANDING the bitmap from all modules creates a bitmap w/a common CL @@ -312,11 +313,11 @@ fapi_try_exit: /// /// @brief Retrieves SDRAM Minimum CAS Latency Time (tAAmin) from SPD -/// @param[in] i_pDecoder the SPD decoder +/// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_value tCKmin value in ps /// @return FAPI2_RC_SUCCESS iff ok /// -fapi2::ReturnCode cas_latency::get_taamin( const std::shared_ptr<mss::spd::decoder>& i_pDecoder, +fapi2::ReturnCode cas_latency::get_taamin( const mss::spd::facade& i_spd_decoder, uint64_t& o_value ) { int64_t l_timing_ftb = 0; @@ -326,15 +327,14 @@ fapi2::ReturnCode cas_latency::get_taamin( const std::shared_ptr<mss::spd::decod int64_t l_temp = 0; // Retrieve timing parameters - const auto l_target = i_pDecoder->iv_target; + const auto l_target = i_spd_decoder.get_dimm_target(); - FAPI_TRY( i_pDecoder->medium_timebase(l_medium_timebase), - "%s. Failed medium_timebase()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_timebase(l_fine_timebase), - "%s. Failed fine_timebase()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->min_taa(l_timing_mtb), + FAPI_TRY( get_timebases(i_spd_decoder, l_medium_timebase, l_fine_timebase), + "%s. Failed Failed get_timebases", mss::c_str(l_target) ); + + FAPI_TRY( i_spd_decoder.min_taa(l_timing_mtb), "%s. Failed min_taa()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_offset_min_taa(l_timing_ftb), + FAPI_TRY( i_spd_decoder.fine_offset_min_taa(l_timing_ftb), "%s. Failed fine_offset_min_taa()", mss::c_str(l_target) ); // Calculate timing value @@ -409,7 +409,7 @@ inline fapi2::ReturnCode cas_latency::calc_cas_latency(const uint64_t i_taa, const uint64_t i_tck, uint64_t& o_cas_latency) const { - FAPI_TRY( spd::calc_nck(i_taa, i_tck, INVERSE_DDR4_CORRECTION_FACTOR, o_cas_latency) ); + FAPI_TRY( spd::calc_nck(i_taa, i_tck, spd::INVERSE_DDR4_CORRECTION_FACTOR, o_cas_latency) ); FAPI_INF("%s. tAA (ps): %d, tCK (ps): %d, CL (nck): %d", mss::c_str(iv_target), diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H index 6c9ad087c..bd01e5dc9 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H @@ -45,7 +45,7 @@ #include <fapi2.H> // mss lib -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> +#include <generic/memory/lib/spd/spd_facade.H> #include <lib/utils/conversions.H> #include <lib/freq/sync.H> @@ -132,7 +132,7 @@ class cas_latency /// @param[out] o_rc returns FAPI2_RC_SUCCESS if constructor initialzed successfully /// cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target_mcs, - const std::vector< std::shared_ptr<spd::decoder> >& i_caches, + const std::vector< spd::facade >& i_caches, const std::vector<uint32_t>& i_supported_freqs, fapi2::ReturnCode& o_rc); @@ -277,11 +277,11 @@ class cas_latency /// /// @brief Retrieves SDRAM Minimum CAS Latency Time (tAAmin) from SPD - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_value tCKmin value in ps /// @return FAPI2_RC_SUCCESS iff ok /// - fapi2::ReturnCode get_taamin(const std::shared_ptr<mss::spd::decoder>& i_pDecoder, + fapi2::ReturnCode get_taamin(const mss::spd::facade& i_spd_decoder, uint64_t& o_value); /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C b/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C index 35f6daa10..0d9d4c0f8 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C @@ -42,8 +42,9 @@ #include <lib/freq/sync.H> #include <generic/memory/lib/utils/find.H> #include <lib/utils/assert_noexit.H> -#include <lib/spd/spd_factory.H> #include <generic/memory/lib/utils/count_dimm.H> +#include <generic/memory/lib/spd/spd_facade.H> +#include <generic/memory/lib/spd/spd_utils.H> using fapi2::TARGET_TYPE_DIMM; using fapi2::TARGET_TYPE_MCS; @@ -445,25 +446,23 @@ fapi2::ReturnCode spd_supported_freq(const fapi2::Target<TARGET_TYPE_MCBIST>& i_ o_supported_freqs = std::vector<uint32_t>(PORTS_PER_MCBIST, ~(0)); // Get cached decoder - std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches; - - FAPI_TRY( mss::spd::populate_decoder_caches(i_target, l_factory_caches), - "%s. Failed to populate decoder cache", mss::c_str(i_target) ); + std::vector< mss::spd::facade > l_spd_facades; + FAPI_TRY( get_spd_decoder_list(i_target, l_spd_facades) ); // Looking for the biggest application period on an MC. // This will further reduce supported frequencies the system can run on. - for ( const auto& l_cache : l_factory_caches ) + for ( const auto& l_cache : l_spd_facades ) { - const auto l_dimm = l_cache->iv_target; + const auto l_dimm = l_cache.get_dimm_target(); const auto l_mca = mss::find_target<TARGET_TYPE_MCA>(l_dimm); const auto l_port_pos = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(l_mca); uint64_t l_tckmax_in_ps = 0; uint64_t l_tck_min_in_ps = 0; uint32_t l_dimm_freq = 0; - FAPI_TRY( get_tckmax(l_cache, l_tckmax_in_ps), + FAPI_TRY( spd::get_tckmax(l_cache, l_tckmax_in_ps), "%s. Failed to get tCKmax", mss::c_str(l_dimm) ); - FAPI_TRY( get_tckmin(l_cache, l_tck_min_in_ps), + FAPI_TRY( spd::get_tckmin(l_cache, l_tck_min_in_ps), "%s. Failed to get tCKmin", mss::c_str(l_dimm) ); // Determine a proposed tCK value that is greater than or equal tCKmin diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C index 0589d11ae..a0622f929 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C @@ -39,7 +39,7 @@ // mss lib #include <lib/power_thermal/throttle.H> #include <generic/memory/lib/utils/count_dimm.H> -#include <mss.H> + using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_MCS; using fapi2::TARGET_TYPE_DIMM; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H index 768917bcf..189583cfa 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H @@ -37,7 +37,9 @@ #define _MSS_POWER_THROTTLE_ #include <fapi2.H> -#include <mss.H> +#include <lib/shared/mss_const.H> +#include <lib/mss_attribute_accessors.H> + namespace mss { namespace power_thermal diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H index 63ab07aa1..6535cab1e 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H @@ -37,6 +37,7 @@ #define _MSS_CONST_H_ #include <cstdint> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> #include <generic/memory/lib/utils/mss_math.H> namespace mss @@ -51,9 +52,6 @@ enum sizes MCBIST_PER_MC = 1, MAX_DIMM_PER_PORT = 2, MAX_RANK_PER_DIMM = 4, - NIBBLES_PER_BYTE = 2, - BITS_PER_NIBBLE = 4, - BITS_PER_BYTE = 8, BITS_PER_DP = 16, NIBBLES_PER_DP = BITS_PER_DP / BITS_PER_NIBBLE, BYTES_PER_DP = BITS_PER_DP / BITS_PER_BYTE, @@ -122,9 +120,6 @@ enum sizes enum times { - CONVERT_PS_IN_A_NS = 1000, ///< 1000 pico in an nano - CONVERT_PS_IN_A_US = 1000000, ///< 1000000 picos in a micro - DELAY_1NS = 1, DELAY_10NS = 10 , ///< general purpose 10 ns delay for HW mode DELAY_100NS = 100, ///< general purpose 100 ns delay for HW mode @@ -134,9 +129,6 @@ enum times DELAY_1MS = 1000000, ///< general purpose 1 ms delay for HW mode // Not *exactly* a time but go with it. - MHZ_TO_KHZ = 1000, - - SEC_IN_HOUR = 60 * 60, ///< seconds in an hour, used for scrub times BG_SCRUB_IN_HOURS = 12, CMD_TIMEBASE = 8192, ///< Represents the timebase multiplier for the MCBIST inter cmd gap @@ -145,13 +137,34 @@ enum times }; /// -/// @brief ID codes so we can lookup which function triggered the ffdc fail +/// @brief function ID codes for FFDC functions +/// @note If we get a fail in HB, we can trace back to the function that failed /// enum ffdc_function_codes { + // Following are used in rank.H + RANK_PAIR_TO_PHY = 0, + RANK_PAIR_FROM_PHY = 1, + SET_RANKS_IN_PAIR = 2, + GET_RANKS_IN_PAIR = 3, + GET_RANK_FIELD = 4, + GET_PAIR_VALID = 5, + SET_RANK_FIELD = 6, + RD_CTR_WORKAROUND_READ_DATA = 7, + OVERRIDE_ODT_WR_CONFIG = 8, + RECORD_BAD_BITS_HELPER = 9, + SET_PAIR_VALID = 10, + // Used in eff_dimm.C + SET_DRAM_DENSITY_INSTANCE = 19, NIBBLE_MAP_FUNC = 20, PACKAGE_RANK_MAP_FUNC = 21, + SET_DRAM_WIDTH_INSTANCE = 22, + PRIM_DIE_COUNT = 23, + DIMM_SIZE = 24, + DRAM_BANK_BITS = 25, + DRAM_ROW_BITS = 26, + SOFT_POST_PACKAGE_REPAIR = 27, // Used in fw_mark_store.H for MSS_INVALID_RANK_PASSED FWMS_READ = 30, @@ -186,10 +199,6 @@ enum ffdc_function_codes GET_DRAM_DISABLE_REG_AND_POS = 94, GET_STARTING_WR_DQ_DELAY_VALUE = 95, - GET_TAAMIN = 96, - GET_TCKMIN = 97, - GET_TCKMAX = 98, - SUPPORTED_FREQS = 99, SELECT_SUPPORTED_FREQ = 100, @@ -228,25 +237,6 @@ enum states NO_CHIP_SELECT_ACTIVE = 0xFF, }; -/// -/// @brief function ID codes for FFDC functions -/// @note If we get a fail in HB, we can trace back to the function that failed -/// -enum ffdc_functions -{ - // Following are used in rank.H - RANK_PAIR_TO_PHY = 0, - RANK_PAIR_FROM_PHY = 1, - SET_RANKS_IN_PAIR = 2, - GET_RANKS_IN_PAIR = 3, - GET_RANK_FIELD = 4, - GET_PAIR_VALID = 5, - SET_RANK_FIELD = 6, - RD_CTR_WORKAROUND_READ_DATA = 7, - OVERRIDE_ODT_WR_CONFIG = 8, - RECORD_BAD_BITS_HELPER = 9, - SET_PAIR_VALID = 10, -}; // Static consts describing the bits used in the cal_step_enable attribute // These are bit positions. 0 is the left most bit. enum cal_steps : uint64_t diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_kind.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_kind.H index 6ffea0585..c1b07f643 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_kind.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_kind.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -62,18 +62,18 @@ enum kind_t FORCE_DISPATCH = 4 + 1, }; -inline mss::kind_t dimm_kind( const uint64_t l_type, const uint64_t l_gen ) +inline mss::kind_t dimm_kind( const uint64_t i_type, const uint64_t i_gen ) { // This is the conditional needed to differentiate dimm type/generation - switch (l_type) + switch (i_type) { case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM: - if (l_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_EMPTY) + if (i_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_EMPTY) { return KIND_RDIMM_EMPTY; } - if (l_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) + if (i_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) { return KIND_RDIMM_DDR4; } @@ -82,12 +82,12 @@ inline mss::kind_t dimm_kind( const uint64_t l_type, const uint64_t l_gen ) break; case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM: - if (l_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_EMPTY) + if (i_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_EMPTY) { return KIND_LRDIMM_EMPTY; } - if (l_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) + if (i_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) { return KIND_LRDIMM_DDR4; } diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C index 10e23a6f2..1dd9cb759 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C @@ -46,10 +46,11 @@ #include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H> #include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H> #include <generic/memory/lib/spd/common/rcw_settings.H> +#include <generic/memory/lib/spd/spd_facade.H> #include <generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H> #include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H> #include <generic/memory/lib/spd/spd_checker.H> -#include <generic/memory/lib/utils/c_str.H> +#include <generic/memory/lib/spd/spd_utils.H> #include <lib/utils/conversions.H> #include <generic/memory/lib/utils/find.H> #include <lib/eff_config/timing.H> @@ -62,883 +63,39 @@ using fapi2::FAPI2_RC_SUCCESS; namespace mss { - -/// -/// @brief Helper function to retrieves medium and fine timebase values -/// @param[in] i_pDecoder the SPD decoder -/// @param[out] o_mtb the medium timebase (MTB) from SPD -/// @param[out] o_ftb the fine timebase (FTB) from SPD -/// @return FAPI2_RC_SUCCESS iff ok -/// -static fapi2::ReturnCode get_timebases( const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - int64_t& o_mtb, - int64_t& o_ftb ) -{ - // Retrieve timing parameters - const auto l_target = i_pDecoder->iv_target; - - FAPI_TRY( i_pDecoder->medium_timebase(o_mtb), - "%s. Failed medium_timebase()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_timebase(o_ftb), - "%s. Failed fine_timebase()", mss::c_str(l_target) ); - - FAPI_INF("MTB: %d, FTB: %d for %s", o_mtb, o_ftb, mss::c_str(l_target)); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Retrieves SDRAM Minimum Cycle Time (tCKmin) from SPD -/// @param[in] i_pDecoder the SPD decoder -/// @param[out] o_value tCKmin value in ps -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode get_tckmin( const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value ) -{ - int64_t l_timing_ftb = 0; - int64_t l_timing_mtb = 0; - int64_t l_medium_timebase = 0; - int64_t l_fine_timebase = 0; - int64_t l_temp = 0; - - // Retrieve timing parameters - const auto l_target = i_pDecoder->iv_target; - - FAPI_TRY( get_timebases(i_pDecoder, l_medium_timebase, l_fine_timebase), - "%s. Failed get_timebases", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->min_tck(l_timing_mtb), - "%s. Failed min_tck()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_offset_min_tck(l_timing_ftb), - "%s. Failed fine_offset_min_tck()", mss::c_str(l_target) ); - - // Calculate timing value - l_temp = spd::calc_timing_from_timebase(l_timing_mtb, - l_medium_timebase, - l_timing_ftb, - l_fine_timebase); - - // Sanity check - FAPI_ASSERT(l_temp > 0, - fapi2::MSS_INVALID_TIMING_VALUE(). - set_VALUE(l_temp). - set_FUNCTION(GET_TCKMIN). - set_DIMM_TARGET(l_target), - "%s. tCKmin invalid (<= 0) : %d", - mss::c_str(l_target), - l_temp); - - o_value = l_temp; - - FAPI_INF("%s. tCKmin (ps): %d", - mss::c_str(l_target), - o_value ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD -/// @param[in] i_pDecoder SPD decoder -/// @param[out] o_value tCKmax value in ps -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode get_tckmax( const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value ) -{ - int64_t l_timing_ftb = 0; - int64_t l_timing_mtb = 0; - int64_t l_medium_timebase = 0; - int64_t l_fine_timebase = 0; - int64_t l_temp = 0; - - // Retrieve timing parameters - const auto l_target = i_pDecoder->iv_target; - - FAPI_TRY( get_timebases(i_pDecoder, l_medium_timebase, l_fine_timebase), - "%s. Failed get_timebases", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->max_tck(l_timing_mtb), - "%s. Failed max_tck()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_offset_max_tck(l_timing_ftb), - "%s. Failed fine_offset_max_tck()", mss::c_str(l_target) ); - - // Calculate timing value - l_temp = spd::calc_timing_from_timebase(l_timing_mtb, - l_medium_timebase, - l_timing_ftb, - l_fine_timebase); - - // Sanity check - FAPI_ASSERT(l_temp > 0, - fapi2::MSS_INVALID_TIMING_VALUE(). - set_VALUE(l_temp). - set_FUNCTION(GET_TCKMAX). - set_DIMM_TARGET(l_target), - "%s. tCKmax invalid (<= 0) : %d", - mss::c_str(l_target), - l_temp); - - o_value = l_temp; - - FAPI_INF( "%s. tCKmax (ps): %d", - mss::c_str(l_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - namespace spd { -enum factory_byte_extract -{ - // Byte 1 - ENCODING_LEVEL_START = 0, ///< SPD encoding level start bit - ENCODING_LEVEL_LEN = 4, ///< SPD encoding level bit length - - ADDITIONS_LEVEL_START = 4, ///< SPD additions level start bit - ADDITIONS_LEVEL_LEN = 4, ///< SPD additions level bit length - - // Byte 3 - HYBRID_START = 0, ///< SPD hybrid start bit - HYBRID_LEN = 1, ///< SPD hybrid bit length - HYBRID_TYPE_START = 1, ///< SPD hybrid type start bit - HYBRID_TYPE_LEN = 3, ///< SPD hybrid type bit length - BASE_MODULE_START = 4, ///< SPD base module start bit - BASE_MODULE_LEN = 4, ///< SPD base module bit length -}; - -/// -/// @brief Decodes SPD Revision encoding level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value encoding revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (3~0). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_encoding_level(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - constexpr size_t BYTE_INDEX = 1; - constexpr field_t ENCODING_LEVEL{BYTE_INDEX, ENCODING_LEVEL_START, ENCODING_LEVEL_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, ENCODING_LEVEL, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - (l_field_bits != UNDEFINED), - ENCODING_LEVEL.iv_byte, - l_field_bits, - "Failed check on SPD rev encoding level") ); - - // Update output only after check passes - o_value = l_field_bits; - - // Print decoded info - FAPI_INF("%s. Rev - Encoding Level : %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SPD Revision additions level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value additions revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (bits 7~4). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_additions_level(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - constexpr size_t BYTE_INDEX = 1; - constexpr field_t ADDITIONS_LEVEL{BYTE_INDEX, ADDITIONS_LEVEL_START, ADDITIONS_LEVEL_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, ADDITIONS_LEVEL, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - (l_field_bits != UNDEFINED), - ADDITIONS_LEVEL.iv_byte, - l_field_bits, - "Failed check on SPD rev encoding level") ); - - // Update output only after check passes - o_value = l_field_bits; - - // Print decoded info - FAPI_INF("%s. Rev - Additions Level : %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes hybrid type (whether or not the DIMM is a hybrid) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value hybrid -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode hybrid(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - // ========================================================= - // Byte 3 maps - // Item JC-45-2220.01x - // Page 17 - // DDR4 SPD Document Release 3 - // Byte 3 (0x003): Key Byte / Module Type - Hybrid - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MAP = - { - //{key byte, dimm type} - {0, fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID}, - {1, fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID}, - // All others reserved or not supported - }; - - constexpr size_t BYTE_INDEX = 3; - constexpr field_t HYBRID{BYTE_INDEX, HYBRID_START, HYBRID_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, HYBRID, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - const bool l_is_val_found = find_value_from_key(HYBRID_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - HYBRID.iv_byte, - l_field_bits, - "Failed check on Hybrid") ); - - FAPI_INF("%s. Hybrid Media: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes hybrid type (hybrid DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value hybrid module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 6~4) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode hybrid_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - // ========================================================= - // Byte 3 maps - // Item JC-45-2220.01x - // Page 17 - // DDR4 SPD Document Release 3 - // Byte 3 (0x003): Key Byte / Module Type - Hybrid - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_TYPE_MAP = - { - //{key byte, dimm type} - {0, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE}, - {1, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM}, - // All others reserved or not supported - }; - - constexpr size_t BYTE_INDEX = 3; - constexpr field_t HYBRID_TYPE{BYTE_INDEX, HYBRID_TYPE_START, HYBRID_TYPE_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, HYBRID_TYPE, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - const bool l_is_val_found = find_value_from_key(HYBRID_TYPE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - HYBRID_TYPE.iv_byte, - l_field_bits, - "Failed check on Hybrid Memory Type") ); - - FAPI_INF("%s. Hybrid Memory Type: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes base module type (DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value base module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode base_module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - // ========================================================= - // Byte 3 maps - // Item JC-45-2220.01x - // Page 17 - // DDR4 SPD Document Release 3 - // Byte 3 (0x003): Key Byte / Module Type - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > BASE_MODULE_TYPE_MAP = - { - //{key byte, dimm type} - {1, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM}, - {2, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM}, - {4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM}, - // All others reserved or not supported - }; - - constexpr size_t BYTE_INDEX = 3; - constexpr field_t BASE_MODULE{BYTE_INDEX, BASE_MODULE_START, BASE_MODULE_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, BASE_MODULE, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - const bool l_is_val_found = find_value_from_key(BASE_MODULE_TYPE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BASE_MODULE.iv_byte, - l_field_bits, - "Failed check on Base Module Type") ); - - FAPI_INF("%s. Base Module Type: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM Device Type -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value dram device type enumeration -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 2 -/// @note Item JC-45-2220.01x -/// @note Page 16 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode dram_device_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - // ========================================================= - // Byte 2 maps - // Item JC-45-2220.01x - // Page 16 - // DDR4 SPD Document Release 3 - // Byte 2 (0x002): Key Byte / DRAM Device Type - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > DRAM_GEN_MAP = - { - //{key value, dram gen} - {0x0B, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR3}, - {0x0C, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4} - // Other key bytes reserved or not supported - }; - - constexpr size_t BYTE_INDEX = 2; - const uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(DRAM_GEN_MAP, l_raw_byte, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_raw_byte, - "Failed check on SPD dram device type") ); - - // Print decoded info - FAPI_INF("%s Device type : %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes reference raw card -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 130 (Bits 7~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @Note Page 4.1.2.12 - 49 -/// -fapi2::ReturnCode reference_raw_card(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_output) -{ - // Extracting desired bits - constexpr size_t BYTE_INDEX = 130; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_spd_data[BYTE_INDEX]); - - // Byte taken directly, all bits are an encoding value so no fail check - o_output = i_spd_data[BYTE_INDEX]; - - FAPI_INF("%s. Reference raw card: %d", - mss::c_str(i_target), - o_output); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Helper function to set dimm type attribute -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_dimm_type dimm type encoding needed by factory -/// @return FAPI2_RC_SUCCESS if okay -/// -static fapi2::ReturnCode dimm_type_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_dimm_type) -{ - const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) ); - const auto l_dimm_num = index(i_target); - const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target); - - // Get dimm type & set attribute (needed by c_str) - uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( base_module_type(i_target, i_spd_data, o_dimm_type), - "%s. Failed to find base module type", mss::c_str(i_target) ); - FAPI_TRY( eff_dimm_type(l_mcs, &l_dimm_types_mcs[0][0]), - "%s. Failed to invoke DIMM type accessor", mss::c_str(i_target)); - - l_dimm_types_mcs[l_port_num][l_dimm_num] = o_dimm_type; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_TYPE, l_mcs, l_dimm_types_mcs), - "%s. Failed to set ATTR_EFF_DIMM_TYPE", mss::c_str(i_target)); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to set hybrid attribute -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_hybrid dimm type encoding needed by factory -/// @return FAPI2_RC_SUCCESS if okay -/// -static fapi2::ReturnCode hybrid_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_hybrid) -{ - const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) ); - const auto l_dimm_num = index(i_target); - const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target); - - // Get dimm type & set attribute (needed by c_str) - uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( hybrid(i_target, i_spd_data, o_hybrid), - "%s. Failed to find hybrid", mss::c_str(i_target) ); - FAPI_TRY( eff_hybrid(l_mcs, &l_dimm_types_mcs[0][0]), - "%s. Failed to invoke hybrid accessor", mss::c_str(i_target)); - - l_dimm_types_mcs[l_port_num][l_dimm_num] = o_hybrid; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID, l_mcs, l_dimm_types_mcs), - "%s. Failed to set ATTR_EFF_HYBRID", mss::c_str(i_target)); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to set hybrid_type attribute -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_hybrid_type dimm type encoding needed by factory -/// @return FAPI2_RC_SUCCESS if okay -/// -static fapi2::ReturnCode hybrid_type_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_hybrid_type) -{ - const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) ); - const auto l_dimm_num = index(i_target); - const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target); - - // Get dimm type & set attribute (needed by c_str) - uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( hybrid_type(i_target, i_spd_data, o_hybrid_type), - "%s. Failed to find hybrid_memory_type", mss::c_str(i_target) ); - FAPI_TRY( eff_hybrid_memory_type(l_mcs, &l_dimm_types_mcs[0][0]), - "%s. Failed to invoke hybrid_memory_type accessor", mss::c_str(i_target)); - - l_dimm_types_mcs[l_port_num][l_dimm_num] = o_hybrid_type; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, l_mcs, l_dimm_types_mcs), - "%s. Failed to set ATTR_EFF_HYBRID_MEMORY", mss::c_str(i_target)); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to set dram gen attribute -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @return FAPI2_RC_SUCCESS if okay -/// -static fapi2::ReturnCode dram_gen_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data) -{ - const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) ); - const auto l_dimm_num = index(i_target); - const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target); - - // Get dram generation & set attribute (needed by c_str) - uint8_t l_dram_gen = 0; - uint8_t l_dram_gen_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( eff_dram_gen(l_mcs, &l_dram_gen_mcs[0][0]), - "%s. Failed to inboke DRAM gen accesssor", mss::c_str(i_target) ); - FAPI_TRY( dram_device_type(i_target, i_spd_data, l_dram_gen), - "%s. Failed to find base module type", mss::c_str(i_target) ); - - l_dram_gen_mcs[l_port_num][l_dimm_num] = l_dram_gen; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, l_mcs, l_dram_gen_mcs), - "%s. Failed to set ATTR_EFF_DRAM_GEN", mss::c_str(i_target) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for number of master ranks per dimm -/// @param[in] i_target FAPI2 target -/// @param[in] the SPD cache -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note This is done after the SPD cache is configured so that it can reflect the results of the -/// factory and we don't need to worry about SPD versions. This is expressly different than the dram and dimm setters -/// -fapi2::ReturnCode master_ranks_per_dimm_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::shared_ptr<decoder>& i_pDecoder) -{ - const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target); - const auto l_mca = find_target<TARGET_TYPE_MCA>(i_target); - - uint8_t l_decoder_val = 0; - fapi2::buffer<uint8_t> l_ranks_configed; - uint8_t l_attrs_master_ranks_per_dimm[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - uint8_t l_attrs_dimm_ranks_configed[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Get & update MCS attribute - FAPI_TRY( i_pDecoder->num_package_ranks_per_dimm(l_decoder_val), - "%s. Failed num_package_ranks_per_dimm()", mss::c_str(i_target) ); - FAPI_TRY(eff_num_master_ranks_per_dimm(l_mcs, &l_attrs_master_ranks_per_dimm[0][0]), - "%s. Failed eff_num_master_ranks_per_dimm()", mss::c_str(i_target) ); - FAPI_TRY(eff_dimm_ranks_configed(l_mcs, &l_attrs_dimm_ranks_configed[0][0]), - "%s. Failed eff_dimm_ranks_configed()", mss::c_str(i_target) ); - - l_attrs_master_ranks_per_dimm[index(l_mca)][index(i_target)] = l_decoder_val; - - // Set configed ranks. Set the bit representing the master rank configured (0 being left most.) So, - // a 4R DIMM would be 0b11110000 (0xF0). This is used by PRD. - FAPI_TRY( l_ranks_configed.setBit(0, l_decoder_val), - "%s. Failed to setBit", mss::c_str(i_target) ); - - l_attrs_dimm_ranks_configed[index(l_mca)][index(i_target)] = l_ranks_configed; - - FAPI_INF( "%s Num Master Ranks %d, DIMM Ranks Configed 0x%x", - mss::c_str(i_target), - l_attrs_master_ranks_per_dimm[index(l_mca)][index(i_target)], - l_attrs_dimm_ranks_configed[index(l_mca)][index(i_target)] ); - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, l_mcs, l_attrs_master_ranks_per_dimm), - "%s. Failed to set ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM", mss::c_str(i_target) ); - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED, l_mcs, l_attrs_dimm_ranks_configed), - "%s. Failed to set ATTR_EFF_DIMM_RANKS_CONFIGED", mss::c_str(i_target) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to return RDIMM decoder -/// @param[in] i_target dimm target -/// @param[in] i_encoding_rev encoding revision -/// @param[in] i_additions_rev additions revision -/// @param[in] i_raw_card raw card reference revision -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -static fapi2::ReturnCode rdimm_rev_helper(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const uint8_t i_encoding_rev, - const uint8_t i_additions_rev, - const rcw_settings i_raw_card, - const std::vector<uint8_t>& i_spd_data, - std::shared_ptr<decoder>& o_fact_obj) -{ - // This needs to be updated for added revisions - constexpr uint64_t HIGHEST_ENCODING_LEVEL = 1; - constexpr uint64_t HIGHEST_ADDITIONS_LEVEL = 1; - - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - std::shared_ptr<dimm_module_decoder> l_module_decoder; - - // SPD Revision format #.# - // 1st # = encoding level - // 2nd # = additions level - switch(i_encoding_rev) - { - // Skipping case 0 since we shouldn't be using pre-production revisions - case 1: - switch(i_additions_rev) - { - // Rev 1.0 - case 0: - // Life starts out at base revision level - FAPI_INF( "%s. Creating decoder for RDIMM SPD revision 1.0", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::rdimm::decoder_v1_0>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_0>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - case 1: - // Rev 1.1 - // Changes to both the general section & rdimm section occured - FAPI_INF( "%s. Creating decoder for RDIMM SPD revision 1.1", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::rdimm::decoder_v1_1>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - default: - // For additions level retrieved from SPD higher than highest decoded revision level, - // we default to be highest decoded additions level because they are backward compatable. - // This will need to be updated for every new additions level that is decoded. - FAPI_INF( "%s. Unable to create decoder for retrieved SPD RDIMM revision %d.%d", - mss::c_str(i_target), i_encoding_rev, i_additions_rev ); - - FAPI_INF("%s. Falling back to highest supported, backward-comptable decoder, " - "for SPD RDIMM revision %d.%d", - mss::c_str(i_target), HIGHEST_ENCODING_LEVEL, HIGHEST_ADDITIONS_LEVEL ); - - l_module_decoder = std::make_shared<ddr4::rdimm::decoder_v1_1>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - }//end additions - - break; - - default: - // For encodings level retrieved from SPD higher than highest decoded revision level, - // we error out because encoding level changes are NOT backward comptable. - // Current this means Rev 2.0+ is no supported - FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, - fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, - i_encoding_rev, - i_additions_rev, - "Encoding Level unsupported!"), - "%s. Invalid encoding level received: %d", - mss::c_str(i_target), i_encoding_rev); - - break; - }// end encodings - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to return LRDIMM decoder -/// @param[in] i_target dimm target -/// @param[in] i_encoding_rev encoding revision -/// @param[in] i_additions_rev additions revision -/// @param[in] i_raw_card raw card reference revision -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -static fapi2::ReturnCode lrdimm_rev_helper(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const uint8_t i_encoding_rev, - const uint8_t i_additions_rev, - const rcw_settings i_raw_card, - const std::vector<uint8_t>& i_spd_data, - std::shared_ptr<decoder>& o_fact_obj) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - std::shared_ptr<dimm_module_decoder> l_module_decoder; - - // This needs to be updated for added revisions - constexpr uint64_t HIGHEST_ENCODING_LEVEL = 2; - constexpr uint64_t HIGHEST_ADDITIONS_LEVEL = 1; - - // SPD Revision format #.# - // 1st # = encoding level - // 2nd # = additions level - switch(i_encoding_rev) - { - // Skipping case 0 since we shouldn't be using pre-production revisions - case 1: - switch(i_additions_rev) - { - // Rev 1.0 - case 0: - // Life starts out at base revision level - FAPI_INF( "%s. Creating decoder for LRDIMM SPD revision 1.0", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::lrdimm::decoder_v1_0>(i_target, i_spd_data); - o_fact_obj = std::make_shared<decoder>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - case 1: - // Rev 1.1 - // Changes to both the general section & lrdimm section occured - FAPI_INF( "%s. Creating decoder for LRDIMM SPD revision 1.1", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::lrdimm::decoder_v1_1>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - case 2: - // Rev 1.2 - // Changes lrdimm section occured - // General section remained the same - FAPI_INF( "%s. Creating decoder for LRDIMM SPD revision 1.2", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::lrdimm::decoder_v1_2>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - default: - // For additions level retrieved from SPD higher than highest decoded revision level, - // we default to be highest decoded additions level because they are backward compatable. - // This will need to be updated for every new additions level that is decoded. - FAPI_INF( "%s. Unable to create decoder for retrieved SPD LRDIMM revision %d.%d", - mss::c_str(i_target), i_encoding_rev, i_additions_rev ); - - FAPI_INF("%s. Falling back to highest supported, backward-comptable decoder, " - "for SPD LRDIMM revision %d.%d", - mss::c_str(i_target), HIGHEST_ENCODING_LEVEL, HIGHEST_ADDITIONS_LEVEL ); - - l_module_decoder = std::make_shared<ddr4::lrdimm::decoder_v1_2>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - }//end additions - - break; - - default: - // For encodings level retrieved from SPD higher than highest decoded revision level, - // we error out because encoding level changes are NOT backward comptable. - // Currently this means Rev 2.0+ is not supported - FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, - fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM, - i_encoding_rev, - i_additions_rev, - "Encoding Level unsupported!"), - "%s. Invalid encoding level received: %d", - mss::c_str(i_target), i_encoding_rev); - break; - }// end encodings - -fapi_try_exit: - return fapi2::current_err; -} - /// /// @brief Retrieve current raw card settings /// based on dimm type and raw card reference rev /// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data +/// @param[in] i_data SPD data /// @param[out] o_raw_card raw card settings /// @return FAPI2_RC_SUCCESS if okay /// fapi2::ReturnCode raw_card_factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, + const facade& i_data, rcw_settings& o_raw_card) { + // Lets find out what raw card we are and grab the right + // raw card settings uint8_t l_dimm_type = 0; uint8_t l_hybrid = 0; uint8_t l_hybrid_type = 0; uint8_t l_ref_raw_card_rev = 0; - // Lets find out what raw card we are and grab the right - // raw card settings - FAPI_TRY( mss::eff_dimm_type(i_target, l_dimm_type) ); - FAPI_TRY( mss::eff_hybrid(i_target, l_hybrid) ); - FAPI_TRY( mss::eff_hybrid_memory_type(i_target, l_hybrid_type) ); - FAPI_TRY( reference_raw_card(i_target, i_spd_data, l_ref_raw_card_rev) ); + FAPI_TRY(i_data.base_module(l_dimm_type) ); + FAPI_TRY(i_data.hybrid(l_hybrid)); + FAPI_TRY(i_data.hybrid_media(l_hybrid_type)); + FAPI_TRY(i_data.reference_raw_card(l_ref_raw_card_rev)); - FAPI_INF( "Retrieved dimm_type: %d, raw card reference: 0x%lx from SPD", - l_dimm_type, l_ref_raw_card_rev); + FAPI_INF("Retrieved dimm_type: %d, raw card reference: 0x%lx from SPD for %s", + l_dimm_type, l_ref_raw_card_rev, spd::c_str(i_target)); switch(l_dimm_type) { - case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM: + case RDIMM: // TODO:RTC178807 - Update how NVDIMMs are handled once more are up and running in the lab // NVDIMM is currently considered differently than all other rdimm raw cards, due to settings differences @@ -947,20 +104,20 @@ fapi2::ReturnCode raw_card_factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_targ { l_ref_raw_card_rev = mss::rdimm::raw_card_rev::NVDIMM; FAPI_INF("%s is an NVDIMM, overwrote l_ref_raw_card_rev to be 0x%02x", - mss::c_str(i_target), + mss::spd::c_str(i_target), l_ref_raw_card_rev); } FAPI_TRY( find_raw_card( i_target, - fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, + RDIMM, l_ref_raw_card_rev, mss::rdimm::RAW_CARDS, o_raw_card) ); break; - case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM: + case LRDIMM: FAPI_TRY( find_raw_card( i_target, - fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM, + LRDIMM, l_ref_raw_card_rev, mss::lrdimm::RAW_CARDS, o_raw_card) ); @@ -972,7 +129,7 @@ fapi2::ReturnCode raw_card_factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_targ .set_DIMM_TYPE(l_dimm_type) .set_DIMM_TARGET(i_target), "Recieved invalid dimm type: %d for %s", - l_dimm_type, mss::c_str(i_target) ); + l_dimm_type, mss::spd::c_str(i_target) ); break; } @@ -981,100 +138,6 @@ fapi_try_exit: } /// -/// @brief Object factory to select correct decoder -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -fapi2::ReturnCode factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - std::shared_ptr<decoder>& o_fact_obj) -{ - if( i_spd_data.empty() ) - { - // This won't work with no data - FAPI_ERR( "%s. SPD vector of data is empty! Factory requires valid SPD data.", mss::c_str(i_target) ); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - } - - uint8_t l_dimm_type = 0; - uint8_t l_hybrid = 0; - uint8_t l_hybrid_type = 0; - uint8_t l_encoding_rev = 0; - uint8_t l_additions_rev = 0; - rcw_settings l_raw_card; - - // Attribute setting needed by mss::c_str() which is used in - // the SPD decoder for debugging help - FAPI_TRY( dimm_type_setter(i_target, i_spd_data, l_dimm_type), - "%s. Failed to set DIMM type", mss::c_str(i_target) ); - FAPI_TRY( hybrid_setter(i_target, i_spd_data, l_hybrid), - "%s. Failed to set hybrid", mss::c_str(i_target) ); - FAPI_TRY( hybrid_type_setter(i_target, i_spd_data, l_hybrid_type), - "%s. Failed to set hybrid_type", mss::c_str(i_target) ); - FAPI_TRY( dram_gen_setter(i_target, i_spd_data), - "%s. Failed to set DRAM generation", mss::c_str(i_target) ); - FAPI_TRY( raw_card_factory(i_target, i_spd_data, l_raw_card), - "%s. Failed raw_card_factory()", mss::c_str(i_target) ); - - // Get revision levels to figure out what SPD version we are - FAPI_TRY( rev_encoding_level(i_target, i_spd_data, l_encoding_rev), - "%s. Failed to decode encoding level", mss::c_str(i_target) ); - FAPI_TRY( rev_additions_level(i_target, i_spd_data, l_additions_rev), - "%s. Failed to decode additons level", mss::c_str(i_target) ); - - // 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: - FAPI_TRY( rdimm_rev_helper(i_target, - l_encoding_rev, - l_additions_rev, - l_raw_card, - i_spd_data, - o_fact_obj), - "%s. Failed to decode SPD revision for RDIMM, " - "encoding rev: %d, additions rev: %d", - mss::c_str(i_target), l_encoding_rev, l_additions_rev ); - break; - - // Each dimm type rev is independent - case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM: - FAPI_TRY( lrdimm_rev_helper(i_target, - l_encoding_rev, - l_additions_rev, - l_raw_card, - i_spd_data, - o_fact_obj), - "%s. Failed to decode SPD revision for LRDIMM, " - "encoding rev: %d, additions rev: %d", - mss::c_str(i_target), l_encoding_rev, l_additions_rev); - break; - - default: - FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, - l_dimm_type, - l_encoding_rev, - l_additions_rev, - "DIMM Type unsupported!") ); - break; - - } // end dimm type - - FAPI_INF( "%s: Decoder created for DIMM type: %d, SPD revision %d.%d", - mss::c_str(i_target), - l_dimm_type, - l_encoding_rev, - l_additions_rev ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// /// @brief Wrapper function for finding the raw card -- helper for testing /// @param[in] i_target the dimm target /// @param[in] i_dimm_type @@ -1100,7 +163,7 @@ fapi2::ReturnCode find_raw_card_helper( const fapi2::Target<TARGET_TYPE_DIMM>& i FAPI_INF("Unsupported raw cards %s allowed for %s", i_mrw_supported_rc ? "are" : "are NOT", - mss::c_str(i_target)); + mss::spd::c_str(i_target)); FAPI_ASSERT(find_value_from_key( i_map, i_ref_raw_card_rev, o_raw_card), fapi2::MSS_INVALID_RAW_CARD(fapi2::FAPI2_ERRL_SEV_RECOVERED, l_rc) @@ -1109,9 +172,9 @@ fapi2::ReturnCode find_raw_card_helper( const fapi2::Target<TARGET_TYPE_DIMM>& i .set_DIMM_TARGET(i_target) .set_MCA_TARGET(l_mca), "Invalid reference raw card received for %s: %d for %s", - (i_dimm_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? "RDIMM" : "LRDIMM", + (i_dimm_type == RDIMM) ? "RDIMM" : "LRDIMM", i_ref_raw_card_rev, - mss::c_str(i_target)); + mss::spd::c_str(i_target)); return fapi2::FAPI2_RC_SUCCESS; @@ -1124,7 +187,7 @@ fapi_try_exit: { fapi2::logError(l_rc, fapi2::FAPI2_ERRL_SEV_RECOVERED); l_rc = fapi2::FAPI2_RC_SUCCESS; - o_raw_card = (i_dimm_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? rdimm_rc_default : lrdimm_rc_default; + o_raw_card = (i_dimm_type == RDIMM) ? rdimm_rc_default : lrdimm_rc_default; } return l_rc; @@ -1151,41 +214,7 @@ fapi2::ReturnCode find_raw_card( const fapi2::Target<TARGET_TYPE_DIMM>& i_target FAPI_TRY( mrw_allow_unsupported_rcw(l_allow_unsupported_rcw) ); FAPI_TRY( find_raw_card_helper(i_target, i_dimm_type, i_ref_raw_card_rev, l_allow_unsupported_rcw, i_map, o_raw_card), - "Failed find_raw_card_helper for %s", mss::c_str(i_target) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Creates factory object & SPD data caches -/// @param[in] i_target the dimm target -/// @param[out] o_factory_caches vector of factory objects -/// @param[in] i_pDecoder custom decoder to populate cache (nullptr default) -/// @return FAPI2_RC_SUCCESS if okay -/// @note This specialization is suited for creating a cache with custom -/// SPD data (e.g. testing custom SPD). -/// -template<> -fapi2::ReturnCode populate_decoder_caches( const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - std::vector< std::shared_ptr<decoder> >& o_factory_caches, - const std::shared_ptr<decoder>& i_pDecoder) -{ - if(i_pDecoder == nullptr) - { - // This won't work w/a null parameter - FAPI_ERR("%s. Received decoder is NULL!", mss::c_str(i_target) ); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - } - - // Custom decoder provided (usually done for testing) - // Populate custom spd caches maps one dimm at a time - o_factory_caches.push_back( i_pDecoder ); - - // Populate some of the DIMM attributes early. This allows the following code to make - // decisions based on DIMM information. Expressly done after the factory has decided on the SPD version - FAPI_TRY( master_ranks_per_dimm_setter(i_target, i_pDecoder), - "%s. Failed master_ranks_per_dimm_setter()", mss::c_str(i_target) ); + "Failed find_raw_card_helper for %s", mss::spd::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H index ab9872ca6..9d8786452 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H @@ -45,8 +45,8 @@ #include <fapi2_spd_access.H> // mss lib -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <generic/memory/lib/utils/find.H> +#include <generic/memory/lib/spd/spd_facade.H> +#include <generic/memory/lib/spd/common/rcw_settings.H> namespace mss { @@ -54,93 +54,6 @@ namespace spd { /// -/// @brief Decodes SPD Revision encoding level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value encoding revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (3~0). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_encoding_level(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); -/// -/// @brief Decodes SPD Revision additions level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD blob -/// @param[out] o_value additions revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (bits 7~4). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_additions_level(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); - -/// -/// @brief Decodes hybrid type (whether or not the DIMM is a hybrid) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value hybrid -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode hybrid(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); - -/// -/// @brief Decodes hybrid type (hybrid DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value hybrid module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 6~4) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode hybrid_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); - -/// -/// @brief Decodes base module type (DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value base module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode base_module_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); -/// -/// @brief Decodes DRAM Device Type -/// @param[in] i_target dimm target -/// @param[out] o_value dram device type enumeration -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 2 -/// @note Item JC-45-2220.01x -/// @note Page 16 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode dram_device_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); - -/// /// @brief Wrapper function for finding the raw card -- helper for testing /// @param[in] i_target the dimm target /// @param[in] i_dimm_type @@ -179,126 +92,18 @@ fapi2::ReturnCode find_raw_card( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i rcw_settings& o_raw_card); /// -/// @brief Decodes reference raw card -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 130 (Bits 7~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @Note Page 4.1.2.12 - 49 -/// -fapi2::ReturnCode reference_raw_card(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_output); - -/// /// @brief Retrieve current raw card settings /// based on dimm type and raw card reference rev /// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data +/// @param[in] i_data SPD data /// @param[out] o_raw_card raw card settings /// @return FAPI2_RC_SUCCESS if okay /// fapi2::ReturnCode raw_card_factory(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, + const facade& i_data, rcw_settings& o_raw_card); -/// -/// @brief Object factory to select correct decoder -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -fapi2::ReturnCode factory(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - std::shared_ptr<decoder>& o_fact_obj); - - -/// -/// @brief Determines & sets effective config for number of master ranks per dimm -/// @param[in] i_target DIMM fapi2::Target -/// @param[in] i_pDecoder shared_ptr to SPD decoder -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note This is done after the SPD cache is configured so that it can reflect the results of the -/// factory and we don't need to worry about SPD versions. This is expressly different than the dram and dimm setters -/// -fapi2::ReturnCode master_ranks_per_dimm_setter(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::shared_ptr<decoder>& i_pDecoder); - -/// -/// @brief Creates factory object & SPD data caches -/// @tparam T fapi2::TargetType, MCA, MCS, MCBIST, PROC_CHIP are possible TargetTypes -/// @param[in] i_target the fapi2 target to find DIMMs on -/// @param[out] o_factory_caches vector of factory objects -/// @param[in] i_pDecoder optional input decoder to insert custom decoder (nullptr default) -/// @return FAPI2_RC_SUCCESS if okay -/// -template<fapi2::TargetType T> -fapi2::ReturnCode populate_decoder_caches(const fapi2::Target<T>& i_target, - std::vector< std::shared_ptr<decoder> >& o_factory_caches, - const std::shared_ptr<decoder>& i_pDecoder = nullptr) -{ - // Input decoder for this version of populating cache would get overriden - // so I don't bother with it in this specialization - std::shared_ptr<decoder> l_pDecoder; - - for( const auto& l_dimm : find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) ) - { - size_t l_size = 0; - FAPI_TRY( fapi2::getSPD(l_dimm, nullptr, l_size), - "%s. Failed to retrieve SPD blob size", mss::c_str(i_target) ); - - { - // "Container" for SPD data - std::vector<uint8_t> l_spd(l_size); - - // Retrieve SPD data - FAPI_TRY( fapi2::getSPD(l_dimm, l_spd.data(), l_size), - "%s. Failed to retrieve SPD data", mss::c_str(i_target) ); - - // Retrieve factory object instance & populate spd data for that instance - FAPI_TRY( factory(l_dimm, l_spd, l_pDecoder), - "%s. Failed SPD factory, could not instantiate decoder object", mss::c_str(i_target) ); - - // Populate spd caches - o_factory_caches.push_back( l_pDecoder ); - } - - // Populate some of the DIMM attributes early. This allows the following code to make - // decisions based on DIMM information. Expressly done after the factory has decided on the SPD version - FAPI_TRY( master_ranks_per_dimm_setter(l_dimm, l_pDecoder), - "%s. Failed master_ranks_per_dimm_setter()", mss::c_str(i_target) ); - - }// end dimm - -fapi_try_exit: - return fapi2::current_err; -} - }// spd - -/// -/// @brief Retrieves SDRAM Minimum Cycle Time (tCKmin) from SPD -/// @param[in] i_pDecoder the SPD decoder -/// @param[out] o_value tCKmin value in ps -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode get_tckmin(const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value); - -/// -/// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD -/// @param[in] i_pDecoder SPD decoder -/// @param[out] o_value tCKmax value in ps -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode get_tckmax(const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value); - }// mss #endif //_MSS_SPD_FACTORY_H_ diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/swizzle.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/swizzle.H index 260197a66..57523f5bd 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/swizzle.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/swizzle.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,6 +42,27 @@ namespace mss { /// +/// @brief Endian swapping +/// @tparam T input type +/// @param[in,out] io_input integral input +/// @note https://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c +/// +template < typename T > +void endian_swap(T& io_input) +{ + constexpr size_t MIN_BYTES = 2; + static_assert(sizeof(T) >= MIN_BYTES, "Byte swapping requires at least 2 bytes of data"); + + uint8_t* l_varArray = reinterpret_cast<uint8_t*>(&io_input); + + for(size_t i = 0; i < sizeof(io_input) / 2; i++) + { + const size_t BYTE_SWAP_INDEX = sizeof(io_input) - 1 - i; + std::swap(l_varArray[BYTE_SWAP_INDEX], l_varArray[i]); + } +} + +/// /// @brief Swap two bits in a buffer /// @tparam TB the bit in the buffer to move to SB /// @tparam SB the bit in the buffer to move to TB diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C index 17ebcba7e..57b40397b 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C @@ -34,7 +34,6 @@ // *HWP Consumed by: FSP:HB #include <vector> -#include <mss.H> #include <fapi2.H> #include <p9_mss_bulk_pwr_throttles.H> #include <generic/memory/lib/utils/find.H> diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C index 711eca0ad..c05c51992 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C @@ -43,7 +43,6 @@ // mss lib #include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <lib/spd/spd_factory.H> #include <generic/memory/lib/utils/pos.H> #include <lib/utils/checker.H> #include <generic/memory/lib/utils/find.H> @@ -67,12 +66,8 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS> return fapi2::FAPI2_RC_SUCCESS; } - fapi2::ReturnCode l_rc; - std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches; - - // Caches - FAPI_TRY( mss::spd::populate_decoder_caches(i_target, l_factory_caches), - "Failed populate_decoder_caches for %s", mss::c_str(i_target)); + std::vector< mss::spd::facade > l_spd_facades; + FAPI_TRY( get_spd_decoder_list(i_target, l_spd_facades) ); // Need to check dead load before we get the VPD. // MR and MT VPD depends on DIMM ranks and freaks out if it receives 0 ranks from DIMM 0 and 1 or more ranks for DIMM 1 @@ -93,13 +88,13 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS> "Unable to decode VPD for %s", mss::c_str(i_target) ); } - for( const auto& l_cache : l_factory_caches ) + for( const auto& l_spd : l_spd_facades ) { - const auto l_dimm = l_cache->iv_target; + const auto l_dimm = l_spd.get_dimm_target(); std::shared_ptr<mss::eff_dimm> l_eff_dimm; - FAPI_TRY( mss::eff_dimm::eff_dimm_factory( l_cache, l_eff_dimm), - "Failed eff_dimm_factory for %s", mss::c_str(l_dimm)); + FAPI_TRY( mss::eff_dimm::factory( l_spd, l_eff_dimm), + "Failed factory for %s", mss::c_str(l_dimm)); FAPI_INF("Running eff_config on %s", mss::c_str(l_dimm) ); @@ -225,6 +220,8 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS> "Failed odt_input_buffer for %s", mss::c_str(l_dimm) ); FAPI_TRY( l_eff_dimm->post_package_repair(), "Failed post_package_repair for %s", mss::c_str(l_dimm) ); + FAPI_TRY( l_eff_dimm->soft_post_package_repair(), + "Failed soft_post_package_repair for %s", mss::c_str(l_dimm) ); FAPI_TRY( l_eff_dimm->read_preamble_train(), "Failed read_preamble_train for %s", mss::c_str(l_dimm) ); FAPI_TRY( l_eff_dimm->read_preamble(), diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C index c767e87b7..e01918cd7 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C @@ -45,8 +45,7 @@ #include <fapi2.H> // mss lib -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <lib/spd/spd_factory.H> +#include <generic/memory/lib/spd/spd_facade.H> #include <lib/freq/cas_latency.H> #include <lib/freq/sync.H> #include <lib/workarounds/freq_workarounds.H> @@ -55,6 +54,7 @@ #include <generic/memory/lib/utils/count_dimm.H> #include <generic/memory/lib/utils/index.H> #include <lib/shared/mss_const.H> +#include <lib/eff_config/attr_setters.H> using fapi2::TARGET_TYPE_MCS; using fapi2::TARGET_TYPE_MCA; @@ -79,7 +79,7 @@ extern "C" // So for now, iterate over all the MCBIST. This isn't great as we do this work // twice for every MC. However, attribute access is cheap so this will suffice for // the time being. - const auto& l_mcbist = mss::find_target<TARGET_TYPE_MCBIST>(i_target); + const auto l_mcbist = mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target); std::vector< std::vector<uint64_t> > l_min_dimm_freq(mss::MCS_PER_MC, std::vector<uint64_t> (mss::PORTS_PER_MCS, 0) ); std::vector<uint32_t> l_supported_freqs; @@ -93,6 +93,21 @@ extern "C" return FAPI2_RC_SUCCESS; } + // We will first set pre-eff_config attributes + for( const auto& d : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(l_mcbist)) + { + std::vector<uint8_t> l_raw_spd; + FAPI_TRY(mss::spd::get_raw_data(d, l_raw_spd)); + + { + fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); + mss::spd::facade l_spd_decoder(d, l_raw_spd, l_rc); + + FAPI_TRY(l_rc, "Failed to initialize SPD facade for %s", mss::spd::c_str(d)); + FAPI_TRY(mss::set_pre_init_attrs(d, l_spd_decoder)); + } + } + // Get supported freqs for this MCBIST FAPI_TRY( mss::supported_freqs(l_mcbist, l_supported_freqs) ); @@ -105,15 +120,14 @@ extern "C" for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs) ) { const auto l_mca_index = mss::index(l_mca); - std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches; fapi2::ReturnCode l_rc; // Get cached decoder - FAPI_TRY( mss::spd::populate_decoder_caches(l_mca, l_factory_caches), - "%s. Failed to populate decoder cache", mss::c_str(l_mca) ); + std::vector< mss::spd::facade > l_spd_facades; + FAPI_TRY( get_spd_decoder_list(l_mca, l_spd_facades) ); // Instantiation of class that calculates CL algorithm - mss::cas_latency l_cas_latency( l_mca, l_factory_caches, l_supported_freqs, l_rc ); + mss::cas_latency l_cas_latency( l_mca, l_spd_facades, l_supported_freqs, l_rc ); FAPI_TRY( l_rc, "%s. Failed to initialize cas_latency ctor", mss::c_str(l_mca) ); diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C index d8bf63b9c..487824835 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C @@ -47,7 +47,6 @@ #include <generic/memory/lib/utils/index.H> #include <generic/memory/lib/utils/find.H> #include <lib/utils/conversions.H> -#include <lib/power_thermal/throttle.H> #include <lib/mss_attribute_accessors.H> #include <generic/memory/lib/utils/count_dimm.H> #include <lib/shared/mss_const.H> diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C index 04a6c0b34..0c8f9d98a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,8 +42,7 @@ #include <fapi2.H> // mss lib -#include <lib/spd/spd_factory.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> +#include <generic/memory/lib/spd/spd_facade.H> #include <lib/eff_config/attr_setters.H> #include <generic/memory/lib/utils/c_str.H> #include <generic/memory/lib/utils/pos.H> @@ -72,19 +71,19 @@ extern "C" FAPI_INF("Populating decoder cache for %s", mss::c_str(l_mcs)); //Factory cache is per MCS - std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches; - FAPI_TRY( mss::spd::populate_decoder_caches(l_mcs, l_factory_caches), - "Failed to populate decoder cache for %s", l_mcs); + std::vector< mss::spd::facade > l_spd_facades; + FAPI_TRY( get_spd_decoder_list(l_mcs, l_spd_facades) ); // Get dimms for each MCS - for ( const auto& l_cache : l_factory_caches ) + for ( const auto& l_cache : l_spd_facades ) { + const auto l_dimm = l_cache.get_dimm_target(); uint8_t l_dimm_nominal = 0; uint8_t l_dimm_endurant = 0; // Read nominal and endurant bits from SPD, 0 = 1.2V is not operable and endurant, 1 = 1.2 is valid - FAPI_TRY( l_cache->operable_nominal_voltage(l_dimm_nominal) ); - FAPI_TRY( l_cache->endurant_nominal_voltage(l_dimm_endurant) ); + FAPI_TRY( l_cache.operable_nominal_voltage(l_dimm_nominal) ); + FAPI_TRY( l_cache.endurant_nominal_voltage(l_dimm_endurant) ); //Check to make sure 1.2 V is both operable and endurant, fail if it is not FAPI_ASSERT ( (l_dimm_nominal == mss::spd::OPERABLE) && (l_dimm_endurant == mss::spd::ENDURANT), @@ -93,10 +92,10 @@ extern "C" set_ACTUAL_ENDURANT(l_dimm_endurant). set_EXPECTED_OPERABLE(mss::spd::OPERABLE). set_EXPECTED_ENDURANT(mss::spd::ENDURANT). - set_DIMM_TARGET(l_cache->iv_target), + set_DIMM_TARGET(l_dimm), "%s: DIMM is not operable (%d) expected (%d)" " and/or endurant (%d) expected (%d) at 1.2V", - mss::c_str(l_cache->iv_target), + mss::c_str(l_dimm), l_dimm_nominal, mss::spd::OPERABLE, l_dimm_endurant, diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_general_errors.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_general_errors.xml index 2e57876e7..4f63f6bc1 100644 --- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_general_errors.xml +++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_general_errors.xml @@ -71,30 +71,6 @@ </hwpError> <hwpError> - <rc>RC_MSS_INVALID_DIMM_TYPE</rc> - <description> - An invalid/unsupported DIMM type was received. This is possibly due - to SPD decoding errors or incorrect setting of ATTR_EFF_DIMM_TYPE attribute. - </description> - <ffdc>DIMM_TYPE</ffdc> - <callout> - <procedure>MEMORY_PLUGGING_ERROR</procedure> - <priority>HIGH</priority> - </callout> - <callout> - <target>DIMM_TARGET</target> - <priority>MEDIUM</priority> - </callout> - <deconfigure> - <target>DIMM_TARGET</target> - </deconfigure> - <callout> - <procedure>CODE</procedure> - <priority>LOW</priority> - </callout> - </hwpError> - - <hwpError> <rc>RC_MSS_INVALID_RTT_WR_ENCODING</rc> <description> An invalid/unsupported RTT_WR encoding was received diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_spd_decode.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_spd_decode.xml index a67cfa73f..e37308594 100644 --- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_spd_decode.xml +++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_spd_decode.xml @@ -37,6 +37,66 @@ <hwpErrors> <hwpError> + <rc>RC_MSS_INVALID_SPD_RESERVED_BITS</rc> + <description> + Invalid SPD reserved bits received. + This could be code problem (decoding) or bad SPD. + </description> + <ffdc>FUNCTION_CODE</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>HIGH</priority> + </callout> + <deconfigure> + <target>TARGET</target> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_INVALID_DIMM_SPEED</rc> + <description> + Invalid DIMM speed received. Possibly a programming error. + </description> + <ffdc>DIMM_SPEED</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>HIGH</priority> + </callout> + <deconfigure> + <target>TARGET</target> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_INVALID_DB_MDQ_DRIVE_STRENGTH</rc> + <description> + Bad SPD data for bytes 145 - 147. + Reserved settings for data buffer MDQ drive strength received. + This could be code problem (decoding) or bad SPD. + </description> + <ffdc>DATA_RATE</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>HIGH</priority> + </callout> + <deconfigure> + <target>TARGET</target> + </deconfigure> + </hwpError> + + <hwpError> <rc>RC_MSS_BAD_SPD</rc> <description> Bad SPD data received. @@ -59,15 +119,62 @@ </hwpError> <hwpError> - <rc>RC_MSS_INVALID_DIMM_REV_COMBO</rc> + <rc>RC_MSS_INVALID_DRAM_GEN</rc> + <description> + Received a DRAM gen unsupported by the SPD decoder factory + </description> + <ffdc>DRAM_GEN</ffdc> + <ffdc>FUNCTION</ffdc> + <callout> + <procedure>MEMORY_PLUGGING_ERROR</procedure> + <priority>HIGH</priority> + </callout> + <callout> + <target>DIMM_TARGET</target> + <priority>LOW</priority> + </callout> + <deconfigure> + <target>DIMM_TARGET</target> + </deconfigure> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_MSS_INVALID_HYBRID_MODULE</rc> <description> - Received a dimm type (e.g. RDIMM, LRDIMM) and SPD revision - (e.g. 1.0, 1.1) combination unsupported by the spd_decoder - object "factory" + Received an invalid or unsupported hybrid media (SPD byte 3, bits [6:4]) + for a specified hybrid modue (SPD byte 3, bit [7]) + </description> + <ffdc>HYBRID</ffdc> + <ffdc>HYBRID_MEDIA</ffdc> + <ffdc>FUNCTION</ffdc> + <callout> + <procedure>MEMORY_PLUGGING_ERROR</procedure> + <priority>HIGH</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>LOW</priority> + </callout> + <deconfigure> + <target>TARGET</target> + </deconfigure> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_MSS_INVALID_DIMM_TYPE</rc> + <description> + Received a DIMM type unsupported by the SPD decoder factory </description> <ffdc>DIMM_TYPE</ffdc> - <ffdc>ENCODING_REV</ffdc> - <ffdc>ADDITIONS_REV</ffdc> + <ffdc>FUNCTION</ffdc> <callout> <procedure>MEMORY_PLUGGING_ERROR</procedure> <priority>HIGH</priority> @@ -108,4 +215,90 @@ <target>MCA_TARGET</target> </deconfigure> </hwpError> + + <hwpError> + <rc>RC_MSS_FAILED_SPD_REVISION_FALLBACK</rc> + <description> + Unable to fall back SPD decoder to the highest decoded + revision. Most likely a programming error. + </description> + <ffdc>FAILED_REVISION</ffdc> + <ffdc>FUNCTION_CODE</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <target>TARGET</target> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_SPD_TIMING_FAIL</rc> + <description> + Timing SPD parameter failed to meet JEDEC SPD timing + bounds. FUNCTION_CODE ffdc field encodes which timing param. + </description> + <ffdc>FAILED_REVISION</ffdc> + <ffdc>FUNCTION_CODE</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <target>TARGET</target> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_INVALID_SPD_PARAMETER_RECEIVED</rc> + <description> + Unable to fall back SPD decoder to the highest decoded + revision. Most likely a programming error. + </description> + <ffdc>SPD_PARAM</ffdc> + <ffdc>FUNCTION_CODE</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <target>TARGET</target> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_SPD_REV_ENCODING_LEVEL_NOT_SUPPORTED</rc> + <description> + SPD revision on byte 1 (bits 7~4) has a unsupported encoding level + that is greater than the largest decoded SPD decoder. There is + no backward compatible revision to fallback to. This could be + bad SPD or a programming error. + </description> + <ffdc>ENCODING_LEVEL</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <target>TARGET</target> + </deconfigure> + </hwpError> + </hwpErrors> diff --git a/src/import/generic/memory/lib/data_engine/pre_data_init.H b/src/import/generic/memory/lib/data_engine/pre_data_init.H index 1f20e6b75..aa061a530 100644 --- a/src/import/generic/memory/lib/data_engine/pre_data_init.H +++ b/src/import/generic/memory/lib/data_engine/pre_data_init.H @@ -22,3 +22,499 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file pre_data_init.H +/// @brief Class to set preliminary eff_config attributes +/// +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: CI + +#ifndef _MSS_PRE_DATA_INIT_H_ +#define _MSS_PRE_DATA_INIT_H_ + +#include <cstring> +#include <fapi2.H> +#include <generic/memory/lib/spd/spd_facade.H> +#include <generic/memory/lib/utils/find.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> + +namespace mss +{ + +/// +/// @brief enum list of preliminary data fields +/// +enum pre_data_init_fields +{ + DIMM_TYPE, + DRAM_GEN, + HYBRID, + HYBRID_MEDIA, + MRANKS, + DIMM_RANKS_CNFG, +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @tparam T proc_type (e.g. Nimbus, Axone, etc.) +/// @tparam TT pre_data_init_fields (e.g. DIMM_TYPE, MRANK, etc.) +/// +template< proc_type T, pre_data_init_fields TT > +class preDataInitTraits; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, DIMM_TYPE specialization +/// +template<> +class preDataInitTraits<NIMBUS, DIMM_TYPE> +{ + public: + using attr_type = fapi2::ATTR_EFF_DIMM_TYPE_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_DIMM_TYPE_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DIMM_TYPE, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_TYPE, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, DRAM_GEN specialization +/// +template<> +class preDataInitTraits<NIMBUS, DRAM_GEN> +{ + public: + using attr_type = fapi2::ATTR_EFF_DRAM_GEN_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_DRAM_GEN_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DRAM_GEN, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, HYBRID specialization +/// +template<> +class preDataInitTraits<NIMBUS, HYBRID> +{ + public: + using attr_type = fapi2::ATTR_EFF_HYBRID_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_HYBRID_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_HYBRID, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, HYBRID_MEDIA specialization +/// +template<> +class preDataInitTraits<NIMBUS, HYBRID_MEDIA> +{ + public: + using attr_type = fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, MRANKS specialization +/// +template<> +class preDataInitTraits<NIMBUS, MRANKS> +{ + public: + using attr_type = fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, DIMM_RANKS_CNFG specialization +/// +template<> +class preDataInitTraits<NIMBUS, DIMM_RANKS_CNFG> +{ + public: + using attr_type = fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Helper function for attribute setting +/// @tparam T processor type (e.g. NIMBUS, AXONE, etc.) +/// defaulted to NIMBUS +/// @tparam X size of 1st array index +/// @tparam Y size of 2nd array index +/// @tparam TT FAPI2 target type +/// @tparam IT Input/outpu data type +/// @param[in] i_target the MCS target +/// @param[in] i_setting array to set +/// @param[out] o_data attribute data structure to set +/// @warning This is Nimbus specific +/// +template < size_t X, size_t Y, typename IT > +void data_setter( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const IT i_setting, + IT (&o_data)[X][Y]) +{ + const size_t l_port_index = mss::index( find_target<fapi2::TARGET_TYPE_MCA>(i_target) ); + const size_t l_dimm_index = mss::index(i_target); + + o_data[l_port_index][l_dimm_index] = i_setting; +} + +/// +/// @brief Mapping boilerplate check +/// @tparam T FAPI2 target type +/// @tparam IT map key type +/// @tparam OT map value type +/// @param[in] i_map SPD to attribute data mapping +/// @param[in] i_ffdc_code FFDC function code +/// @param[in] i_key Key to query map +/// @param[out] o_output value from key +/// +template< fapi2::TargetType T, typename IT, typename OT > +fapi2::ReturnCode lookup_table_check(const fapi2::Target<T>& i_target, + const std::vector<std::pair<IT, OT>>& i_map, + const generic_ffdc_codes i_ffdc_code, + const IT i_key, + OT& o_output) +{ + const bool l_is_val_found = mss::find_value_from_key(i_map, i_key, o_output); + + FAPI_ASSERT( l_is_val_found, + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(i_key) + .set_DATA(o_output) + .set_FUNCTION(i_ffdc_code) + .set_TARGET(i_target), + "Failed to find a mapped value for %d on %s", + i_key, + spd::c_str(i_target) ); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Sets preliminary data fields +/// @tparam P processor type (e.g. NIMBUS, AXONE, etc.) +/// @tparam F pre_data_init_fields +/// @tparam T FAPI2 target type +/// @tparam IT Input data type +/// @tparam TT defaulted to preDataInitTraits<T> +/// @param[in] i_setting value we want to set attr with +/// @return FAPI2_RC_SUCCESS iff okay +/// +template< proc_type P, + pre_data_init_fields F, + fapi2::TargetType T, + typename IT, + typename TT = preDataInitTraits<P, F> + > +fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target, const IT i_setting) +{ + const auto l_target = mss::find_target<TT::TARGET_TYPE>(i_target); + typename TT::attr_type l_attr_list = {}; + IT l_mapping_value = i_setting; + + FAPI_TRY( TT::get_attr(l_target, l_attr_list) ); + + // Indexing isn't very general + data_setter(i_target, l_mapping_value, l_attr_list); + + FAPI_TRY( TT::set_attr(l_target, l_attr_list) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Data structure to set pre-effective config data +/// @class pre_data_engine +/// @tparam T supported processor type (e.g. Nimbus, Axone, etc.) +/// +template< proc_type T > +class pre_data_engine; + +/// +/// @brief Data structure to set pre-effective config data +/// @class pre_data_engine +/// @note NIMBUS specialization +/// +template< > +class pre_data_engine< NIMBUS > +{ + private: + + fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_dimm; + uint8_t iv_master_ranks; + spd::facade iv_spd_data; + size_t iv_port_index; + size_t iv_dimm_index; + + public: + + static const std::vector<std::pair<uint8_t, uint8_t> > NUM_PACKAGE_RANKS_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > BASE_MODULE_TYPE_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > DRAM_GEN_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MEMORY_TYPE_MAP; + + /// + /// @brief ctor + /// @param[in] i_target the DIMM target + /// @param[in] i_spd_data SPD decoder + /// @param[out] o_rc ReturnCode for failure to init object + /// + pre_data_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const spd::facade& i_spd_data, + fapi2::ReturnCode& o_rc); + + /// + /// @brief default dtor + /// + ~pre_data_engine() = default; + + /// + /// @brief Set ATTR_EFF_DIMM_TYPE + /// @return FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode set_dimm_type(); + + /// + /// @brief Set ATTR_EFF_DRAM_GEN + /// @return FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode set_dram_gen(); + + /// + /// @brief Set ATTR_EFF_HYBRID + /// @return FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode set_hybrid(); + + /// + /// @brief Set ATTR_EFF_HYBRID_MEMORY_TYPE + /// @return FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode set_hybrid_media(); + + /// + /// @brief Set ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM + /// @return FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode set_master_ranks(); + + /// + /// @brief Sets ATTR_EFF_DIMM_RANKS_CONFIGED + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode set_dimm_ranks_configured(); +}; + +}//mss + +#endif diff --git a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H index e7fee6e6d..422d95443 100644 --- a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H +++ b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H @@ -45,17 +45,55 @@ #include <fapi2.H> // mss lib +#include <generic/memory/lib/spd/spd_decoder_def.H> #include <generic/memory/lib/spd/common/dimm_module_decoder.H> #include <generic/memory/lib/spd/common/rcw_settings.H> -#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H> -#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H> -#include <generic/memory/lib/utils/c_str.H> #include <generic/memory/lib/spd/common/spd_decoder_base.H> #include <generic/memory/lib/spd/spd_checker.H> namespace mss { +namespace spd +{ + +/// +/// @brief sdram package types. Follows encodings in SPD +/// +enum sdram_package_type : uint8_t +{ + // Package Type + MONOLITHIC = 0, ///< Monolithic DRAM device + NON_MONOLITHIC = 1, ///< NonMonolithic DRAM device (3DS, Dual/Quad Die, etc) + + // Signal loading + UNSPECIFIED = MONOLITHIC, ///< Not specified + MULTI_LOAD_STACK = 1, ///< Multi laod stack + SINGLE_LOAD_STACK = 2, ///< Single load stack (3DS) +}; + +/// +/// @brief module type DDR4 encoding +/// +enum module_type +{ + NOT_HYBRID = 0, + HYBRID = 1, + NVDIMM_HYBRID = 1 +}; + +/// +/// @brief enum for voltage information. Encoding comes from SPD +/// +enum nominal_voltage : uint8_t +{ + NOT_OPERABLE = 0, ///< Not operable at 1.2V + OPERABLE = 1, ///< Operable at 1.2V + + NOT_ENDURANT = 0, ///< Not endurant at 1.2V + ENDURANT = 1 ///< Endurant at 1.2 V +}; + /// /// @brief Connector to SDRAM Bit Mapping field positions /// @note Bytes 60 - 77 . Mapping to Package rank map and @@ -117,11 +155,11 @@ static fapi2::ReturnCode nibble_map_helper( const fapi2::Target<fapi2::TARGET_TY const bool VALID_LOWER_NIBBLE = (i_bit_order >= LOW_BIT_ORDER_MIN) && (i_bit_order <= LOW_BIT_ORDER_MAX); const bool VALID_UPPER_NIBBLE = (i_bit_order >= UP_BIT_ORDER_MIN) && (i_bit_order <= UP_BIT_ORDER_MAX); - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (VALID_LOWER_NIBBLE || VALID_UPPER_NIBBLE), - i_byte, - i_bit_order, - "Failed check on the NIBBLE_MAP field") ); + FAPI_TRY(check::fail_for_invalid_value(i_target, + (VALID_LOWER_NIBBLE || VALID_UPPER_NIBBLE), + i_byte, + i_bit_order, + "Failed check on the NIBBLE_MAP field") ); fapi_try_exit: return fapi2::current_err; } @@ -139,11 +177,11 @@ static fapi2::ReturnCode package_rank_map_helper( const fapi2::Target<fapi2::TAR { // Taken from the SPD JEDEC spec, only valid encoding, the rest are reserved constexpr uint64_t VALID_VALUE = 0; - FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target, - (i_pkg_rank_map == VALID_VALUE), - i_byte, - i_pkg_rank_map, - "Failed check on Package Rank Map") ); + FAPI_TRY(check::fail_for_invalid_value(i_target, + (i_pkg_rank_map == VALID_VALUE), + i_byte, + i_pkg_rank_map, + "Failed check on Package Rank Map") ); fapi_try_exit: return fapi2::current_err; } @@ -374,1353 +412,1453 @@ class connectorTraits<CB0_7, PKG_RANK_MAP> } }; -namespace spd -{ - -/// -/// @brief sdram package types. Follows encodings in SPD -/// -enum sdram_package_type : uint8_t -{ - // Package Type - MONOLITHIC = 0, ///< Monolithic DRAM device - NON_MONOLITHIC = 1, ///< Non-Monolithic DRAM device (3DS, Dual/Quad Die, etc) - - // Signal loading - UNSPECIFIED = MONOLITHIC, ///< Not specified - MULTI_LOAD_STACK = 1, ///< Multi laod stack - SINGLE_LOAD_STACK = 2, ///< Single load stack (3DS) -}; - -/// -/// @brief enum for voltage information. Encoding comes from SPD -/// -enum nominal_voltage : uint8_t -{ - NOT_OPERABLE = 0, ///< Not operable at 1.2V - OPERABLE = 1, ///< Operable at 1.2V - - NOT_ENDURANT = 0, ///< Not endurant at 1.2V - ENDURANT = 1 ///< Endurant at 1.2 V -}; - -namespace ddr4 -{ - /// /// @class decoder +/// @tparam R SPD revision - partial specialization /// @brief Base SPD DRAM decoder /// -class decoder_v1_0 : public decoder +template < rev R > +class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder { - protected: - enum - { - // Byte 0 - BYTES_USED_START = 4, - BYTES_USED_LEN = 4, - - BYTES_TOTAL_START = 1, - BYTES_TOTAL_LEN = 3, - - // Byte 1 - see factory byte enum - // Byte 2 - Entire byte used - // Byte 3 - used in the SPD factory - - // Byte 4 - SDRAM_CAPACITY_START = 4, - SDRAM_CAPACITY_LEN = 4, - - SDRAM_BANKS_START = 2, - SDRAM_BANKS_LEN = 2, - - BANK_GROUP_START = 0, - BANK_GROUP_LEN = 2, - - // Byte 5 - COL_ADDRESS_START = 5, - COL_ADDRESS_LEN = 3, - - ROW_ADDRESS_START = 2, - ROW_ADDRESS_LEN = 3, - - // Byte 6 - PRIM_SIGNAL_LOAD_START = 6, - PRIM_SIGNAL_LOAD_LEN = 2, - - PRIM_DIE_COUNT_START = 1, - PRIM_DIE_COUNT_LEN = 3, - - PRIM_PACKAGE_TYPE_START = 0, - PRIM_PACKAGE_TYPE_LEN = 1, - - // Byte 7 - MAC_START = 4, - MAC_LEN = 4, - - TMAW_START = 2, - TMAW_LEN = 2, - - // Byte 8 reserved - - // Byte 9 - SOFT_PPR_START = 2, - SOFT_PPR_LEN = 1, - - PPR_START = 0, - PPR_LEN = 2, - - // Byte 10 - SEC_SIGNAL_LOAD_START = 5, - SEC_SIGNAL_LOAD_LEN = 2, - - DENSITY_RATIO_START = 4, - DENSITY_RATIO_LEN = 2, - - SEC_DIE_COUNT_START = 1, - SEC_DIE_COUNT_LEN = 3, - - SEC_PACKAGE_TYPE_START = 0, - SEC_PACKAGE_TYPE_LEN = 1, - - // Byte 11 - OPERABLE_START = 7, - OPERABLE_LEN = 1, - - ENDURANT_START = 6, - ENDURANT_LEN = 1, - - NOM_VOLT_START = 0, - NOM_VOLT_LEN = 6, - - // Byte 12 - SDRAM_WIDTH_START = 5, - SDRAM_WIDTH_LEN = 3, - - PACKAGE_RANKS_START = 2, - PACKAGE_RANKS_LEN = 3, - - RANK_MIX_START = 1, - RANK_MIX_LEN = 1, - - // Byte 13 - BUS_WIDTH_START = 5, - BUS_WIDTH_LEN = 3, + private: - BUS_EXT_WIDTH_START = 3, - BUS_EXT_WIDTH_LEN = 2, + using fields_t = fields<DDR4, BASE_CNFG>; + fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + std::vector<uint8_t> iv_data; - // Byte 14 - THERM_SENSOR_RESERV_START = 1, - THERM_SENSOR_RESERV_LEN = 7, + /// + /// @brief SPD byte field threshold check + /// @param[out] o_value list of connector_field values from SPD + /// @return FAPI2_RC_SUCCESS iff okay + /// + template< connector_bits T, connector_field OT, typename TT = connectorTraits<T, OT> > + fapi2::ReturnCode sdram_connector_helper( std::vector<uint8_t>& o_value ) const + { + for( size_t byte = TT::START; byte <= TT::END; ++byte ) + { + uint8_t l_field = 0; - THERM_SENSOR_START = 0, - THERM_SENSOR_LEN = 1, + fapi2::buffer<uint8_t> l_buffer(iv_data[byte]); + l_buffer.extractToRight<TT::EXTRACT_START, TT::EXTRACT_LEN>(l_field); - // Byte 15 - EXT_MOD_TYPE_START = 5, - EXT_MOD_TYPE_LEN = 3, + FAPI_DBG("%s SPD byte %d, data: %d, field value: %d, starting bit: %d, bit length: %d", + spd::c_str(iv_target), byte, iv_data[byte], l_field, TT::EXTRACT_START, TT::EXTRACT_LEN); - // Byte 16 - reserved + FAPI_TRY( TT::fail_check(iv_target, byte, l_field) ); - // Byte 17 - FINE_TIMEBASE_START = 6, - FINE_TIMEBASE_LEN = 2, + o_value.push_back(l_field); + } - MED_TIMEBASE_START = 4, - MED_TIMEBASE_LEN = 2, + fapi_try_exit: + return fapi2::current_err; + } - // Byte 18 - Entire byte used - // Byte 19 - Entire byte used + /// + /// @class proxy + /// @brief Nested class to help specialize certain decoder methods + /// @tparam U SPD revision + /// @tparam B dummy var to faciliate partial specialization - defaulted to true + /// @note explicit specialization of a class isn't allowed on the HB compiler. + /// This is a helper class to workaround specialization for just a few methods + /// instead of having the explicitly specialize the entire class itself. + /// Since nested classes also can't be explicitly specialized...we use a bool + /// template param to facilitate partial specialzation of the nested helper class. + /// + template< rev U, bool B = true > + struct proxy + { + /// + /// @brief Decodes Minimum Write Recovery Time + /// @param[in] i_target dimm target + /// @param[in] i_data SPD data vector + /// @param[out] o_value tWRmin in MTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode min_twr( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_data, + int64_t& o_value ) + { + uint8_t l_twrmin_msn = 0; + uint8_t l_twrmin_lsb = 0; + + FAPI_TRY( (mss::spd::reader<fields_t::TWRMIN_MSN, U>(i_target, i_data, l_twrmin_msn)) ); + FAPI_TRY( (mss::spd::reader<fields_t::TWRMIN_LSB, U>(i_target, i_data, l_twrmin_lsb)) ); + + { + fapi2::buffer<int64_t> l_buffer; + rightAlignedInsert(l_buffer, l_twrmin_msn, l_twrmin_lsb); + + // Update output only after check passes + FAPI_TRY( check::max_timing_range<BITS12>(i_target, l_buffer, TWRMIN)); + o_value = l_buffer; + + FAPI_INF("%s. Minimum Write Recovery Time (tWRmin) in MTB units: %d", + spd::c_str(i_target), + o_value); + } + fapi_try_exit: + return fapi2::current_err; + } - // Byte 20-23 - CAS_BYTE_1_START = 56, - CAS_BYTE_1_LEN = 8, - CAS_BYTE_2_START = 48, - CAS_BYTE_2_LEN = 8, - CAS_BYTE_3_START = 40, - CAS_BYTE_3_LEN = 8, - CAS_BYTE_4_START = 32, - CAS_BYTE_4_LEN = 8, + /// + /// @brief Decodes Minimum Write to Read Time - Same Bank Group + /// @param[in] i_target dimm target + /// @param[in] i_data SPD data vector + /// @param[out] o_value tWRT_Lmin in MTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode min_twtr_l( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_data, + int64_t& o_value ) + { + uint8_t l_twtr_lmin_msn = 0; + uint8_t l_twtr_lmin_lsb = 0; - // Byte 24 - Entire byte used - // Byte 25 - Entire byte used - // Byte 26 - Entire byte used + FAPI_TRY( (mss::spd::reader<fields_t::TWTRMIN_L_MSN, U>(i_target, i_data, l_twtr_lmin_msn)) ); + FAPI_TRY( (mss::spd::reader<fields_t::TWTRMIN_L_LSB, U>(i_target, i_data, l_twtr_lmin_lsb)) ); - // Byte 27 - TRASMIN_MSN_START = 4, // MSN = most significant nibble - TRASMIN_MSN_LEN = 4, + { + fapi2::buffer<int64_t> l_buffer; + rightAlignedInsert(l_buffer, l_twtr_lmin_msn, l_twtr_lmin_lsb); - TRCMIN_MSN_START = 0, // MSN = most significant nibble - TRCMIN_MSN_LEN = 4, + // Update output only after check passes + FAPI_TRY( check::max_timing_range<BITS12>(i_target, l_buffer, TWTR_L_MIN)); + o_value = l_buffer; - // Byte 28 - TRASMIN_LSB_START = 0, // LSB = least significant byte - TRASMIN_LSB_LEN = 8, + FAPI_INF("%s. Minimum Write to Read Time - Different Bank Group (tWTR_Lmin) in MTB units: %d", + spd::c_str(i_target), + o_value); + } - // Byte 29 - TRCMIN_LSB_START = 0, // LSB = least significant byte - TRCMIN_LSB_LEN = 8, + fapi_try_exit: + return fapi2::current_err; + } - // Byte 30 - TRFC1MIN_LSB_START = 0, - TRFC1MIN_LSB_LEN = 8, + /// + /// @brief Decodes Minimum Write to Read Time - Different Bank Group + /// @param[in] i_target dimm target + /// @param[in] i_data SPD data vector + /// @param[out] o_value tWRT_Smin in MTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode min_twtr_s( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_data, + int64_t& o_value ) + { + uint8_t l_twtr_smin_msn = 0; + uint8_t l_twtr_smin_lsb = 0; - // Byte 31 - TRFC1MIN_MSB_START = 0, - TRFC1MIN_MSB_LEN = 8, + FAPI_TRY( (mss::spd::reader<fields_t::TWTRMIN_S_MSN, U>(i_target, i_data, l_twtr_smin_msn)) ); + FAPI_TRY( (mss::spd::reader<fields_t::TWTRMIN_S_LSB, U>(i_target, i_data, l_twtr_smin_lsb)) ); - // Byte 32 - TRFC2MIN_LSB_START = 0, - TRFC2MIN_LSB_LEN = 8, + { + fapi2::buffer<int64_t> l_buffer; + rightAlignedInsert(l_buffer, l_twtr_smin_msn, l_twtr_smin_lsb); - // Byte 33 - TRFC2MIN_MSB_START = 0, - TRFC2MIN_MSB_LEN = 8, + // Update output only after check passes + FAPI_TRY( check::max_timing_range<BITS12>(i_target, l_buffer, TWTR_S_MIN)); + o_value = l_buffer; - // Byte 34 & Byte 35 - TRFC4MIN_LSB_START = 0, - TRFC4MIN_LSB_LEN = 8, + FAPI_INF("%s. Minimum Write to Read Time - Different Bank Group (tWTR_Smin) in MTB units: %d", + spd::c_str(i_target), + o_value); + } - TRFC4MIN_MSB_START = 0, - TRFC4MIN_MSB_LEN = 8, + fapi_try_exit: + return fapi2::current_err; + } + }; - // Byte 36 - TFAWMIN_MSN_START = 4, - TFAWMIN_MSN_LEN = 4, + /// + /// @class proxy - rev::V1_0 specialization + /// @brief Nested class to help specialize certain decoder methods + /// @tparam B dummy var to faciliatate partial specialization + /// @note If the decoder methods are rev::v1_0 hardcode them to these values + /// + template< bool B > + struct proxy<rev::V1_0, B> + { - // Byte 37 - TFAWMIN_LSB_START = 0, - TFAWMIN_LSB_LEN = 8, + /// + /// @brief Decodes Minimum Write Recovery Time + /// @param[in] i_target dimm target + /// @param[in] i_data SPD data vector + /// @param[out] o_value tWRmin in MTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode min_twr( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_data, + int64_t& o_value ) + { + // For General Section rev 1.0 of the SPD, + // SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) were reserved + // and coded as zeros. + // Default as 0x78 for all DDR4 bins for rev 1.0 + o_value = 0x78; + return fapi2::FAPI2_RC_SUCCESS; + } - // Byte 38 - Entire byte used - // Byte 39 - Entire byte used - // Byte 40 - Entire byte used + /// + /// @brief Decodes Minimum Write to Read Time - Same Bank Group + /// @param[in] i_target dimm target + /// @param[in] i_data SPD data vector + /// @param[out] o_value tWRT_Lmin in MTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode min_twtr_l( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_data, + int64_t& o_value ) + { + // For General Section rev 1.0 of the SPD, + // SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) were reserved + // and coded as zeros. + // Default as 0x3C for all DDR4 bins for rev 1.0 + o_value = 0x3C; + return fapi2::FAPI2_RC_SUCCESS; + } - // Byte 41 - TWRMIN_MSN_START = 4, // MSN = most significant nibble - TWRMIN_MSN_LEN = 4, + /// + /// @brief Decodes Minimum Write to Read Time - Different Bank Group + /// @param[in] i_target dimm target + /// @param[in] i_data SPD data vector + /// @param[out] o_value tWRT_Smin in MTB units + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode min_twtr_s( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_data, + int64_t& o_value ) + { + // For General Section rev 1.0 of the SPD, + // SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) were reserved + // and coded as zeros. + // Default as 0x14 for all DDR4 bins for rev 1.0 + o_value = 0x14; + return fapi2::FAPI2_RC_SUCCESS; + } - // Byte 42 - TWRMIN_LSB_START = 0, // LSB = least significant nibble - TWRMIN_LSB_LEN = 8, + }; - // Byte 43 - TWTRMIN_L_MSN_START = 0, // MSN = most significant nibble - TWTRMIN_L_MSN_LEN = 4, + public: - TWTRMIN_S_MSN_START = 4, // MSN = most significant nibble - TWTRMIN_S_MSN_LEN = 4, + /// + /// @brief default ctor + /// + decoder() = default; - // Byte 44 - TWTRMIN_S_LSB_START = 0, // LSB = least significant byte - TWTRMIN_S_LSB_LEN = 8, + /// + /// @brief ctor + /// @param[in] i_target dimm target + /// @param[in] i_spd_data SPD data vector + /// + decoder(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data): + base_cnfg_decoder(i_target, i_spd_data), + iv_target(i_target), + iv_data(i_spd_data) + { + static_assert( R <= rev::GEN_SEC_MAX, " R > rev::GEN_SEC_MAX"); + } - // Byte 45 - TWTRMIN_L_LSB_START = 0, - TWTRMIN_L_LSB_LEN = 8, + /// + /// @brief Default dtor + /// + virtual ~decoder() = default; - // Bytes 46 - 59 - reserved + ///////////////////////// + // Member Methods + ///////////////////////// - // Bytes 78 - 116 - reserved + /// + /// @brief Gets decoder target + /// @return fapi2::Target<fapi2::TARGET_TYPE_DIMM> + /// + virtual fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_dimm_target() const + { + return iv_target; + } - // Bytes 117 - 125 : Entire byte used + /// + /// @brief Gets decoder SPD data + /// @return std::vector<uint8_t> + /// + virtual std::vector<uint8_t> get_data() const + { + return iv_data; + } - // Byte 126 - CRC_LSB_START = 0, - CRC_LSB_LEN = 8, + /// + /// @brief Sets decoder SPD data + /// @param[in] i_spd_data SPD data in a vector reference + /// + virtual void set_data(const std::vector<uint8_t>& i_spd_data) + { + iv_data = i_spd_data; + } - // Byte 127 - CRC_MSB_START = 0, - CRC_MSB_LEN = 8, + /// + /// @brief Decodes number of used SPD bytes + /// @param[out] o_value number of SPD bytes used + /// @return FAPI2_RC_SUCCESS iff okay + /// + virtual fapi2::ReturnCode number_of_used_bytes( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::BYTES_USED, R>(iv_target, iv_data, o_value)) ); - // Byte 320 - // Skip SPD most signigicant bit, so our 0 - MOD_MFG_LSB_START = 0, - MOD_MFG_LSB_LEN = 8, + fapi_try_exit: + return fapi2::current_err; + } - // Byte 321 - MOD_MFG_MSB_START = 0, - MOD_MFG_MSB_LEN = 8, + /// + /// @brief Decodes total number of SPD bytes + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS iff okay + /// + virtual fapi2::ReturnCode number_of_total_bytes( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TOTAL_BYTES, R>(iv_target, iv_data, o_value)) ); - }; + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief Helper function that turns Logical ranks in Primary SDRAM type - /// @param[out] o_logical_ranks number of logical ranks - /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// @brief Decodes SDP revision + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS iff okay /// - virtual fapi2::ReturnCode prim_sdram_logical_ranks( uint8_t& o_logical_ranks ) const; - - public: + virtual fapi2::ReturnCode revision( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::REVISION, R>(iv_target, iv_data, o_value)) ); - // First field is byte index - // Second field is the decoding start bit - // Third field is the decoding bit length - static constexpr field_t BYTES_USED{0, BYTES_USED_START, BYTES_USED_LEN}; - static constexpr field_t TOTAL_BYTES_USED{0, BYTES_TOTAL_START, BYTES_TOTAL_LEN}; - static constexpr field_t SDRAM_CAPACITY{4, SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN}; - static constexpr field_t SDRAM_BANKS{4, SDRAM_BANKS_START, SDRAM_BANKS_LEN}; - static constexpr field_t BANK_GROUP{4, BANK_GROUP_START, BANK_GROUP_LEN}; - static constexpr field_t COL_ADDRESS{5, COL_ADDRESS_START, COL_ADDRESS_LEN}; - static constexpr field_t ROW_ADDRESS{5, ROW_ADDRESS_START, ROW_ADDRESS_LEN}; - static constexpr field_t PRIM_SIGNAL_LOADING{6, PRIM_SIGNAL_LOAD_START, PRIM_SIGNAL_LOAD_LEN}; - static constexpr field_t PRIM_DIE_COUNT{6, PRIM_DIE_COUNT_START, PRIM_DIE_COUNT_LEN}; - static constexpr field_t PRIM_PACKAGE_TYPE{6, PRIM_PACKAGE_TYPE_START, PRIM_PACKAGE_TYPE_LEN}; - static constexpr field_t MAC{7, MAC_START, MAC_LEN}; - static constexpr field_t TMAW{7, TMAW_START, TMAW_LEN}; - static constexpr field_t PPR{9, PPR_START, PPR_LEN}; - static constexpr field_t SOFT_PPR{9, SOFT_PPR_START, SOFT_PPR_LEN}; - static constexpr field_t SEC_SIGNAL_LOADING{10, SEC_SIGNAL_LOAD_START, SEC_SIGNAL_LOAD_LEN}; - static constexpr field_t SEC_DENSITY_RATIO{10, DENSITY_RATIO_START, DENSITY_RATIO_LEN}; - static constexpr field_t SEC_DIE_COUNT{10, SEC_DIE_COUNT_START, SEC_DIE_COUNT_LEN}; - static constexpr field_t SEC_PACKAGE_TYPE{10, SEC_PACKAGE_TYPE_START, SEC_PACKAGE_TYPE_LEN}; - static constexpr field_t OPERABLE_FLD{11, OPERABLE_START, OPERABLE_LEN}; - static constexpr field_t ENDURANT_FLD{11, ENDURANT_START, ENDURANT_LEN}; - static constexpr field_t SDRAM_WIDTH{12, SDRAM_WIDTH_START, SDRAM_WIDTH_LEN}; - static constexpr field_t RANK_MIX{12, RANK_MIX_START, RANK_MIX_LEN}; - static constexpr field_t PACKAGE_RANKS{12, PACKAGE_RANKS_START, PACKAGE_RANKS_LEN}; - static constexpr field_t BUS_WIDTH{13, BUS_WIDTH_START, BUS_WIDTH_LEN}; - static constexpr field_t BUS_EXT_WIDTH{13, BUS_EXT_WIDTH_START, BUS_EXT_WIDTH_LEN}; - static constexpr field_t THERM_SENSOR{14, THERM_SENSOR_START, THERM_SENSOR_LEN}; - static constexpr field_t EXTENDED_MODULE_TYPE{15, EXT_MOD_TYPE_START, EXT_MOD_TYPE_LEN}; - static constexpr field_t FINE_TIMEBASE{17, FINE_TIMEBASE_START, FINE_TIMEBASE_LEN}; - static constexpr field_t MEDIUM_TIMEBASE{17, MED_TIMEBASE_START, MED_TIMEBASE_LEN}; - static constexpr field_t TRASMIN_MSN{27, TRASMIN_MSN_START, TRASMIN_MSN_LEN}; - static constexpr field_t TRASMIN_LSB{28, TRASMIN_LSB_START, TRASMIN_LSB_LEN}; - static constexpr field_t TRCMIN_MSN{27, TRCMIN_MSN_START, TRCMIN_MSN_LEN}; - static constexpr field_t TRCMIN_LSB{29, TRCMIN_LSB_START, TRCMIN_LSB_LEN}; - static constexpr field_t TRFC1MIN_MSB{31, TRFC1MIN_MSB_START, TRFC1MIN_MSB_LEN}; - static constexpr field_t TRFC1MIN_LSB{30, TRFC1MIN_LSB_START, TRFC1MIN_LSB_LEN}; - static constexpr field_t TRFC2MIN_MSB{33, TRFC2MIN_MSB_START, TRFC2MIN_MSB_LEN}; - static constexpr field_t TRFC2MIN_LSB{32, TRFC2MIN_LSB_START, TRFC2MIN_LSB_LEN}; - static constexpr field_t TRFC4MIN_MSB{35, TRFC4MIN_MSB_START, TRFC4MIN_MSB_LEN}; - static constexpr field_t TRFC4MIN_LSB{34, TRFC4MIN_LSB_START, TRFC4MIN_LSB_LEN}; - static constexpr field_t TFAWMIN_MSN{36, TFAWMIN_MSN_START, TFAWMIN_MSN_LEN}; - static constexpr field_t TFAWMIN_LSB{37, TFAWMIN_LSB_START, TFAWMIN_LSB_LEN}; - static constexpr field_t TWRMIN_MSN{41, TWRMIN_MSN_START, TWRMIN_MSN_LEN}; - static constexpr field_t TWRMIN_LSB{42, TWRMIN_LSB_START, TWRMIN_LSB_LEN}; - static constexpr field_t TWTRMIN_S_MSN{43, TWTRMIN_S_MSN_START, TWTRMIN_S_MSN_LEN}; - static constexpr field_t TWTRMIN_S_LSB{44, TWTRMIN_S_LSB_START, TWTRMIN_S_LSB_LEN}; - static constexpr field_t TWTRMIN_L_MSN{43, TWTRMIN_L_MSN_START, TWTRMIN_L_MSN_LEN}; - static constexpr field_t TWTRMIN_L_LSB{45, TWTRMIN_L_LSB_START, TWTRMIN_L_LSB_LEN}; - static constexpr field_t CRC_MSB{127, CRC_MSB_START, CRC_MSB_LEN}; - static constexpr field_t CRC_LSB{126, CRC_LSB_START, CRC_LSB_LEN}; - - // Default constructor deleted - decoder_v1_0() = delete; + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief ctor - /// @param[in] i_target dimm target - /// @param[in] i_spd_data SPD data vector - /// @param[in] i_module_decoder shared_ptr to dimm module decoder - /// @param[in] i_raw_card raw pointer to rcd data + /// @brief Decodes DRAM device type + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS iff okay /// - decoder_v1_0(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - const std::shared_ptr<dimm_module_decoder>& i_module_decoder, - const rcw_settings& i_raw_card); + virtual fapi2::ReturnCode device_type( uint8_t& o_value ) const override + { + // Sparsed reserved bits within valid SPD field range + static const std::vector<uint8_t> l_reserved_bits{0x00, 0x0D}; + FAPI_TRY( (mss::spd::reader<fields_t::DEVICE_TYPE, R>(iv_target, iv_data, o_value)) ); + FAPI_TRY( check::reserved_values(iv_target, l_reserved_bits, DEVICE_TYPE, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief Default dtor + /// @brief Decodes base module type + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS iff okay /// - virtual ~decoder_v1_0() = default; + virtual fapi2::ReturnCode base_module( uint8_t& o_value ) const override + { + // Sparsed reserved bits within valid SPD field range + static const std::vector<uint8_t> l_reserved_bits{0b0111, 0b1010, 0b1011, 0b1110, 0b1111}; + FAPI_TRY( (mss::spd::reader<fields_t::BASE_MODULE, R>(iv_target, iv_data, o_value)) ); + FAPI_TRY( check::reserved_values(iv_target, l_reserved_bits, BASE_MODULE_TYPE, o_value) ); - ///////////////////////// - // Member Methods - ///////////////////////// + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief Decodes number of used SPD bytes - /// @param[out] o_value number of SPD bytes used + /// @brief Decodes hybrid media + /// @param[out] o_value number of total SPD bytes /// @return FAPI2_RC_SUCCESS iff okay - /// @note Decodes SPD Byte 0 (3~0) - /// @note Item JC-45-2220.01x - /// @note Page 14 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode number_of_used_bytes( uint16_t& o_value ) const override; + virtual fapi2::ReturnCode hybrid_media( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::HYBRID_MEDIA, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief Decodes total number of SPD bytes + /// @brief Decodes hybrid /// @param[out] o_value number of total SPD bytes /// @return FAPI2_RC_SUCCESS iff okay - /// @note Decodes SPD Byte 0 (bits 6~4) - /// @note Item JC-45-2220.01x - /// @note Page 14 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode number_of_total_bytes( uint16_t& o_value ) const override; + virtual fapi2::ReturnCode hybrid( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::HYBRID, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM density from SPD /// @param[out] o_value SDRAM density in GBs /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 4 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode sdram_density( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode sdram_density( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::SDRAM_CAPACITY, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes number of SDRAM banks bits from SPD /// @param[out] o_value Number of SDRAM bank bits /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 4 (bits 5~4) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode bank_bits( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode bank_bits( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::BANKS_ADDR_BITS, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes number of SDRAM bank groups bits from SPD /// @param[out] o_value Number of SDRAM bank groups bits /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 4 (bits 7~6) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode bank_group_bits( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode bank_group_bits( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::BANK_GROUP_BITS, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes number of SDRAM column address bits + /// @param[out] o_value Number of SDRAM bank bits /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 5 (bits 2~0) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode column_address_bits( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode column_address_bits( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::COL_ADDR_BITS, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes number of SDRAM row address bits + /// @param[out] o_value Number of SDRAM bank bits /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 5 (bits 5~3) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode row_address_bits( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode row_address_bits( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::ROW_ADDR_BITS, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Primary SDRAM signal loading + /// @param[out] o_value Number of SDRAM bank bits /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 6 (bits 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 19 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode prim_sdram_signal_loading( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode prim_sdram_signal_loading( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::PRIM_SIGNAL_LOADING, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Primary SDRAM die count + /// @param[out] o_value Number of SDRAM bank bits /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 6 (bits 6~4) - /// @note Item JC-45-2220.01x - /// @note Page 19 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode prim_sdram_die_count( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode prim_sdram_die_count( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::PRIM_DIE_COUNT, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Primary SDRAM package type /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 6 (bit 7) - /// @note Item JC-45-2220.01x - /// @note Page 19 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode prim_sdram_package_type( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode prim_sdram_package_type( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::PRIM_PACKAGE_TYPE, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode SDRAM Maximum activate count /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 7 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 20 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode maximum_activate_count( uint32_t& o_value ) const override; + virtual fapi2::ReturnCode maximum_activate_count( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::MAC, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 7 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 20 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode maximum_activate_window_multiplier( uint32_t& o_value ) const override; + virtual fapi2::ReturnCode maximum_activate_window_multiplier( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TMAW, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode Post package repair (PPR) /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 9 (bits 7~6) - /// @note Item JC-45-2220.01x - /// @note Page 21 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode post_package_repair( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode post_package_repair( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::PPR, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode Soft post package repair (soft PPR) /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 9 (bit 5) - /// @note Item JC-45-2220.01x - /// @note Page 21 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode soft_post_package_repair( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode soft_post_package_repair( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::SOFT_PPR, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Secondary SDRAM signal loading /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 10 (bits 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode sec_sdram_signal_loading( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode sec_sdram_signal_loading( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::SEC_SIGNAL_LOADING, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Secondary DRAM Density Ratio /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 10 (bits 3~2) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode sec_dram_density_ratio( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode sec_dram_density_ratio( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::SEC_DENSITY_RATIO, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Secondary SDRAM die count /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 10 (bits 6~4) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode sec_sdram_die_count( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode sec_sdram_die_count( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::SEC_DIE_COUNT, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Secondary SDRAM package type /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 10 (bit 7) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode sec_sdram_package_type( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode sec_sdram_package_type( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::SEC_PACKAGE_TYPE, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode Module Nominal Voltage, VDD /// @param[out] o_value enum representing if 1.2V is operable /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 11 (bit 0) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode operable_nominal_voltage( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode operable_nominal_voltage( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OPERABLE_FLD, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode Module Nominal Voltage, VDD /// @param[out] o_value enum representing if 1.2V is endurant /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 11 (bit 1) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode endurant_nominal_voltage( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode endurant_nominal_voltage( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::ENDURANT_FLD, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } + /// /// @brief Decodes SDRAM device width /// @param[out] o_value device width in bits /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 12 (bits 2~0) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode device_width( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode device_width( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::SDRAM_WIDTH, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes number of package ranks per DIMM /// @param[out] o_value number of package ranks per DIMM /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 12 (bits 5~3) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode num_package_ranks_per_dimm( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode num_package_ranks_per_dimm( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::PACKAGE_RANKS, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Rank Mix /// @param[out] o_value rank mix value from SPD /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 12 (bit 6) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode rank_mix( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode rank_mix( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::RANK_MIX, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes primary bus width /// @param[out] o_value primary bus width in bits /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 13 (bits 2~0) - /// @note Item JC-45-2220.01x - /// @note Page 27 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode prim_bus_width( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode prim_bus_width( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::BUS_WIDTH, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes bus width extension /// @param[out] o_value bus width extension in bits /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 13 (bits 4~3) - /// @note Item JC-45-2220.01x - /// @note Page 27 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode bus_width_extension( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode bus_width_extension( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::BUS_EXT_WIDTH, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode Module Thermal Sensor /// @param[out] o_value thermal sensor value from SPD /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 14 (bit 7) - /// @note Item JC-45-2220.01x - /// @note Page 28 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode thermal_sensor( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode thermal_sensor( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::THERM_SENSOR, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode Extended Base Module Type /// @param[out] o_value extended base module type value from SPD /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 15 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 28 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode extended_base_module_type( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode extended_base_module_type( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::EXTENDED_MODULE_TYPE, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode Fine Timebase /// @param[out] o_value fine_timebase from SPD in picoseconds /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 17 (bits 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 29 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_timebase( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_timebase( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::FINE_TIMEBASE, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode Medium Timebase /// @param[out] o_value fine_timebase from SPD in picoseconds /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 17 (bits 3~2) - /// @note Item JC-45-2220.01x - /// @note Page 29 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode medium_timebase( int64_t& o_value ) const override; + virtual fapi2::ReturnCode medium_timebase( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::MEDIUM_TIMEBASE, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// /// @brief Decodes SDRAM Minimum Cycle Time in MTB /// @param[out] o_value tCKmin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 18 - /// @note Item JC-45-2220.01x - /// @note Page 31-32 - /// @note DDR4 SPD Document Release 3 - /// @warning If tCKmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tCKmin (SPD byte 125) - /// used for correction to get the actual value. /// - virtual fapi2::ReturnCode min_tck( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_tck( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TCK_MIN, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Maximum Cycle Time in MTB /// @param[out] o_value tCKmax in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 19 - /// @note Item JC-45-2220.01x - /// @note Page 32 - /// @note DDR4 SPD Document Release 3 - /// @warning If tCKmax cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tCKmax (SPD byte 124) - /// used for correction to get the actual value. /// - virtual fapi2::ReturnCode max_tck( int64_t& o_value ) const override; + virtual fapi2::ReturnCode max_tck( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TCK_MAX, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decode CAS Latencies Supported /// @param[out] o_value bitmap of supported CAS latencies /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Bytes 20-23 - /// @note Item JC-45-2220.01x - /// @note Page 33-34 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode supported_cas_latencies( uint64_t& o_value ) const override; + virtual fapi2::ReturnCode supported_cas_latencies( uint64_t& o_value ) const override + { + uint8_t l_first_raw_byte = 0; + uint8_t l_sec_raw_byte = 0; + uint8_t l_third_raw_byte = 0; + uint8_t l_fourth_raw_byte = 0; + + FAPI_TRY( (mss::spd::reader<fields_t::CL_FIRST_BYTE, R>(iv_target, iv_data, l_first_raw_byte)) ); + FAPI_TRY( (mss::spd::reader<fields_t::CL_SECOND_BYTE, R>(iv_target, iv_data, l_sec_raw_byte)) ); + FAPI_TRY( (mss::spd::reader<fields_t::CL_THIRD_BYTE, R>(iv_target, iv_data, l_third_raw_byte)) ); + FAPI_TRY( (mss::spd::reader<fields_t::CL_FOURTH_BYTE, R>(iv_target, iv_data, l_fourth_raw_byte)) ); + + { + // Buffers used for bit manipulation + // Combine Bytes to create bitmap - right aligned + fapi2::buffer<uint64_t> l_buffer; + rightAlignedInsert(l_buffer, l_fourth_raw_byte, l_third_raw_byte, l_sec_raw_byte, l_first_raw_byte); + + // According to the JEDEC spec: + // Byte 22 (Bits 7~0) and Byte 23 are reserved and thus not supported + // Check for a valid value + constexpr size_t MAX_VALID_VAL = 0x3FFFF; + FAPI_TRY( check::fail_for_invalid_value(iv_target, + l_buffer <= MAX_VALID_VAL, + 23, + l_buffer, + "Failed check on CAS latencies supported") ); + + // Update output value only if range check passes + o_value = int64_t(l_buffer); + + FAPI_INF("%s. CAS latencies supported (bitmap): 0x%llX", + spd::c_str(iv_target), + o_value); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Minimum CAS Latency Time in MTB /// @param[out] o_value tAAmin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 24 - /// @note Item JC-45-2220.01x - /// @note Page 34 - /// @note DDR4 SPD Document Release 3 - /// @warning If tAAmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tAAmin (SPD byte 123) - /// used for correction to get the actual value. /// - virtual fapi2::ReturnCode min_taa( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_taa( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TAA_MIN, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB /// @param[out] o_value tRCDmin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 25 - /// @note Item JC-45-2220.01x - /// @note Page 35 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRCDmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRCDmin (SPD byte 122) - /// used for correction to get the actual value /// - virtual fapi2::ReturnCode min_trcd( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_trcd( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TRCD_MIN, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB /// @param[out] o_value tRPmin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 26 - /// @note Item JC-45-2220.01x - /// @note Page 36-37 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRPmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRPmin (SPD byte 121) - /// used for correction to get the actual value /// - virtual fapi2::ReturnCode min_trp( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_trp( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TRP_MIN, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB /// @param[out] o_value tRASmin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 28 (bits 7~4) & SPD Byte 27 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 38 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode min_tras( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_tras( int64_t& o_value ) const override + { + uint8_t l_tRASmin_msn = 0; + uint8_t l_tRASmin_lsb = 0; + FAPI_TRY( (mss::spd::reader<fields_t::TRASMIN_MSN, R>(iv_target, iv_data, l_tRASmin_msn)) ); + FAPI_TRY( (mss::spd::reader<fields_t::TRASMIN_LSB, R>(iv_target, iv_data, l_tRASmin_lsb)) ); + + { + fapi2::buffer<int64_t> l_buffer; + rightAlignedInsert(l_buffer, l_tRASmin_msn, l_tRASmin_lsb); + + // Update output only after check passes + FAPI_TRY( check::max_timing_range<BITS12>(iv_target, l_buffer, TRASMIN)); + o_value = l_buffer; + + FAPI_INF("%s. Minimum Active to Precharge Delay Time (tRASmin) in MTB units: %d", + spd::c_str(iv_target), + o_value); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB /// @param[out] o_value tRCmin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 27 (bits 7~4) & SPD Byte 29 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 38 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRCmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRCmin (SPD byte 120) - /// used for correction to get the actual value. /// - virtual fapi2::ReturnCode min_trc( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_trc( int64_t& o_value ) const override + { + uint8_t l_trcmin_msn = 0; + uint8_t l_trcmin_lsb = 0; + FAPI_TRY( (mss::spd::reader<fields_t::TRCMIN_MSN, R>(iv_target, iv_data, l_trcmin_msn)) ); + FAPI_TRY( (mss::spd::reader<fields_t::TRCMIN_LSB, R>(iv_target, iv_data, l_trcmin_lsb)) ); + + { + // Combining bits to create timing value (in a buffer) + fapi2::buffer<int64_t> l_buffer; + rightAlignedInsert(l_buffer, l_trcmin_msn, l_trcmin_lsb); + + // Update output only after check passes + FAPI_TRY( check::max_timing_range<BITS12>(iv_target, l_buffer, TRCMIN)); + o_value = l_buffer; + + FAPI_INF("%s. Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB units: %d", + spd::c_str(iv_target), + o_value); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1 /// @param[out] o_value tRFC1min in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 30 & Byte 31 - /// @note Item JC-45-2220.01x - /// @note Page 39-40 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode min_trfc1( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_trfc1( int64_t& o_value ) const override + { + uint8_t l_trfc1min_msb = 0; + uint8_t l_trfc1min_lsb = 0; + + FAPI_TRY( (mss::spd::reader<fields_t::TRFC1MIN_MSB, R>(iv_target, iv_data, l_trfc1min_msb)) ); + FAPI_TRY( (mss::spd::reader<fields_t::TRFC1MIN_LSB, R>(iv_target, iv_data, l_trfc1min_lsb)) ); + + { + // Combining bits to create timing value (in a buffer) + fapi2::buffer<int64_t> l_buffer; + rightAlignedInsert(l_buffer, l_trfc1min_msb, l_trfc1min_lsb); + + // Update output only after check passes + FAPI_TRY( check::max_timing_range<BITS16>(iv_target, l_buffer, TRFC1MIN)); + o_value = l_buffer; + + FAPI_INF("%s. Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB units: %d", + spd::c_str(iv_target), + o_value); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2 /// @param[out] o_value tRFC2min in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 32 & Byte 33 - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode min_trfc2( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_trfc2( int64_t& o_value ) const override + { + uint8_t l_trfc2min_msb = 0; + uint8_t l_trfc2min_lsb = 0; + FAPI_TRY( (mss::spd::reader<fields_t::TRFC2MIN_MSB, R>(iv_target, iv_data, l_trfc2min_msb)) ); + FAPI_TRY( (mss::spd::reader<fields_t::TRFC2MIN_LSB, R>(iv_target, iv_data, l_trfc2min_lsb)) ); + + { + // Combining bits to create timing value (in a buffer) + fapi2::buffer<int64_t> l_buffer; + rightAlignedInsert(l_buffer, l_trfc2min_msb, l_trfc2min_lsb); + + // Update output only after check passes + FAPI_TRY( check::max_timing_range<BITS16>(iv_target, l_buffer, TRFC2MIN)); + o_value = l_buffer; + + FAPI_INF("%s. Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB units: %d", + spd::c_str(iv_target), + o_value); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4 /// @param[out] o_value tRFC4min in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 34 & Byte 35 - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode min_trfc4( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_trfc4( int64_t& o_value ) const override + { + uint8_t l_trfc4min_msb = 0; + uint8_t l_trfc4min_lsb = 0; + FAPI_TRY( (mss::spd::reader<fields_t::TRFC4MIN_MSB, R>(iv_target, iv_data, l_trfc4min_msb)) ); + FAPI_TRY( (mss::spd::reader<fields_t::TRFC4MIN_LSB, R>(iv_target, iv_data, l_trfc4min_lsb)) ); + + { + // Combining bits to create timing value (in a buffer) + fapi2::buffer<int64_t> l_buffer; + rightAlignedInsert(l_buffer, l_trfc4min_msb, l_trfc4min_lsb); + + // Update output only after check passes + FAPI_TRY( check::max_timing_range<BITS16>(iv_target, l_buffer, TRFC4MIN)); + o_value = l_buffer; + + FAPI_INF("%s. Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB units: %d", + spd::c_str(iv_target), + o_value); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes SDRAM Minimum Four Activate Window Delay Time /// @param[out] o_value tFAWmin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 36 (bits 3~0) & Byte 37 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 42 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode min_tfaw( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_tfaw( int64_t& o_value ) const override + { + uint8_t l_tfawmin_msn = 0; + uint8_t l_tfawmin_lsb = 0; + FAPI_TRY( (mss::spd::reader<fields_t::TFAWMIN_MSN, R>(iv_target, iv_data, l_tfawmin_msn)) ); + FAPI_TRY( (mss::spd::reader<fields_t::TFAWMIN_LSB, R>(iv_target, iv_data, l_tfawmin_lsb)) ); + + { + // Combining bits to create timing value (in a buffer) + fapi2::buffer<int64_t> l_buffer; + rightAlignedInsert(l_buffer, l_tfawmin_msn, l_tfawmin_lsb); + + // Update output only after check passes + FAPI_TRY( check::max_timing_range<BITS12>(iv_target, l_buffer, TFAWMIN)); + o_value = l_buffer; + + FAPI_INF("%s. Minimum Four Activate Window Delay Time (tFAWmin) in MTB units: %d", + spd::c_str(iv_target), + o_value); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group /// @param[out] o_value tRRD_Smin MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 38 - /// @note Item JC-45-2220.01x - /// @note Page 43 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRRD_Smin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRRD_Smin (SPD byte 119) - /// used for correction to get the actual value. /// - virtual fapi2::ReturnCode min_trrd_s( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_trrd_s( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TRRD_S_MIN, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group /// @param[out] o_value tRRD_Lmin MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 39 - /// @note Item JC-45-2220.01x - /// @note Page 43-44 - /// @note DDR4 SPD Document Release 3 - /// @warning If tRRD_Lmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tRRD_Lmin (SPD byte 118) - /// used for correction to get the actual value. /// - virtual fapi2::ReturnCode min_trrd_l( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_trrd_l( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TRRD_L_MIN, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group /// @param[out] o_value tCCD_Lmin MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 40 - /// @note Item JC-45-2220.01x - /// @note Page 44-45 - /// @note DDR4 SPD Document Release 3 - /// @warning If tCCD_Lmin cannot be divided evenly by the MTB, - /// this byte must be rounded up to the next larger - /// integer and the Fine Offset for tCCD_Lmin (SPD byte 117) - /// used for correction to get the actual value. /// - virtual fapi2::ReturnCode min_tccd_l( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_tccd_l( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::TCCD_L_MIN, R>(iv_target, iv_data, o_value)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Minimum Write Recovery Time /// @param[out] o_value tWRmin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode min_twr( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_twr( int64_t& o_value ) const override + { + FAPI_TRY( proxy<R>::min_twr(iv_target, iv_data, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Minimum Write to Read Time - Different Bank Group /// @param[out] o_value tWRT_Smin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode min_twtr_s( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_twtr_s( int64_t& o_value ) const override + { + FAPI_TRY( proxy<R>::min_twtr_s(iv_target, iv_data, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + /// /// @brief Decodes Minimum Write to Read Time - Same Bank Group /// @param[out] o_value tWRT_Lmin in MTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 46 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode min_twtr_l( int64_t& o_value ) const override; + virtual fapi2::ReturnCode min_twtr_l( int64_t& o_value ) const override + { + FAPI_TRY( proxy<R>::min_twtr_l(iv_target, iv_data, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Package Rank Map /// @param[out] o_value vector of package rank maps for SPD bytes 60 - 77 /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 60 - 77 - /// @note JEDEC Standard No. 21-C - /// @note Page 45 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode package_rank_map( std::vector<uint8_t>& o_value ) const override; + virtual fapi2::ReturnCode package_rank_map( std::vector<uint8_t>& o_value ) const override + { + o_value.clear(); + + FAPI_TRY( (sdram_connector_helper<DQ0_31, PKG_RANK_MAP>(o_value)), + "%s Failed to sdram_connector_helper for DQ0_31, PKG_RANK_MAP", spd::c_str(iv_target) ); + + FAPI_TRY( (sdram_connector_helper<DQ32_63, PKG_RANK_MAP>(o_value)), + "%s Failed to sdram_connector_helper for DQ32_63, PKG_RANK_MAP", spd::c_str(iv_target) ); + + FAPI_TRY( (sdram_connector_helper<CB0_7, PKG_RANK_MAP>(o_value)), + "%s Failed to sdram_connector_helper for CB0_7, PKG_RANK_MAP", spd::c_str(iv_target) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Nibble Map /// @param[out] o_value vector of nibble map encoding for SPD bytes 60 - 77 /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 60 - 77 - /// @note JEDEC Standard No. 21-C - /// @note Page 45 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode nibble_map( std::vector<uint8_t>& o_value ) const override; + virtual fapi2::ReturnCode nibble_map( std::vector<uint8_t>& o_value ) const override + { + o_value.clear(); + + FAPI_TRY( (sdram_connector_helper<DQ0_31, NIBBLE_MAP>(o_value)), + "%s Failed to sdram_connector_helper for DQ0_31, NIBBLE_MAP", spd::c_str(iv_target) ); + + FAPI_TRY( (sdram_connector_helper<DQ32_63, NIBBLE_MAP>(o_value)), + "%s Failed to sdram_connector_helper for DQ32_63, NIBBLE_MAP", spd::c_str(iv_target) ); + + FAPI_TRY( (sdram_connector_helper<CB0_7, NIBBLE_MAP>(o_value)), + "%s Failed to sdram_connector_helper for CB0_7, NIBBLE_MAP", spd::c_str(iv_target) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group /// @param[out] o_value tCCD_Lmin offset in FTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 117 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_offset_min_tccd_l( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_offset_min_tccd_l( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OFFSET_TCCD_L_MIN, R>(iv_target, iv_data, o_value)) ); + o_value = static_cast<int8_t>(o_value); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group /// @param[out] o_value tRRD_Lmin offset in FTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 118 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_offset_min_trrd_l( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_offset_min_trrd_l( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OFFSET_TRRD_L_MIN, R>(iv_target, iv_data, o_value)) ); + o_value = static_cast<int8_t>(o_value); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group /// @param[out] o_value tRRD_Smin offset in FTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 119 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_offset_min_trrd_s( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_offset_min_trrd_s( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OFFSET_TRRD_S_MIN, R>(iv_target, iv_data, o_value)) ); + o_value = static_cast<int8_t>(o_value); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time /// @param[out] o_value tRCmin offset in FTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 120 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_offset_min_trc( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_offset_min_trc( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OFFSET_TRC_MIN, R>(iv_target, iv_data, o_value)) ); + o_value = static_cast<int8_t>(o_value); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time /// @param[out] o_value tRPmin offset in FTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 121 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_offset_min_trp( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_offset_min_trp( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OFFSET_TRP_MIN, R>(iv_target, iv_data, o_value)) ); + o_value = static_cast<int8_t>(o_value); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time /// @param[out] o_value tRCDmin offset in FTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 122 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_offset_min_trcd( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_offset_min_trcd( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OFFSET_TRCD_MIN, R>(iv_target, iv_data, o_value)) ); + o_value = static_cast<int8_t>(o_value); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time /// @param[out] o_value tAAmin offset in FTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 123 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_offset_min_taa( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_offset_min_taa( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OFFSET_TAA_MIN, R>(iv_target, iv_data, o_value)) ); + o_value = static_cast<int8_t>(o_value); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time /// @param[out] o_value tCKmax offset in FTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 124 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_offset_max_tck( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_offset_max_tck( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OFFSET_TCK_MAX, R>(iv_target, iv_data, o_value)) ); + o_value = static_cast<int8_t>(o_value); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time /// @param[out] o_value tCKmin offset in FTB units /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 125 - /// @note Item JC-45-2220.01x - /// @note Page 52 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode fine_offset_min_tck( int64_t& o_value ) const override; + virtual fapi2::ReturnCode fine_offset_min_tck( int64_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::OFFSET_TCK_MIN, R>(iv_target, iv_data, o_value)) ); + o_value = static_cast<int8_t>(o_value); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section /// @param[out] o_value crc value from SPD /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 127 & Byte 126 - /// @note Item JC-45-2220.01x - /// @note Page 53 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode cyclical_redundancy_code( uint16_t& o_value ) const override; + virtual fapi2::ReturnCode cyclical_redundancy_code( uint16_t& o_value ) const override + { + uint8_t l_crc_msb = 0; + uint8_t l_crc_lsb = 0; + FAPI_TRY( (mss::spd::reader<fields_t::CRC_MSB, R>(iv_target, iv_data, l_crc_msb)) ); + FAPI_TRY( (mss::spd::reader<fields_t::CRC_LSB, R>(iv_target, iv_data, l_crc_lsb)) ); + + { + // Combining bits to create timing value (in a buffer) + fapi2::buffer<uint16_t> l_buffer; + rightAlignedInsert(l_buffer, l_crc_msb, l_crc_lsb); + + // This value isn't bounded in the SPD document + o_value = l_buffer; + + FAPI_INF("%s. Cyclical Redundancy Code (CRC): %d", + spd::c_str(iv_target), + o_value); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes module manufacturer ID code /// @param[out] o_output module manufacturing id code /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 320 (bit 7~0), 321 (6~0) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12 - 54 - /// - virtual fapi2::ReturnCode module_manufacturer_id_code( uint16_t& o_value ) const override; - /// - /// @brief Decodes Module Manufacturing Location - /// @param[out] o_value uint8_t identifier for manufacturing location of memory module - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 322 - /// @note Item JC-45-2220.01x - /// @note Page 55 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode module_manufacturing_location( uint8_t& o_value ) const override; - /// - /// @brief Decodesmodule manufacturing date - /// @param[out] o_output the 2 byte date of manufacturing in BCD format - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 323 & 324 - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 54 - /// @note in Binary Coded Decimal (BCD) - /// @note MSB = year, LSB = week - /// - virtual fapi2::ReturnCode module_manufacturing_date( uint16_t& o_output ) const override; + virtual fapi2::ReturnCode module_manufacturer_id_code( uint16_t& o_value ) const override + { + uint8_t l_cont_codes = 0; + uint8_t l_last_nonzero_byte = 0; - /// - /// @brief Decodes module's unique serial number - /// @param[out] o_output - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 325-328 - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 54 - /// - virtual fapi2::ReturnCode module_serial_number( uint32_t& o_output ) const override; + FAPI_TRY( (mss::spd::reader<fields_t::CONTINUATION_CODES, R>(iv_target, iv_data, l_cont_codes)) ); + FAPI_TRY( (mss::spd::reader<fields_t::LAST_NON_ZERO_BYTE, R>(iv_target, iv_data, l_last_nonzero_byte)) ); - /// - /// @brief Decodes Module Revision Code - /// @param[out] o_value uint8_t identifier for revision code - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 349 - /// @note Item JC-45-2220.01x - /// @note Page 55 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode module_revision_code( uint8_t& o_value ) const override; + { + fapi2::buffer<uint16_t> l_buffer; + rightAlignedInsert(l_buffer, l_last_nonzero_byte, l_cont_codes); - /// - /// @brief Decodes DRAM Manufacturer ID code - /// @param[out] o_output dram manufacturing id code - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 350 - 351 - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 54 - /// - virtual fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_output ) const override; + o_value = l_buffer; - /// - /// @brief Decodes RCD Manufacturer ID code - /// @param[out] o_value rcd manufacturing id code - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 133 134 - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 54 - /// - virtual fapi2::ReturnCode reg_manufacturer_id_code( uint16_t& o_value ) const override; + FAPI_INF("%s.Module Manufacturer ID Code: %x", + spd::c_str(iv_target), + o_value); + } - /// - /// @brief Decodes Register Revision Number - /// @param[out] o_value register revision number - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 135 - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 54 - /// - virtual fapi2::ReturnCode register_rev_num( uint8_t& o_value ) const override; + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief Decodes DRAM Stepping - /// @param[out] o_value uint8_t DRAM Stepping val + /// @brief Decodes Module Manufacturing Location + /// @param[out] o_value uint8_t identifier for manufacturing location of memory module /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 352 - /// @note Item JC-45-2220.01x - /// @note Page 56 - /// @note DDR4 SPD Document Release 3 - /// @note also called die revision level - /// - virtual fapi2::ReturnCode dram_stepping( uint8_t& o_value ) const override; - - /// - /// @brief Returns Logical ranks per DIMM - /// @param[out] o_logical_ranks number of logical ranks - /// @return fapi2::FAPI2_RC_SUCCESS iff okay /// - virtual fapi2::ReturnCode logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const override; + virtual fapi2::ReturnCode module_manufacturing_location( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_MFG_LOCATION, R>(iv_target, iv_data, o_value)) ); - private: + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief SPD byte field threshold check - /// @param[out] o_value list of connector_field values from SPD + /// @brief Decodesmodule manufacturing date + /// @param[out] o_value the 2 byte date of manufacturing in BCD format /// @return FAPI2_RC_SUCCESS iff okay - /// - template< mss::connector_bits T, mss::connector_field OT, typename TT = mss::connectorTraits<T, OT> > - fapi2::ReturnCode sdram_connector_helper( std::vector<uint8_t>& o_value ) const + virtual fapi2::ReturnCode module_manufacturing_date( uint16_t& o_value ) const override { - for( size_t byte = TT::START; byte <= TT::END; ++byte ) - { - uint8_t l_field = 0; + uint8_t l_date_msb = 0; + uint8_t l_date_lsb = 0; - fapi2::buffer<uint8_t> l_buffer(iv_spd_data[byte]); - l_buffer.extractToRight<TT::EXTRACT_START, TT::EXTRACT_LEN>(l_field); + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_MFG_DATE_MSB, R>(iv_target, iv_data, l_date_msb)) ); + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_MFG_DATE_LSB, R>(iv_target, iv_data, l_date_lsb)) ); - FAPI_DBG("%s SPD byte %d, data: %d, field value: %d, starting bit: %d, bit length: %d", - iv_target_str_storage, byte, iv_spd_data[byte], l_field, TT::EXTRACT_START, TT::EXTRACT_LEN); + { + fapi2::buffer<uint16_t> l_buffer; + rightAlignedInsert(l_buffer, l_date_msb, l_date_lsb); - FAPI_TRY( TT::fail_check(iv_target, byte, l_field) ); + o_value = l_buffer; - o_value.push_back(l_field); + FAPI_INF("%s.Module Manufacturer ID date: %x", + spd::c_str(iv_target), + o_value); } fapi_try_exit: return fapi2::current_err; } -};// decoder - -/// -/// @class decoder_v1_1 -/// @brief Base SPD DRAM decoder, 1st addition to general section -/// -class decoder_v1_1 : public decoder_v1_0 -{ - protected: - - /// - /// @brief Helper functions that returns Logical ranks in Secondary SDRAM type - /// @param[out] o_logical_ranks number of logical ranks - /// @return fapi2::FAPI2_RC_SUCCESS iff okay /// - virtual fapi2::ReturnCode sec_sdram_logical_ranks( uint8_t& o_logical_ranks ) const; - - public: - /// - /// @brief Default constructor + /// @brief Decodes module's unique serial number + /// @param[out] o_value module's serial number + /// @return FAPI2_RC_SUCCESS iff okay /// - decoder_v1_1() = default; + virtual fapi2::ReturnCode module_serial_number( uint32_t& o_value ) const override + { + uint8_t l_sn_byte_0 = 0; + uint8_t l_sn_byte_1 = 0; + uint8_t l_sn_byte_2 = 0; + uint8_t l_sn_byte_3 = 0; - /// - /// @brief ctor - /// @param[in] i_target dimm target - /// @param[in] i_spd_data SPD data vector - /// @param[in] i_module_decoder shared_ptr to dimm module decoder - /// @param[in] i_raw_card raw pointer to rcd data - /// - decoder_v1_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - const std::shared_ptr<dimm_module_decoder>& i_module_decoder, - const rcw_settings& i_raw_card); + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_SERIAL_NUM_BYTE1, R>(iv_target, iv_data, l_sn_byte_0)) ); + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_SERIAL_NUM_BYTE2, R>(iv_target, iv_data, l_sn_byte_1)) ); + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_SERIAL_NUM_BYTE3, R>(iv_target, iv_data, l_sn_byte_2)) ); + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_SERIAL_NUM_BYTE4, R>(iv_target, iv_data, l_sn_byte_3)) ); - /// - /// @brief Default dtor - /// - virtual ~decoder_v1_1() = default; + { + fapi2::buffer<uint32_t> l_buffer; + rightAlignedInsert(l_buffer, l_sn_byte_3, l_sn_byte_2, l_sn_byte_1, l_sn_byte_0); - ///////////////////////// - // Member Methods - ///////////////////////// + o_value = l_buffer; - /// - /// @brief Decodes SDRAM density from SPD - /// @param[out] o_value SDRAM density in GBs - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 4 (bits 3~0) - /// @note Item JC-45-2220.01x - /// @note Page 18 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode sdram_density( uint8_t& o_value ) const override; - - /// - /// @brief Decode Soft post package repair (soft PPR) - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 9 (bit 5) - /// @note Item JC-45-2220.01x - /// @note Page 21 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode soft_post_package_repair( uint8_t& o_value ) const override; + FAPI_INF("%s.Module Serial Number : 0x%08x", + spd::c_str(iv_target), + o_value); + } - /// - /// @brief Decodes Secondary SDRAM signal loading - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 10 (bits 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode sec_sdram_signal_loading( uint8_t& o_value ) const override; + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief Decodes Secondary DRAM Density Ratio + /// @brief Decodes Module Revision Code + /// @param[out] o_value uint8_t identifier for revision code /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 10 (bits 3~2) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode sec_dram_density_ratio( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode module_revision_code( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_REV_CODE, R>(iv_target, iv_data, o_value)) ); - /// - /// @brief Decodes Secondary SDRAM die count - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 10 (bits 6~4) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode sec_sdram_die_count( uint8_t& o_value ) const override; + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief Decodes Secondary SDRAM package type + /// @brief Decodes DRAM Manufacturer ID code + /// @param[out] o_value dram manufacturing id code /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 10 (bit 7) - /// @note Item JC-45-2220.01x - /// @note Page 22 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode sec_sdram_package_type( uint8_t& o_value ) const override; + virtual fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_value ) const override + { + uint8_t l_mfgid_msb = 0; + uint8_t l_mfgid_lsb = 0; - /// - /// @brief Decodes number of package ranks per DIMM - /// @param[out] o_value number of package ranks per DIMM - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 12 (bits 5~3) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode num_package_ranks_per_dimm( uint8_t& o_value ) const override; + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_MFR_ID_CODE_LSB, R>(iv_target, iv_data, l_mfgid_lsb)) ); + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_MFR_ID_CODE_MSB, R>(iv_target, iv_data, l_mfgid_msb)) ); - /// - /// @brief Decodes Rank Mix - /// @param[out] o_value rank mix value from SPD - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 12 (bit 6) - /// @note Item JC-45-2220.01x - /// @note Page 23 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode rank_mix( uint8_t& o_value ) const override; + { + fapi2::buffer<uint16_t> l_buffer; + rightAlignedInsert(l_buffer, l_mfgid_msb, l_mfgid_lsb); - /// - /// @brief Decode CAS Latencies Supported - /// @param[out] o_value bitmap of supported CAS latencies - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Bytes 20-23 - /// @note Item JC-45-2220.01x - /// @note Page 33-34 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode supported_cas_latencies( uint64_t& o_value) const override; + o_value = l_buffer; - /// - /// @brief Decodes Minimum Write Recovery Time - /// @param[out] o_value tWRmin in MTB units - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_twr( int64_t& o_value ) const override; + FAPI_INF("%s.DRAM Manufacturer ID Code: %x", + spd::c_str(iv_target), + o_value); + } - /// - /// @brief Decodes Minimum Write to Read Time - Different Bank Group - /// @param[out] o_value tWRT_Smin in MTB units - /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 40 - /// @note DDR4 SPD Document Release 3 - /// - virtual fapi2::ReturnCode min_twtr_s( int64_t& o_value ) const override; + fapi_try_exit: + return fapi2::current_err; + } /// - /// @brief Decodes Minimum Write to Read Time - Same Bank Group - /// @param[out] o_value tWRT_Lmin in MTB units + /// @brief Decodes DRAM Stepping + /// @param[out] o_value uint8_t DRAM Stepping val /// @return FAPI2_RC_SUCCESS iff okay - /// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) - /// @note Item JC-45-2220.01x - /// @note Page 46 - /// @note DDR4 SPD Document Release 3 /// - virtual fapi2::ReturnCode min_twtr_l( int64_t& o_value ) const override; + virtual fapi2::ReturnCode dram_stepping( uint8_t& o_value ) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_STEPPING, R>(iv_target, iv_data, o_value)) ); - /// - /// @brief Returns Logical ranks per DIMM - /// @param[out] o_logical_ranks number of logical ranks - /// @return fapi2::FAPI2_RC_SUCCESS iff okay - /// - virtual fapi2::ReturnCode logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const override; + fapi_try_exit: + return fapi2::current_err; + } -};// spd_decoder_v1_1 +};// decoder -}// ddr4 }// spd }// mss diff --git a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C deleted file mode 100644 index fa47e5384..000000000 --- a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C +++ /dev/null @@ -1,3021 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2018 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -/// -/// @file spd_decoder.C -/// @brief SPD decoder definitions -/// -// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> -// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> -// *HWP Team: Memory -// *HWP Level: 3 -// *HWP Consumed by: HB:FSP - -// std lib -#include <map> -#include <vector> - -// fapi2 -#include <fapi2.H> - -// mss lib -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H> -#include <generic/memory/lib/spd/common/rcw_settings.H> -#include <generic/memory/lib/utils/c_str.H> -#include <generic/memory/lib/utils/find.H> -#include <generic/memory/lib/utils/mss_math.H> - -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_MCS; -using fapi2::TARGET_TYPE_DIMM; - -namespace mss -{ -namespace spd -{ -namespace ddr4 -{ - -///////////////////////// -// Member Method implementation -///////////////////////// - -/// -/// @brief ctor -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data vector -/// @param[in] i_module_decoder shared_ptr to dimm module decoder -/// @param[in] i_raw_card raw card data structure -/// -decoder_v1_0::decoder_v1_0(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - const std::shared_ptr<dimm_module_decoder>& i_module_decoder, - const rcw_settings& i_raw_card) - : decoder(i_target, i_spd_data, i_module_decoder, i_raw_card) -{} - -/// -/// @brief Decodes number of used SPD bytes -/// @param[out] o_value number of SPD bytes used -/// @return FAPI2_RC_SUCCESS iff okay -/// @note Decodes SPD Byte 0 bits(0~3) -/// @note Item JC-45-2220.01x -/// @note Page 14 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::number_of_used_bytes( uint16_t& o_value ) const -{ - // ========================================================= - // Byte 0 maps - // Item JC-45-2220.01x - // Page 14 - // DDR4 SPD Document Release 3 - // Byte 0 (0x000): Number of Bytes Used / Number of Bytes in SPD Device - // ========================================================= - static const std::vector<std::pair<uint8_t, uint16_t> > BYTES_USED_MAP = - { - //{key byte, number of used bytes} - {1, 128}, - {2, 256}, - {3, 384}, - {4, 512} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< BYTES_USED >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(BYTES_USED_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - BYTES_USED.iv_byte, - l_field_bits, - "Failed check on SPD used bytes") ); - - FAPI_INF("%s. Bytes Used: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes total number of SPD bytes -/// @param[out] o_value number of total SPD bytes -/// @return FAPI2_RC_SUCCESS iff okay -/// @note Decodes SPD Byte 0 (bits 4~6) -/// @note Item JC-45-2220.01x -/// @note Page 14 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::number_of_total_bytes( uint16_t& o_value ) const -{ - - // ========================================================= - // Byte 0 maps - // Item JC-45-2220.01x - // Page 14 - // DDR4 SPD Document Release 3 - // Byte 0 (0x000): Number of Bytes Used / Number of Bytes in SPD Device - // ========================================================= - static const std::vector<std::pair<uint8_t, uint16_t> > BYTES_TOTAL_MAP = - { - //{key byte, number of total bytes} - {1, 256}, - {2, 512} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< TOTAL_BYTES_USED >(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(BYTES_TOTAL_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - TOTAL_BYTES_USED.iv_byte, - l_field_bits, - "Failed check on SPD total bytes") ); - - FAPI_INF("%s. Total Bytes: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM density from SPD -/// @param[out] o_value SDRAM density in GBs -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 4 (bits 0~3) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::sdram_density( uint8_t& o_value) const -{ - // ========================================================= - // Byte 4 maps - // Item JC-45-2220.01x - // Page 18 - // DDR4 SPD Document Release 3 - // Byte 4 (0x004): SDRAM Density and Banks - // ========================================================= - static const std::vector< std::pair<uint8_t, uint8_t> > SDRAM_DENSITY_MAP = - { - // {key byte, capacity in GBs} - {2, 1}, - {3, 2}, - {4, 4}, - {5, 8}, - {6, 16}, - {7, 32}, - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< SDRAM_CAPACITY >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - const bool l_is_val_found = mss::find_value_from_key(SDRAM_DENSITY_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - SDRAM_CAPACITY.iv_byte, - l_field_bits, - "Failed check for SPD DRAM capacity") ); - - FAPI_INF("%s. SDRAM density: %d Gb", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of SDRAM bank_bits from SPD -/// @param[out] o_value Number of SDRAM bank bits -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 4 (bits 5~4) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::bank_bits( uint8_t& o_value) const - -{ - // ========================================================= - // Byte 4 maps - // Item JC-45-2220.01x - // Page 18 - // DDR4 SPD Document Release 3 - // Byte 4 (0x004): SDRAM Density and Banks - // ========================================================= - static const std::vector< std::pair<uint8_t, uint8_t> > BANK_ADDR_BITS_MAP = - { - // {key byte, number of bank address bits} - {0, 2}, - {1, 3} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< SDRAM_BANKS >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - const bool l_is_val_found = mss::find_value_from_key(BANK_ADDR_BITS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - SDRAM_BANKS.iv_byte, - l_field_bits, - "Failed check for SPD DRAM banks") ); - - FAPI_INF("%s. Number of banks address bits: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of SDRAM bank group bits from SPD -/// @param[out] o_value Number of SDRAM bank group bits -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 4 (bits 6~7) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::bank_group_bits( uint8_t& o_value) const -{ - // ========================================================= - // Byte 4 maps - // Item JC-45-2220.01x - // Page 18 - // DDR4 SPD Document Release 3 - // Byte 4 (0x004): SDRAM Density and Banks - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > BANK_GROUP_BITS_MAP = - { - // {key byte, number of bank groups bits} - {0, 0}, - {1, 1}, - {2, 2} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< BANK_GROUP >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - const bool l_is_val_found = mss::find_value_from_key(BANK_GROUP_BITS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - BANK_GROUP.iv_byte, - l_field_bits, - "Failed check for SPD DRAM bank groups") ); - - FAPI_INF("%s. Number of bank group bits: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of SDRAM column address bits -/// @param[out] o_value number of column address bits -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 5 (bits 2~0) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::column_address_bits( uint8_t& o_value) const -{ - // ========================================================= - // Byte 5 maps - // Item JC-45-2220.01x - // Page 18 - // DDR4 SPD Document Release 3 - // Byte 5 (0x005): SDRAM Addressing - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > COLUMN_ADDRESS_BITS_MAP = - { - //{key byte,col address bits} - {0, 9}, - {1, 10}, - {2, 11}, - {3, 12} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< COL_ADDRESS >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - const bool l_is_val_found = mss::find_value_from_key(COLUMN_ADDRESS_BITS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - COL_ADDRESS.iv_byte, - l_field_bits, - "Failed check for SDRAM Column Address Bits") ); - - FAPI_INF("%s. Number of Column Address Bits: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of SDRAM row address bits -/// @param[out] o_value number of row address bits -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 5 (bits 5~3) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::row_address_bits( uint8_t& o_value) const -{ - // ========================================================= - // Byte 5 maps - // Item JC-45-2220.01x - // Page 18 - // DDR4 SPD Document Release 3 - // Byte 5 (0x005): SDRAM Addressing - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > ROW_ADDRESS_BITS_MAP = - { - //{key byte,row address bits} - {0, 12}, - {1, 13}, - {2, 14}, - {3, 15}, - {4, 16}, - {5, 17}, - {6, 18} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< ROW_ADDRESS >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - const bool l_is_val_found = mss::find_value_from_key(ROW_ADDRESS_BITS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target, - l_is_val_found, - ROW_ADDRESS.iv_byte, - l_field_bits, - "Failed check for SDRAM Row Address Bits") ); - - FAPI_INF("%s. Number of Row Address Bits: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes Primary SDRAM signal loading -/// @param[out] o_value enum representing signal loading type -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 6 (bits 1~0) -/// @note Item JC-45-2220.01x -/// @note Page 19 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::prim_sdram_signal_loading( uint8_t& o_value) const -{ - // ========================================================= - // Byte 6 maps - // Item JC-45-2220.01x - // Page 19 - // DDR4 SPD Document Release 3 - // Byte 6 (0x006): Primary SDRAM Package Type - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_SIGNAL_LOADING_MAP = - { - // {key byte, signal loading} - {0, fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_SDP}, - {1, fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_DDP_QDP}, - {2, fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< PRIM_SIGNAL_LOADING >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(PRIM_SIGNAL_LOADING_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target, - l_is_val_found, - PRIM_SIGNAL_LOADING.iv_byte, - l_field_bits, - "Failed check for Primary SDRAM Signal Loading") ); - - FAPI_INF("%s. Primary SDRAM Signal Loading: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Primary SDRAM die count -/// @param[out] o_value die count -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 6 (bits 6~4) -/// @note Item JC-45-2220.01x -/// @note Page 19 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::prim_sdram_die_count( uint8_t& o_value) const -{ - // ========================================================= - // Byte 6 maps - // Item JC-45-2220.01x - // Page 19 - // DDR4 SPD Document Release 3 - // Byte 6 (0x006): Primary SDRAM Package Type - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_DIE_COUNT_MAP = - { - // {key byte, number of die} - {0, 1}, - {1, 2}, - {2, 3}, - {3, 4}, - {4, 5}, - {5, 6}, - {6, 7}, - {7, 8} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< PRIM_DIE_COUNT >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(PRIM_DIE_COUNT_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target, - l_is_val_found, - PRIM_DIE_COUNT.iv_byte, - l_field_bits, - "Failed check for SDRAM Row Address Bits") ); - - FAPI_INF("%s. Number of Row Address Bits: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Primary SDRAM package type -/// @param[out] o_value enum representing package type -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 6 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 19 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::prim_sdram_package_type( uint8_t& o_value) const -{ - // ========================================================= - // Byte 6 maps - // Item JC-45-2220.01x - // Page 19 - // DDR4 SPD Document Release 3 - // Byte 6 (0x006): Primary SDRAM Package Type - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_PACKAGE_TYPE_MAP = - { - // {key byte, value} - {0, MONOLITHIC}, - {1, NON_MONOLITHIC} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< PRIM_PACKAGE_TYPE >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(PRIM_PACKAGE_TYPE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - PRIM_PACKAGE_TYPE.iv_byte, - l_field_bits, - "Failed check for Primary SDRAM package type") ); - - FAPI_INF("%s. Primary SDRAM package type: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decode SDRAM Maximum activate count -/// @param[out] o_value enum representing max activate count -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 7 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 20 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::maximum_activate_count( uint32_t& o_value ) const -{ - // ========================================================= - // Byte 7 maps - // Item JC-45-2220.01x - // Page 20 - // DDR4 SPD Document Release 3 - // Byte 7 (0x007): SDRAM Optional Features - // ========================================================= - static const std::vector<std::pair<uint8_t, uint32_t> > MAC_MAP = - { - // {key byte, maximum activate count} - {0, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNTESTED}, - {1, fapi2::ENUM_ATTR_EFF_DRAM_MAC_700K}, - {2, fapi2::ENUM_ATTR_EFF_DRAM_MAC_600K}, - {3, fapi2::ENUM_ATTR_EFF_DRAM_MAC_500K}, - {4, fapi2::ENUM_ATTR_EFF_DRAM_MAC_400K}, - {5, fapi2::ENUM_ATTR_EFF_DRAM_MAC_300K}, - {6, fapi2::ENUM_ATTR_EFF_DRAM_MAC_200K}, - {8, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNLIMITED} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< MAC >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(MAC_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - MAC.iv_byte, - l_field_bits, - "Failed check for SDRAM Maximum Active Count (MAC)") ); - - FAPI_INF("%s. Maximum Active Count (MAC): %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point -/// @param[out] o_value max activate window multiplier -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 7 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 20 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::maximum_activate_window_multiplier( uint32_t& o_value ) const -{ - // ========================================================= - // Byte 7 maps - // Item JC-45-2220.01x - // Page 20 - // DDR4 SPD Document Release 3 - // Byte 7 (0x007): SDRAM Optional Features - // ========================================================= - // Multiplier with tREFI is not taken into account here - static const std::vector<std::pair<uint8_t, uint32_t> > TMAW_MAP = - { - // {key byte, tMAW multiplier} - {0, 8192}, - {1, 4096}, - {2, 2048} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< TMAW >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(TMAW_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - TMAW.iv_byte, - l_field_bits, - "Failed check for Maximum Active Window (tMAW)") ); - - FAPI_INF("%s. Maximum Active Window multiplier: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Post package repair (PPR) -/// @param[out] o_value enum representing if (hard) PPR is supported -/// @return fapi2::ReturnCode -/// @note SPD Byte 9 (bits 7~6) -/// @note Item JC-45-2220.01x -/// @note Page 21 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::post_package_repair( uint8_t& o_value) const -{ - // ========================================================= - // Byte 9 maps - // Item JC-45-2220.01x - // Page 21 - // DDR4 SPD Document Release 3 - // Byte 9 (0x009): Other SDRAM Optional Features - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > PPR_MAP = - { - // {key byte, value } - {0, fapi2::ENUM_ATTR_EFF_DRAM_PPR_NOT_SUPPORTED}, - {1, fapi2::ENUM_ATTR_EFF_DRAM_PPR_SUPPORTED} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< PPR >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(PPR_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - PPR.iv_byte, - l_field_bits, - "Failed check for PPR") ); - - FAPI_INF("%s. Post Package Repair (PPR): %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Secondary SDRAM signal loading -/// @param[out] o_value enum representing signal loading type -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 10 (bits 1~0) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::sec_sdram_signal_loading( uint8_t& o_value) const -{ - // For General Section rev 1.0 of the SPD, - // SPD Byte 10 (bits 1~0) were reserved - // and coded as zeros. There was no concept of - // secondary SDRAM signal loading so this - // is thus hard-wired to zero. - o_value = 0x00; - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decode Soft post package repair (soft PPR) -/// @param[out] o_value enum representing if soft PPR is supported -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 9 (bit 5) -/// @note Item JC-45-2220.01x -/// @note Page 21 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::soft_post_package_repair( uint8_t& o_value) const -{ - // For General Section rev 1.0 of the SPD, - // SPD Byte 9 (bit 5) was reserved - // and coded as zeros. There was no concept of soft PPR so this - // is thus hard-wired to zero. - o_value = 0x00; - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes Secondary DRAM Density Ratio -/// @param[out] o_value raw bits from SPD -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 10 (bits 3~2) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::sec_dram_density_ratio( uint8_t& o_value) const -{ - // For General Section rev 1.0 of the SPD, - // SPD Byte 10 (bits 3~2) were reserved - // and coded as zeros. There was no concept of - // secondary SDRAM density ratio so this - // is thus hard-wired to zero. - o_value = 0x00; - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes Secondary SDRAM die count -/// @param[out] o_value die count -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 10 (bits 6~4) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::sec_sdram_die_count( uint8_t& o_value) const -{ - // For General Section rev 1.0 of the SPD, - // SPD Byte 10 (bits 6~4) were reserved - // and coded as zeros. There was no concept of - // secondary SDRAM hybrid media so this - // is thus hard-wired to zero. - o_value = 0x00; - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes Secondary SDRAM package type -/// @param[out] o_value enum representing package type -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 10 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::sec_sdram_package_type( uint8_t& o_value) const -{ - // For General Section rev 1.0 of the SPD, - // SPD Byte 10 (bit 7) was reserved - // and coded as zeros. There was no concept of - // secondary SDRAM package type so this - // is thus hard-wired to zero. - o_value = 0x00; - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decode Module Nominal Voltage, VDD -/// @param[out] o_value enum representing if 1.2V is operable -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 11 (bit 0) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::operable_nominal_voltage( uint8_t& o_value) const -{ - // ========================================================= - // Byte 11 maps - // Item JC-45-2220.01x - // Page 22-23 - // DDR4 SPD Document Release 3 - // Byte 11 (0x00B): Modle Nominal Voltage - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > OPERABLE_MAP = - { - // {key byte, value } - {0, NOT_OPERABLE }, - {1, OPERABLE} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< OPERABLE_FLD >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(OPERABLE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - OPERABLE_FLD.iv_byte, - l_field_bits, - "Failed check for Operable nominal voltage") ); - - FAPI_INF("%s. Operable: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Module Nominal Voltage, VDD -/// @param[out] o_value enum representing if 1.2V is endurant -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 11 (bit 1) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::endurant_nominal_voltage( uint8_t& o_value) const -{ - // ========================================================= - // Byte 11 maps - // Item JC-45-2220.01x - // Page 22-23 - // DDR4 SPD Document Release 3 - // Byte 11 (0x00B): Modle Nominal Voltage - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > ENDURANT_MAP = - { - // {key byte, value } - {0, NOT_ENDURANT}, - {1, ENDURANT} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< ENDURANT_FLD >(iv_target, iv_spd_data); - - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(ENDURANT_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - ENDURANT_FLD.iv_byte, - l_field_bits, - "Failed check for Endurant nominal voltage") ); - - FAPI_INF("%s. Endurant: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM device width -/// @param[out] o_value device width in bits -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 12 (bits 2~0) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::device_width( uint8_t& o_value) const -{ - // ========================================================= - // Byte 12 maps - // Item JC-45-2220.01x - // Page 23 - // DDR4 SPD Document Release 3 - // Byte 12 (0x00C): Module Organization - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > DEVICE_WIDTH_MAP = - { - // {key byte, device width (bits)} - {0, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4}, - {1, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8}, - {2, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16}, - {3, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X32}, - // All others reserved - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< SDRAM_WIDTH >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(DEVICE_WIDTH_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - SDRAM_WIDTH.iv_byte, - l_field_bits, - "Failed check for Device Width") ); - - FAPI_INF("%s. Device Width: %d bits", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes number of package ranks per DIMM -/// @param[out] o_value number of package ranks per DIMM -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 12 (bits 5~3) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::num_package_ranks_per_dimm( uint8_t& o_value) const -{ - // ========================================================= - // Byte 12 maps - // Item JC-45-2220.01x - // Page 23 - // DDR4 SPD Document Release 3 - // Byte 12 (0x00C): Module Organization - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > NUM_PACKAGE_RANKS_MAP = - { - // {key byte, num of package ranks per DIMM (package ranks)} - {0, 1}, - {1, 2}, - {2, 3}, - {3, 4}, - {4, 5}, - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< PACKAGE_RANKS >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(NUM_PACKAGE_RANKS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - PACKAGE_RANKS.iv_byte, - l_field_bits, - "Failed check for Num Package Ranks Per DIMM") ); - - FAPI_INF("%s. Num Package Ranks per DIMM: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Rank Mix -/// @param[out] o_value rank mix value from SPD -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 12 (bit 6) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::rank_mix( uint8_t& o_value) const -{ - // For General Section rev 1.0 of the SPD, - // Decodes SPD Byte 3 (bits 4~6) were reserved - // and coded as zeros. There was no concept of rank_mix so this - // is thus hard-wired to zero. - o_value = 0x00; - return fapi2::FAPI2_RC_SUCCESS; - -} - -/// -/// @brief Decodes primary bus width -/// @param[out] o_value primary bus width in bits -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 13 (bits 2~0) -/// @note Item JC-45-2220.01x -/// @note Page 27 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::prim_bus_width( uint8_t& o_value) const -{ - // ========================================================= - // Byte 13 maps - // Item JC-45-2220.01x - // Page 27 - // DDR4 SPD Document Release 3 - // Byte 13 (0x00D): Module Memory Bus Width - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_MAP = - { - // {key byte, bus width (in bits) - {0, 8}, - {1, 16}, - {2, 32}, - {3, 64} - // All others reserved - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< BUS_WIDTH >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(BUS_WIDTH_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - BUS_WIDTH.iv_byte, - l_field_bits, - "Failed check for Primary Bus Width") ); - - FAPI_INF("%s. Primary Bus Width: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes bus width extension -/// @param[out] o_value bus width extension in bits -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 13 (bits 2~0) -/// @note Item JC-45-2220.01x -/// @note Page 28 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::bus_width_extension( uint8_t& o_value) const -{ - // ========================================================= - // Byte 13 maps - // Item JC-45-2220.01x - // Page 27 - // DDR4 SPD Document Release 3 - // Byte 13 (0x00D): Module Memory Bus Width - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_EXT_MAP = - { - {0, 0}, - {1, 8} - // All others reserved - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< BUS_EXT_WIDTH >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(BUS_WIDTH_EXT_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - BUS_EXT_WIDTH.iv_byte, - l_field_bits, - "Failed check for Bus Width Extension") ); - - FAPI_INF("%s. Bus Width Extension (bits): %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decode Module Thermal Sensor -/// @param[out] o_value thermal sensor value from SPD -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 14 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 28 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::thermal_sensor( uint8_t& o_value) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< THERM_SENSOR >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check for valid value - constexpr size_t INVALID_VALUE = 2; // single bit value 0 or 1 - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < INVALID_VALUE, - THERM_SENSOR.iv_byte, - l_field_bits, - "Failed check for Thermal Sensor") ); - - // Update output after check passes - o_value = l_field_bits; - - FAPI_INF("%s. Thermal Sensor: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Extended Base Module Type -/// @param[out] o_value raw data from SPD -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 15 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 28 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::extended_base_module_type( uint8_t& o_value) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< EXTENDED_MODULE_TYPE >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check for valid value - // Currently reserved to 0b000 - constexpr size_t RESERVED = 0; - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits == RESERVED, - EXTENDED_MODULE_TYPE.iv_byte, - l_field_bits, - "Failed check for Extended Base Module Type") ); - - // Update output for check passes - o_value = l_field_bits; - - FAPI_INF("%s. Extended Base Module Type: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decode Fine Timebase -/// @param[out] o_value fine_timebase from SPD in picoseconds -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 17 (bits 1~0) -/// @note Item JC-45-2220.01x -/// @note Page 29 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_timebase( int64_t& o_value) const -{ - // ========================================================= - // Byte 17 maps - // Item JC-45-2220.01x - // Page 29 - // DDR4 SPD Document Release 3 - // Byte 17 (0x011): Timebases - // ========================================================= - // Created a maps of a single value in case mapping expands to more values - static const std::vector<std::pair<uint8_t, int64_t> > FINE_TIMEBASE_MAP = - { - // {key byte, fine timebase (in picoseconds) - {0, 1} - // All others reserved - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< FINE_TIMEBASE >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(FINE_TIMEBASE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - FINE_TIMEBASE.iv_byte, - l_field_bits, - "Failed check for Fine Timebase") ); - - FAPI_INF("%s. Fine Timebase: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Medium Timebase -/// @param[out] o_value medium timebase from SPD in picoseconds -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 17 (bits 3~2) -/// @note Item JC-45-2220.01x -/// @note Page 29 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::medium_timebase( int64_t& o_value) const -{ - // ========================================================= - // Byte 17 maps - // Item JC-45-2220.01x - // Page 29 - // DDR4 SPD Document Release 3 - // Byte 17 (0x011): Timebases - // ========================================================= - // Created a maps of a single value in case mapping expands to more values - static const std::vector<std::pair<uint8_t, int64_t> > MEDIUM_TIMEBASE_MAP = - { - // {key byte, medium timebase (in picoseconds) - {0, 125} - // All others reserved - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< MEDIUM_TIMEBASE >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(MEDIUM_TIMEBASE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - MEDIUM_TIMEBASE.iv_byte, - l_field_bits, - "Failed check for Medium Timebase") ); - - FAPI_INF("%s. Medium Timebase: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes SDRAM Minimum Cycle Time in MTB -/// @param[out] o_value tCKmin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 18 -/// @note Item JC-45-2220.01x -/// @note Page 31-32 -/// @note DDR4 SPD Document Release 3 -/// @warning If tCKmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tCKmin (SPD byte 125) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder_v1_0::min_tck( int64_t& o_value ) const -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 18; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: %d.", - iv_target_str_storage, - BYTE_INDEX, - l_timing_val); - - // Check if value is valid - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the min cycle time (tckmin) in MTB") ); - - // Update output after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Cycle Time (tCKmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Maximum Cycle Time in MTB -/// @param[out] o_value tCKmax in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 19 -/// @note Item JC-45-2220.01x -/// @note Page 32 -/// @note DDR4 SPD Document Release 3 -/// @warning If tCKmax cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tCKmax (SPD byte 124) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder_v1_0::max_tck( int64_t& o_value ) const -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 19; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: %d.", - iv_target_str_storage, - BYTE_INDEX, - l_timing_val); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the max cycle time (tckmax) in MTB") ); - - // Update output after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Maximum Cycle Time (tCKmax) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decode CAS Latencies Supported -/// @param[out] o_value bitmap of supported CAS latencies -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Bytes 20-23 -/// @note Item JC-45-2220.01x -/// @note Page 33-34 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::supported_cas_latencies( uint64_t& o_value ) const -{ - // Trace print in the front assists w/ debug - constexpr size_t FIRST_BYTE = 20; - uint8_t first_raw_byte = iv_spd_data[FIRST_BYTE]; - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - FIRST_BYTE, - first_raw_byte); - - constexpr size_t SEC_BYTE = 21; - uint8_t sec_raw_byte = iv_spd_data[SEC_BYTE]; - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - SEC_BYTE, - sec_raw_byte); - - constexpr size_t THIRD_BYTE = 22; - uint8_t third_raw_byte = iv_spd_data[THIRD_BYTE]; - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - THIRD_BYTE, - third_raw_byte); - - constexpr size_t FOURTH_BYTE = 23; - uint8_t fourth_raw_byte = iv_spd_data[FOURTH_BYTE]; - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - FOURTH_BYTE, - fourth_raw_byte); - - // Buffers used for bit manipulation - // Combine Bytes to create bitmap - right aligned - fapi2::buffer<uint64_t> l_buffer; - - l_buffer.insertFromRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(first_raw_byte) - .insertFromRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(sec_raw_byte) - .insertFromRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(third_raw_byte) - .insertFromRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(fourth_raw_byte); - - // According to the JEDEC spec: - // Byte 22 (Bits 7~0) and Byte 23 are reserved and thus not supported - constexpr size_t MAX_VALID_VAL = 0x3FFFF; - - // Check for a valid value - uint64_t l_supported_cl = l_buffer; - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_supported_cl <= MAX_VALID_VAL, - FOURTH_BYTE, - fourth_raw_byte, - "Failed check on CAS latencies supported") ); - - // Update output value only if range check passes - o_value = l_supported_cl; - - FAPI_INF("%s. CAS latencies supported (bitmap): 0x%llX", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes SDRAM Minimum CAS Latency Time in MTB -/// @param[out] o_value tAAmin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 24 -/// @note Item JC-45-2220.01x -/// @note Page 34 -/// @note DDR4 SPD Document Release 3 -/// @warning If tAAmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tAAmin (SPD byte 123) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder_v1_0::min_taa( int64_t& o_value ) const -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 24; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - l_timing_val); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum CAS Latency Time (tAAmin) in MTB") ); - - // Only update output if it passes check - o_value = l_timing_val; - - FAPI_INF("%s. Minimum CAS Latency Time (tAAmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB -/// @param[out] o_value tRCDmin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 25 -/// @note Item JC-45-2220.01x -/// @note Page 35 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRCDmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRCDmin (SPD byte 122) -/// used for correction to get the actual value -/// -fapi2::ReturnCode decoder_v1_0::min_trcd( int64_t& o_value ) const -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 25; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - l_timing_val); - - // Find valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum RAS to CAS Delay Time (tRCDmin) in MTB") ); - - // Only update output if it passes check - o_value = l_timing_val; - - FAPI_INF("%s. Minimum RAS to CAS Delay Time (tRCDmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB -/// @param[out] o_value tRPmin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 26 -/// @note Item JC-45-2220.01x -/// @note Page 36-37 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRPmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRPmin (SPD byte 121) -/// used for correction to get the actual value -/// -fapi2::ReturnCode decoder_v1_0::min_trp( int64_t& o_value ) const -{ - // Explicit conversion - constexpr size_t BYTE_INDEX = 26; - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - l_timing_val); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Row Precharge Delay Time (tRPmin) in MTB") ); - - // Only update output if it passes check - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Row Precharge Delay Time (tRPmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB -/// @param[out] o_value tRASmin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 27 (bits 3~0) & Byte 28 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 38 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::min_tras( int64_t& o_value) const -{ - uint8_t tRASmin_MSN = extract_spd_field< TRASMIN_MSN >(iv_target, iv_spd_data); - FAPI_INF("MSN Field Bits value: %lu", tRASmin_MSN); - - uint8_t tRASmin_LSB = extract_spd_field< TRASMIN_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", tRASmin_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<int64_t> l_buffer; - - l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRASmin_MSN ) - .insertFromRight<LSB_START, LSB_LEN>( tRASmin_LSB ); - - // Extract timing value from the buffer into an integral type - int64_t l_timing_val = l_buffer; - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // But byte 28 of the JEDEC spec explains how to piece this together - AAM - constexpr size_t ERROR_BYTE_INDEX = 28; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Active to Precharge Delay Time (tRASmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Active to Precharge Delay Time (tRASmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB -/// @param[out] o_value tRCmin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 27 (bits 7~4) & SPD Byte 29 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 38 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRCmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRCmin (SPD byte 120) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder_v1_0::min_trc( int64_t& o_value) const -{ - uint8_t tRCmin_MSN = extract_spd_field< TRCMIN_MSN >(iv_target, iv_spd_data); - FAPI_INF("MSN Field Bits value: %lu", tRCmin_MSN); - - uint8_t tRCmin_LSB = extract_spd_field< TRCMIN_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", tRCmin_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<int64_t> l_buffer; - l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRCmin_MSN ) - .insertFromRight<LSB_START, LSB_LEN>( tRCmin_LSB ); - - // Extract timing value from the buffer into an integral type - int64_t l_timing_val = l_buffer; - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // But byte 29 of the JEDEC spec explains how to piece this together - AAM - constexpr size_t ERROR_BYTE_INDEX = 29; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1 -/// @param[out] o_value tRFC1min in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 30 & Byte 31 -/// @note Item JC-45-2220.01x -/// @note Page 39-40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::min_trfc1( int64_t& o_value) const -{ - uint8_t tRFC1min_MSB = extract_spd_field< TRFC1MIN_MSB >(iv_target, iv_spd_data); - FAPI_INF("MSB Field Bits value: %lu", tRFC1min_MSB); - - uint8_t tRFC1min_LSB = extract_spd_field< TRFC1MIN_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", tRFC1min_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSB_START = 48; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<int64_t> l_buffer; - - l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC1min_MSB ) - .insertFromRight<LSB_START, LSB_LEN>( tRFC1min_LSB ); - - // Extract timing value from the buffer into an integral type - int64_t l_timing_val = l_buffer; - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 30) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 30; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2 -/// @param[out] o_value tRFC2min in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 32 & Byte 33 -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::min_trfc2( int64_t& o_value) const -{ - uint8_t tRFC2min_MSB = extract_spd_field< TRFC2MIN_MSB >(iv_target, iv_spd_data); - FAPI_INF("MSB Field Bits value: %lu", tRFC2min_MSB); - - uint8_t tRFC2min_LSB = extract_spd_field< TRFC2MIN_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", tRFC2min_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSB_START = 48; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<int64_t> l_buffer; - - l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC2min_MSB ) - .insertFromRight<LSB_START, LSB_LEN>( tRFC2min_LSB ); - - // Extract timing value from the buffer into an integral type - int64_t l_timing_val = l_buffer; - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 33) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 33; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4 -/// @param[out] o_value tRFC4min in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 34 & Byte 35 -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::min_trfc4( int64_t& o_value) const -{ - uint8_t tRFC4min_MSB = extract_spd_field< TRFC4MIN_MSB >(iv_target, iv_spd_data); - FAPI_INF("MSB Field Bits value: %lu", tRFC4min_MSB); - - uint8_t tRFC4min_LSB = extract_spd_field< TRFC4MIN_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", tRFC4min_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSB_START = 48; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<int64_t> l_buffer; - - l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC4min_MSB ) - .insertFromRight<LSB_START, LSB_LEN>( tRFC4min_LSB ); - - // Extract timing value from the buffer into an integral type - int64_t l_timing_val = l_buffer; - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 34) for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 34; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SDRAM Minimum Four Activate Window Delay Time -/// @param[out] o_value tFAWmin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 36 (bits 3~0) & Byte 37 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 42 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::min_tfaw( int64_t& o_value) const -{ - uint8_t tFAWmin_MSN = extract_spd_field< TFAWMIN_MSN >(iv_target, iv_spd_data); - FAPI_INF("MSN Field Bits value: %lu", tFAWmin_MSN); - - uint8_t tFAWmin_LSB = extract_spd_field< TFAWMIN_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", tFAWmin_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<int64_t> l_buffer; - - l_buffer.insertFromRight<MSN_START, MSN_LEN>( tFAWmin_MSN ). - insertFromRight<LSB_START, LSB_LEN>( tFAWmin_LSB ); - - // Extract timing value from the buffer into an integral type - int64_t l_timing_val = l_buffer; - - // JEDEC spec limits for this timing value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 37) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 37; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Four Activate Window Delay Time (tFAWmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Four Activate Window Delay Time (tFAWmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group -/// @param[out] o_value tRRD_Smin MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 38 -/// @note Item JC-45-2220.01x -/// @note Page 43 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRRD_Smin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRRD_Smin (SPD byte 119) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder_v1_0::min_trrd_s( int64_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 38; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Minimum Activate to Activate Delay Time - Different Bank Group - // explicit conversion to int64_t - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Find valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group -/// @param[out] o_value tRRD_Lmin MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 39 -/// @note Item JC-45-2220.01x -/// @note Page 43-44 -/// @note DDR4 SPD Document Release 3 -/// @warning If tRRD_Lmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tRRD_Lmin (SPD byte 118) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder_v1_0::min_trrd_l( int64_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 39; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Minimum Activate to Activate Delay Time - Same Bank Group - // explicit conversion to int64_t - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Find valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group -/// @param[out] o_value tCCD_Lmin MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 40 -/// @note Item JC-45-2220.01x -/// @note Page 44-45 -/// @note DDR4 SPD Document Release 3 -/// @warning If tCCD_Lmin cannot be divided evenly by the MTB, -/// this byte must be rounded up to the next larger -/// integer and the Fine Offset for tCCD_Lmin (SPD byte 117) -/// used for correction to get the actual value. -/// -fapi2::ReturnCode decoder_v1_0::min_tccd_l( int64_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 40; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Minimum CAS to CAS Delay Time - Same Bank Group - // explicit conversion to int64_t - int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum Write Recovery Time -/// @param[out] o_value tWRmin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::min_twr( int64_t& o_value) const -{ - // For General Section rev 1.0 of the SPD, - // SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) were reserved - // and coded as zeros. - // Default as 0x78 for all DDR4 bins for rev 1.0 - // No value given in 1.0 JEDEC spec and no value in SPD - JLH - // 1.1 Has valid values defined and in SPD, this is taken from there - o_value = 0x78; - return fapi2::FAPI2_RC_SUCCESS; - -} - -/// -/// @brief Decodes Minimum Write to Read Time - Different Bank Group -/// @param[out] o_value tWRT_Smin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::min_twtr_s( int64_t& o_value) const -{ - // For General Section rev 1.0 of the SPD, - // SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) were reserved - // and coded as zeros. - // Default as 0x14 for all DDR4 bins for rev 1.0 - // No value given in 1.0 JEDEC spec and no value in SPD - JLH - // 1.1 Has valid values defined and in SPD, this is taken from there - o_value = 0x14; - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes Minimum Write to Read Time - Same Bank Group -/// @param[out] o_value tWRT_Lmin in MTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 46 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::min_twtr_l( int64_t& o_value) const -{ - // For General Section rev 1.0 of the SPD, - // SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) were reserved - // and coded as zeros. - // Default as 0x3C for all DDR4 bins for rev 1.0 - // No value given in 1.0 JEDEC spec and no value in SPD - JLH - // 1.1 Has valid values defined and in SPD, this is taken from there - o_value = 0x3C; - return fapi2::FAPI2_RC_SUCCESS; - -} - -/// -/// @brief Decodes Package Rank Map -/// @param[out] o_value vector of package rank maps for SPD bytes 60 - 77 -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 60 - 77 -/// @note JEDEC Standard No. 21-C -/// @note Page 45 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::package_rank_map( std::vector<uint8_t>& o_value ) const -{ - o_value.clear(); - - FAPI_TRY( (sdram_connector_helper<DQ0_31, PKG_RANK_MAP>(o_value)), - "%s Failed to sdram_connector_helper for DQ0_31, PKG_RANK_MAP", iv_target_str_storage ); - - FAPI_TRY( (sdram_connector_helper<DQ32_63, PKG_RANK_MAP>(o_value)), - "%s Failed to sdram_connector_helper for DQ32_63, PKG_RANK_MAP", iv_target_str_storage ); - - FAPI_TRY( (sdram_connector_helper<CB0_7, PKG_RANK_MAP>(o_value)), - "%s Failed to sdram_connector_helper for CB0_7, PKG_RANK_MAP", iv_target_str_storage ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Nibble map -/// @param[out] o_value vector of bit order encoding for SPD bytes 60 - 77 -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 60 - 77 -/// @note JEDEC Standard No. 21-C -/// @note Page 45 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::nibble_map( std::vector<uint8_t>& o_value ) const -{ - o_value.clear(); - - FAPI_TRY( (sdram_connector_helper<DQ0_31, NIBBLE_MAP>(o_value)), - "%s Failed to sdram_connector_helper for DQ0_31, NIBBLE_MAP", iv_target_str_storage ); - - FAPI_TRY( (sdram_connector_helper<DQ32_63, NIBBLE_MAP>(o_value)), - "%s Failed to sdram_connector_helper for DQ32_63, NIBBLE_MAP", iv_target_str_storage ); - - FAPI_TRY( (sdram_connector_helper<CB0_7, NIBBLE_MAP>(o_value)), - "%s Failed to sdram_connector_helper for CB0_7, NIBBLE_MAP", iv_target_str_storage ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group -/// @param[out] o_value tCCD_Lmin offset in FTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 117 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_offset_min_tccd_l( int64_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 117; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum CAS to CAS Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for min RAS to CAS Delay Time (tCCD_Lmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Fine offset for Minimum RAS to CAS Delay Time (tCCD_Lmin) in FTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group -/// @param[out] o_value tRRD_Lmin offset in FTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 118 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_offset_min_trrd_l( int64_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 118; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum Activate to Activate Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin) in FTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group -/// @param[out] o_value tRRD_Smin offset in FTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 119 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_offset_min_trrd_s( int64_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 119; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in FTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time -/// @param[out] o_value tRCmin offset in FTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 120 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_offset_min_trc( int64_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 120; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum Active to Active/Refresh Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for vali value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin) in FTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time -/// @param[out] o_value tRPmin offset in FTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 121 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_offset_min_trp( int64_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 121; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for Minimum Row Precharge Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for Minimum Row Precharge Delay Time (tRPmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Fine offset for Minimum Row Precharge Delay Time (tRPmin) in FTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} -/// -/// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time -/// @param[out] o_value tRCDmin offset in FTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 122 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_offset_min_trcd( int64_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 122; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for SDRAM Minimum RAS to CAS Delay Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for min RAS to CAS Delay Time (tRCDmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Fine offset for Minimum RAS to CAS Delay Time (tRCDmin) in FTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time -/// @param[out] o_value tAAmin offset in FTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 123 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_offset_min_taa( int64_t& o_value ) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 123; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for SDRAM Minimum CAS Latency Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Fine offset for Minimum CAS Latency Time (tAAmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Fine offset for Minimum CAS Latency Time (tAAmin) in FTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time -/// @param[out] o_value tCKmax offset in FTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 124 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_offset_max_tck( int64_t& o_value ) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 124; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for SDRAM Maximum Cycle Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the fine offset for max cycle time (tckmax)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Fine offset for Maximum Cycle Time (tCKmax) in FTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time -/// @param[out] o_value tCKmin offset in FTB units -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 125 -/// @note Item JC-45-2220.01x -/// @note Page 52 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::fine_offset_min_tck( int64_t& o_value ) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 125; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - // Retrieve Fine Offset for SDRAM Minimum Cycle Time - // int8_t conversion - allows me to get a negative offset - // then implicit conversion to int64_t - int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]); - - // Check for valid value - constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC - constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - BYTE_INDEX, - l_timing_val, - "Failed check on the Fine offset for Minimum Cycle Time (tCKmin)") ); - - // Update output value only if range check passes - o_value = l_timing_val; - - FAPI_INF("%s. Fine offset for Minimum Cycle Time (tCKmin) in FTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section -/// @param[out] o_value crc value from SPD -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 127 & Byte 126 -/// @note Item JC-45-2220.01x -/// @note Page 53 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::cyclical_redundancy_code( uint16_t& o_value ) const -{ - uint8_t crc_MSB = extract_spd_field< CRC_MSB >(iv_target, iv_spd_data); - FAPI_INF("MSB Field Bits value: %lu", crc_MSB); - - uint8_t crc_LSB = extract_spd_field< CRC_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", crc_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 0; - constexpr size_t MSN_LEN = 8; - constexpr size_t LSB_START = 8; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<uint16_t> l_buffer; - l_buffer.insertFromRight<MSN_START, MSN_LEN>( crc_MSB ) - .insertFromRight<LSB_START, LSB_LEN>( crc_LSB ); - - // This value isn't bounded in the SPD document - o_value = l_buffer; - - FAPI_INF("%s. Cyclical Redundancy Code (CRC): %d", - iv_target_str_storage, - o_value); - - // Returns "happy" until we can figure out a way to test this - AAM - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes module manufacturer ID code -/// @param[out] o_value module manufacturing id code -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 320 (bit 7~0), 321 (6~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 3 -/// @note Page 4.1.2.12 - 54 -/// -fapi2::ReturnCode decoder_v1_0::module_manufacturer_id_code( uint16_t& o_value ) const -{ - - constexpr size_t BYTE_INDEX_MSB = 320; - uint8_t mfgid_MSB = iv_spd_data[BYTE_INDEX_MSB]; - - constexpr size_t BYTE_INDEX_LSB = 321; - uint8_t mfgid_LSB = iv_spd_data[BYTE_INDEX_LSB]; - - constexpr size_t MSB_START = 0; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 8; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<uint16_t> l_buffer; - l_buffer.insertFromRight<MSB_START, MSB_LEN>( mfgid_MSB ) - .insertFromRight<LSB_START, LSB_LEN>( mfgid_LSB ); - - o_value = l_buffer; - - FAPI_INF("%s.Module Manufacturer ID Code: %x", - iv_target_str_storage, - o_value); - - // Returns "happy" until we can figure out a way to test this - AAM - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes Module Manufacturing Location -/// @param[out] o_value uint8_t identifier for manufacturing location of memory module -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 322 -/// @note Item JC-45-2220.01x -/// @note Page 55 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::module_manufacturing_location( uint8_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 322; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - o_value = iv_spd_data[BYTE_INDEX]; - - FAPI_INF("%s. Module Manufacturing Location: %x", - iv_target_str_storage, - o_value); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodesmodule manufacturing date -/// @param[out] o_value the 2 byte date of manufacturing in BCD format -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 323-324 -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 54 -/// @note in Binary Coded Decimal (BCD) -/// @note MSB = year, LSB = week -/// -fapi2::ReturnCode decoder_v1_0::module_manufacturing_date( uint16_t& o_value ) const -{ - - constexpr size_t BYTE_INDEX_MSB = 323; - uint8_t date_MSB = iv_spd_data[BYTE_INDEX_MSB]; - - constexpr size_t BYTE_INDEX_LSB = 324; - uint8_t date_LSB = iv_spd_data[BYTE_INDEX_LSB]; - - constexpr size_t MSB_START = 0; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 8; - constexpr size_t LSB_LEN = 8; - - //Using insertFromRight because IBM is backwards - fapi2::buffer<uint16_t> l_buffer; - l_buffer.insertFromRight<MSB_START, MSB_LEN>( date_MSB ) - .insertFromRight<LSB_START, LSB_LEN>( date_LSB ); - - o_value = l_buffer; - - FAPI_INF("%s.Module Manufacturer ID date: %x", - iv_target_str_storage, - o_value); - - // Returns "happy" until we can figure out a way to test this - AAM - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes module's unique serial number -/// @param[out] o_value -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 325-328 -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 54 -/// @note in Binary Coded Decimal (BCD) -/// -fapi2::ReturnCode decoder_v1_0::module_serial_number( uint32_t& o_value ) const -{ - constexpr size_t BYTE_INDEX_0 = 325; - uint8_t sn_byte_0 = iv_spd_data[BYTE_INDEX_0]; - - constexpr size_t BYTE_INDEX_1 = 326; - uint8_t sn_byte_1 = iv_spd_data[BYTE_INDEX_1]; - - constexpr size_t BYTE_INDEX_2 = 327; - uint8_t sn_byte_2 = iv_spd_data[BYTE_INDEX_2]; - - constexpr size_t BYTE_INDEX_3 = 328; - uint8_t sn_byte_3 = iv_spd_data[BYTE_INDEX_3]; - - constexpr size_t START_BYTE_0 = 0; - constexpr size_t LEN_BYTE_0 = 8; - constexpr size_t START_BYTE_1 = 8; - constexpr size_t LEN_BYTE_1 = 8; - constexpr size_t START_BYTE_2 = 16; - constexpr size_t LEN_BYTE_2 = 8; - constexpr size_t START_BYTE_3 = 24; - constexpr size_t LEN_BYTE_3 = 8; - - //Goes down the batting order, Inserts from left side because IBM - fapi2::buffer<uint32_t> l_buffer; - l_buffer.insertFromRight<START_BYTE_0, LEN_BYTE_0>( sn_byte_0 ) - .insertFromRight<START_BYTE_1, LEN_BYTE_1>( sn_byte_1 ) - .insertFromRight<START_BYTE_2, LEN_BYTE_2>( sn_byte_2 ) - .insertFromRight<START_BYTE_3, LEN_BYTE_3>( sn_byte_3 ); - - o_value = l_buffer; - - FAPI_INF("%s.Module Serial Number : %x", - iv_target_str_storage, - o_value); - - // Returns "happy" until we can figure out a way to test this - AAM - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes Module Revision Code -/// @param[out] o_value uint8_t identifier for revision code -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 349 -/// @note Item JC-45-2220.01x -/// @note Page 55 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_0::module_revision_code( uint8_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 349; - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - o_value = iv_spd_data[BYTE_INDEX]; - - FAPI_INF("%s. Module Revision Code: %x", - iv_target_str_storage, - o_value); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes DRAM Manufacturer ID code -/// @param[out] o_value dram manufacturing id code -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 350 351 -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 54 -/// -fapi2::ReturnCode decoder_v1_0::dram_manufacturer_id_code( uint16_t& o_value ) const -{ - constexpr size_t BYTE_INDEX_MSB = 350; - uint8_t mfgid_MSB = iv_spd_data[BYTE_INDEX_MSB]; - - constexpr size_t BYTE_INDEX_LSB = 351; - uint8_t mfgid_LSB = iv_spd_data[BYTE_INDEX_LSB]; - - constexpr size_t MSB_START = 0; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 8; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<uint16_t> l_buffer; - l_buffer.insertFromRight<MSB_START, MSB_LEN>( mfgid_MSB ) - .insertFromRight<LSB_START, LSB_LEN>( mfgid_LSB ); - - o_value = l_buffer; - - FAPI_INF("%s.DRAM Manufacturer ID Code (dram_mfg_id): %x", - iv_target_str_storage, - o_value); - - // Returns "happy" until we can figure out a way to test this - AAM - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes REGISTER Manufacturer ID code -/// @param[out] o_value rcd manufacturing id code -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 133-134 -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 54 -/// -fapi2::ReturnCode decoder_v1_0::reg_manufacturer_id_code( uint16_t& o_value ) const -{ - constexpr size_t BYTE_INDEX_LSB = 133; - uint8_t mfgid_LSB = iv_spd_data[BYTE_INDEX_LSB]; - - constexpr size_t BYTE_INDEX_MSB = 134; - uint8_t mfgid_MSB = iv_spd_data[BYTE_INDEX_MSB]; - - constexpr size_t MSB_START = 0; - constexpr size_t MSB_LEN = 8; - constexpr size_t LSB_START = 8; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<uint16_t> l_buffer; - l_buffer.insertFromRight<MSB_START, MSB_LEN>( mfgid_MSB ) - .insertFromRight<LSB_START, LSB_LEN>( mfgid_LSB ); - - o_value = l_buffer; - - FAPI_INF("%s.RCD Manufacturer ID Code (rcd_mfg_id): %x", - iv_target_str_storage, - o_value); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes Register Revision Number -/// @param[out] o_value register revision number -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 135 -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 54 -/// -fapi2::ReturnCode decoder_v1_0::register_rev_num( uint8_t& o_value ) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 135; - - FAPI_INF("%s SPD data at Byte %d: 0x%01X.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - o_value = iv_spd_data[BYTE_INDEX]; - - FAPI_INF("%s. Register Revision Number: %x", - iv_target_str_storage, - o_value); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes DRAM Stepping -/// @param[out] o_value uint8_t DRAM Stepping val -/// @return FAPI2_RC_SUCCESS iff okay -/// @note SPD Byte 353 -/// @note Item JC-45-2220.01x -/// @note Page 56 -/// @note DDR4 SPD Document Release 3 -/// @note also called die revision level -/// -fapi2::ReturnCode decoder_v1_0::dram_stepping( uint8_t& o_value) const -{ - // Trace in the front assists w/ debug - constexpr size_t BYTE_INDEX = 352; - - FAPI_INF("%s SPD data at Byte %d: 0x%01X.", - iv_target_str_storage, - BYTE_INDEX, - iv_spd_data[BYTE_INDEX]); - - o_value = iv_spd_data[BYTE_INDEX]; - - FAPI_INF("%s. DRAM stepping: %x", - iv_target_str_storage, - o_value); - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Returns Logicalranks in Primary SDRAM type -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS iff okay -/// -fapi2::ReturnCode decoder_v1_0::prim_sdram_logical_ranks( uint8_t& o_logical_ranks ) const -{ - uint8_t l_signal_loading = 0; - uint8_t l_ranks_per_dimm = 0; - - FAPI_TRY( prim_sdram_signal_loading(l_signal_loading) ); - FAPI_TRY( num_package_ranks_per_dimm(l_ranks_per_dimm) ); - - if(l_signal_loading == spd::SINGLE_LOAD_STACK) - { - // For single-load-stack(3DS) the logical ranks per package ends up being the same as the die count. - uint8_t l_die_count = 0; - FAPI_TRY( prim_sdram_die_count(l_die_count) ); - - o_logical_ranks = l_ranks_per_dimm * l_die_count; - } - else - { - // Covers case for MONOLITHIC & MULTI_LOAD_STACK - // The die count isn't guaranteed to be 1 (e.g. SDP - 1 die package, DDP - 2 die package). - // Value of 1 is used for calculation purposes as defined by the SPD spec. - o_logical_ranks = l_ranks_per_dimm; - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Returns Logical ranks per DIMM -/// @param[in] i_pDecoder shared pointer to the SPD decoder -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS iff okay -/// -fapi2::ReturnCode decoder_v1_0::logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const -{ - FAPI_TRY( prim_sdram_logical_ranks(o_logical_rank_per_dimm) ); - -fapi_try_exit: - return fapi2::current_err; -} - -}// ddr4 -}//spd -}// mss diff --git a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C deleted file mode 100644 index ca08de944..000000000 --- a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C +++ /dev/null @@ -1,760 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2018 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -/// -/// @file spd_decoder_v1_1.C -/// @brief SPD decoder definitions -/// -// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> -// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> -// *HWP Team: Memory -// *HWP Level: 3 -// *HWP Consumed by: HB:FSP - -// fapi2 -#include <fapi2.H> - -// mss lib -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <generic/memory/lib/spd/spd_checker.H> -#include <generic/memory/lib/utils/c_str.H> -#include <generic/memory/lib/utils/find.H> - -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_MCS; -using fapi2::TARGET_TYPE_DIMM; - -namespace mss -{ -namespace spd -{ -namespace ddr4 -{ - -///////////////////////// -// Member method definitions -///////////////////////// - -/// -/// @brief ctor -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data vector -/// @param[in] i_module_decoder shared_ptr to dimm module decoder -/// @param[in] i_raw_card raw card data structure -/// -decoder_v1_1::decoder_v1_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - const std::shared_ptr<dimm_module_decoder>& i_module_decoder, - const rcw_settings& i_raw_card) - : decoder_v1_0(i_target, i_spd_data, i_module_decoder, i_raw_card) -{} - -/// -/// @brief Decodes SDRAM density from SPD -/// @param[out] o_value SDRAM density in GBs -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 4 (bits 0~3) -/// @note Item JC-45-2220.01x -/// @note Page 18 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::sdram_density( uint8_t& o_value ) const -{ - // ========================================================= - // Byte 4 maps - // Item JC-45-2220.01x - // Page 18 - // DDR4 SPD Document Release 3 - // Byte 4 (0x004): SDRAM Density and Banks - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > SDRAM_DENSITY_MAP = - { - // {key byte, capacity in GBs} - {2, 1}, - {3, 2}, - {4, 4}, - {5, 8}, - {6, 16}, - {7, 32}, - {8, 12}, - {12, 24} - }; - - // Extracting desired biits - const uint8_t l_field_bits = extract_spd_field< SDRAM_CAPACITY >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Check to assure SPD DRAM capacity (map) wont be at invalid values - bool l_is_val_found = mss::find_value_from_key(SDRAM_DENSITY_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - SDRAM_CAPACITY.iv_byte, - l_field_bits, - "Failed check for SPD DRAM capacity") ); - - FAPI_INF("%s. SDRAM density: %d Gb", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Secondary SDRAM signal loading -/// @param[out] o_value enum representing signal loading type -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 10 (bits 1~0) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::sec_sdram_signal_loading( uint8_t& o_value ) const -{ - // ========================================================= - // Byte 10 maps - // Item JC-45-2220.01x - // Page 21-22 - // DDR4 SPD Document Release 3 - // Byte 10 (0x00A): Secondary SDRAM Package Type - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > SEC_SIGNAL_LOADING_MAP = - { - // {key byte, signal loading} - {0, UNSPECIFIED}, - {1, MULTI_LOAD_STACK}, - {2, SINGLE_LOAD_STACK} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< SEC_SIGNAL_LOADING >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(SEC_SIGNAL_LOADING_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - SEC_SIGNAL_LOADING.iv_byte, - l_field_bits, - "Failed check for Secondary SDRAM Signal Loading") ); - - FAPI_INF("%s. Secondary SDRAM Signal Loading: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode Soft post package repair (soft PPR) -/// @param[out] o_value enum representing if soft PPR is supported -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 9 (bit 5) -/// @note Item JC-45-2220.01x -/// @note Page 21 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::soft_post_package_repair( uint8_t& o_value ) const -{ - // ========================================================= - // Byte 9 maps - // Item JC-45-2220.01x - // Page 21 - // DDR4 SPD Document Release 3 - // Byte 9 (0x009): Other SDRAM Optional Features - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > SOFT_PPR_MAP = - { - // {key byte, value } - {0, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED}, - {1, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< SOFT_PPR >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(SOFT_PPR_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target, - l_is_val_found, - SOFT_PPR.iv_byte, - l_field_bits, - "Failed check for Soft PPR") ); - - FAPI_INF("%s. Soft Post Package Repair (Soft PPR): %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Secondary DRAM Density Ratio -/// @param[out] o_value raw bits from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 10 (bits 3~2) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::sec_dram_density_ratio( uint8_t& o_value ) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< SEC_DENSITY_RATIO >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - constexpr size_t UNDEFINED = 3; // JEDEC map doesn't go beyond 3 - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target, - l_field_bits < UNDEFINED, - SEC_DENSITY_RATIO.iv_byte, - l_field_bits, - "Failed check for DRAM Density Ratio") ); - - FAPI_INF("%s. DRAM Density Ratio: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes Secondary SDRAM die count -/// @param[out] o_value die count -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 10 (bits 6~4) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::sec_sdram_die_count( uint8_t& o_value ) const -{ - // ========================================================= - // Byte 10 maps - // Item JC-45-2220.01x - // Page 21-22 - // DDR4 SPD Document Release 3 - // Byte 10 (0x00A): Secondary SDRAM Package Type - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > SEC_DIE_COUNT_MAP = - { - // {key byte, number of die} - {0, 1}, - {1, 2}, - {2, 3}, - {3, 4}, - {4, 5}, - {5, 6}, - {6, 7}, - {7, 8} - - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< SEC_DIE_COUNT >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(SEC_DIE_COUNT_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - SEC_DIE_COUNT.iv_byte, - l_field_bits, - "Failed check for Secondary Die Count") ); - - FAPI_INF("%s. Secondary Die Count: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Secondary SDRAM package type -/// @param[out] o_value enum representing package type -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 10 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 22 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::sec_sdram_package_type( uint8_t& o_value ) const -{ - // ========================================================= - // Byte 10 maps - // Item JC-45-2220.01x - // Page 21-22 - // DDR4 SPD Document Release 3 - // Byte 10 (0x00A): Secondary SDRAM Package Type - // ========================================================= - - static const std::vector<std::pair<uint8_t, uint8_t> > SEC_PACKAGE_TYPE_MAP = - { - // {key byte, value } - {0, MONOLITHIC}, - {1, NON_MONOLITHIC} - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< SEC_PACKAGE_TYPE >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(SEC_PACKAGE_TYPE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - SEC_PACKAGE_TYPE.iv_byte, - l_field_bits, - "Failed check for Secondary Package Type") ); - - FAPI_INF("%s. Secondary Package Type: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of package ranks per DIMM -/// @param[out] o_value number of package ranks per DIMM -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 12 (bits 5~3) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::num_package_ranks_per_dimm( uint8_t& o_value ) const -{ - // ========================================================= - // Byte 12 maps - // Item JC-45-2220.01x - // Page 23 - // DDR4 SPD Document Release 3 - // Byte 12 (0x00C): Module Organization - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > NUM_PACKAGE_RANKS_MAP = - { - // {key byte, num of package ranks per DIMM (package ranks)} - {0, 1}, - {1, 2}, - {2, 3}, - {3, 4}, - {4, 5}, - {5, 6}, - {6, 7}, - {7, 8}, - }; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< PACKAGE_RANKS >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - bool l_is_val_found = mss::find_value_from_key(NUM_PACKAGE_RANKS_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_is_val_found, - PACKAGE_RANKS.iv_byte, - l_field_bits, - "Failed check for Num Package Ranks Per DIMM") ); - - FAPI_INF("%s. Num Package Ranks per DIMM: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Rank Mix -/// @param[out] o_value rank mix value from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 12 (bit 6) -/// @note Item JC-45-2220.01x -/// @note Page 23 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::rank_mix( uint8_t& o_value ) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< RANK_MIX >(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // Find map value - constexpr size_t INVALID_VALUE = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - (l_field_bits < INVALID_VALUE), - RANK_MIX.iv_byte, - l_field_bits, - "Failed check for Rank Mix") ); - - // Update output after check passes - o_value = l_field_bits; - - FAPI_INF("%s. Rank Mix: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decode CAS Latencies Supported -/// @param[out] o_value bitmap of supported CAS latencies -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Bytes 20-23 -/// @note Item JC-45-2220.01x -/// @note Page 33-34 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::supported_cas_latencies( uint64_t& o_value ) const -{ - // Trace print in the front assists w/ debug - constexpr size_t FIRST_BYTE = 20; - uint8_t first_raw_byte = iv_spd_data[FIRST_BYTE]; - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - FIRST_BYTE, - first_raw_byte); - - constexpr size_t SEC_BYTE = 21; - uint8_t sec_raw_byte = iv_spd_data[SEC_BYTE]; - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - SEC_BYTE, - sec_raw_byte); - - constexpr size_t THIRD_BYTE = 22; - uint8_t third_raw_byte = iv_spd_data[THIRD_BYTE]; - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - THIRD_BYTE, - third_raw_byte); - - constexpr size_t FOURTH_BYTE = 23; - uint8_t fourth_raw_byte = iv_spd_data[FOURTH_BYTE]; - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - FOURTH_BYTE, - fourth_raw_byte); - - // Buffers used for bit manipulation - // Combine Bytes to create bitmap - right aligned - fapi2::buffer<uint64_t> l_buffer; - - l_buffer.insertFromRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(first_raw_byte) - .insertFromRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(sec_raw_byte) - .insertFromRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(third_raw_byte) - .insertFromRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(fourth_raw_byte); - - // According to the JEDEC spec: - // Byte 23 bit 6 is reserved and must be coded as 0. - // Should we warn instead of fail because in last revision this was a reserved byte coded as 0x00 - constexpr size_t BIT_START = 33; // relative position of bit 6 in byte 23 relative to uint64_t - constexpr size_t BIT_LEN = 1; - - // Check for a valid value - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - !(l_buffer.getBit<BIT_START, BIT_LEN>()), - FOURTH_BYTE, - fourth_raw_byte, - "Failed check on CAS latencies supported") ); - - // Update output value only if range check passes - o_value = l_buffer; - - FAPI_INF("%s. CAS latencies supported (bitmap): 0x%llX", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum Write Recovery Time -/// @param[out] o_value tWRmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::min_twr( int64_t& o_value ) const -{ - uint8_t tWRmin_MSN = extract_spd_field< TWRMIN_MSN >(iv_target, iv_spd_data); - FAPI_INF("MSN Field Bits value: %lu", tWRmin_MSN); - - uint8_t tWRmin_LSB = extract_spd_field< TWRMIN_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", tWRmin_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<int64_t> l_buffer; - l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRmin_MSN ). - insertFromRight<LSB_START, LSB_LEN>( tWRmin_LSB ); - - // Extract timing value from the buffer into an integral type - int64_t l_timing_val = l_buffer; - - // JEDEC spec limits for this timing value - // This value used to be reserved to 0 - before spec update - // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - - constexpr int64_t TIMING_LOWER_BOUND = 0; - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 42) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 42; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target, - (l_timing_val <= TIMING_UPPER_BOUND) && - (l_timing_val >= TIMING_LOWER_BOUND), - ERROR_BYTE_INDEX, - l_timing_val, - "Failed check on the Minimum Write Recovery Time (tWRmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Write Recovery Time (tWRmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes Minimum Write to Read Time - Different Bank Group -/// @param[out] o_value tWTR_Smin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 40 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::min_twtr_s( int64_t& o_value ) const -{ - uint8_t tWTR_Smin_MSN = extract_spd_field< TWTRMIN_S_MSN >(iv_target, iv_spd_data); - FAPI_INF("MSN Field Bits value: %lu", tWTR_Smin_MSN); - - uint8_t tWTR_Smin_LSB = extract_spd_field< TWTRMIN_S_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", tWTR_Smin_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<int64_t> l_buffer; - - l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWTR_Smin_MSN ) - .insertFromRight<LSB_START, LSB_LEN>( tWTR_Smin_LSB ); - - // Extract timing value from the buffer into an integral type - int64_t l_timing_val = l_buffer; - - // JEDEC spec limits for this timing value - - // This value used to be reserved to 0 - before spec update - AAM - // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC - constexpr int64_t TIMING_LOWER_BOUND = 0; - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 44) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 44; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_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 (tWTR_Smin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Write to Read Time - Different Bank Group (tWTR_Smin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes Minimum Write to Read Time - Same Bank Group -/// @param[out] o_value tWTR_Lmin in MTB units -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) -/// @note Item JC-45-2220.01x -/// @note Page 46 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode decoder_v1_1::min_twtr_l( int64_t& o_value ) const -{ - // Extracting desired bits - uint8_t tWTR_Lmin_MSN = extract_spd_field< TWTRMIN_L_MSN >(iv_target, iv_spd_data); - FAPI_INF("MSN Field Bits value: %lu", tWTR_Lmin_MSN); - - uint8_t tWTR_Lmin_LSB = extract_spd_field< TWTRMIN_L_LSB >(iv_target, iv_spd_data); - FAPI_INF("LSB Field Bits value: %lu", tWTR_Lmin_LSB); - - // Combining bits to create timing value (in a buffer) - constexpr size_t MSN_START = 52; - constexpr size_t MSN_LEN = 4; - constexpr size_t LSB_START = 56; - constexpr size_t LSB_LEN = 8; - - fapi2::buffer<int64_t> l_buffer; - - l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWTR_Lmin_MSN ) - .insertFromRight<LSB_START, LSB_LEN>( tWTR_Lmin_LSB ); - - // Extract timing value from the buffer into an integral type - int64_t l_timing_val = l_buffer; - - // JEDEC spec limits for this timing value - // This value used to be reserved to 0 - before spec update - //constexpr int64_t TIMING_LOWER_BOUND = 1 // from JEDEC - constexpr int64_t TIMING_LOWER_BOUND = 0; - constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC - - // best we can do? - // I had to combine parts from two different bytes. - // Chose one of them (byte 45) to for error printout of this decode - constexpr size_t ERROR_BYTE_INDEX = 45; - - FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_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 (tWTR_Lmin) in MTB") ); - - // Update output only after check passes - o_value = l_timing_val; - - FAPI_INF("%s. Minimum Write to Read Time - Same Bank Group (tWTR_Lmin) in MTB units: %d", - iv_target_str_storage, - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function that returns Logical ranks in SDRAM type -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode decoder_v1_1::sec_sdram_logical_ranks( uint8_t& o_logical_ranks ) const -{ - uint8_t l_signal_loading = 0; - uint8_t l_ranks_per_dimm = 0; - - FAPI_TRY( sec_sdram_signal_loading(l_signal_loading) ); - FAPI_TRY( num_package_ranks_per_dimm(l_ranks_per_dimm) ); - - if(l_signal_loading == spd::SINGLE_LOAD_STACK) - { - // For single-load-stack(3DS) the logical ranks per package ends up being the same as the die count. - uint8_t l_die_count = 0; - FAPI_TRY( sec_sdram_die_count(l_die_count) ); - - o_logical_ranks = l_ranks_per_dimm * l_die_count; - } - else - { - // Covers case for MONOLITHIC & MULTI_LOAD_STACK - // The die count isn't guaranteed to be 1 (e.g. SDP - 1 die package, DDP - 2 die package). - // Value of 1 is used for calculation purposes as defined by the SPD spec. - o_logical_ranks = l_ranks_per_dimm; - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Returns Logical ranks per DIMM -/// @param[out] o_logical_ranks number of logical ranks -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode decoder_v1_1::logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const -{ - uint8_t l_rank_mix = 0; - - FAPI_TRY( rank_mix(l_rank_mix) ); - - if(l_rank_mix == fapi2::ENUM_ATTR_EFF_DRAM_RANK_MIX_SYMMETRICAL) - { - FAPI_TRY( prim_sdram_logical_ranks(o_logical_rank_per_dimm) ); - } - else - { - // Rank mix is ASYMMETRICAL - uint8_t l_prim_logical_rank_per_dimm = 0; - uint8_t l_sec_logical_rank_per_dimm = 0; - - FAPI_TRY( prim_sdram_logical_ranks(l_prim_logical_rank_per_dimm) ); - FAPI_TRY( sec_sdram_logical_ranks(l_sec_logical_rank_per_dimm) ); - - o_logical_rank_per_dimm = l_prim_logical_rank_per_dimm + l_sec_logical_rank_per_dimm; - } - -fapi_try_exit: - return fapi2::current_err; -} - -}// ddr4 -}// spd -}// mss diff --git a/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H b/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H index da24f3155..ec7916df4 100644 --- a/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H +++ b/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H @@ -52,11 +52,12 @@ namespace spd /// class dimm_module_decoder { - public: + private: + const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + std::vector<uint8_t> iv_data; - // - std::vector<uint8_t> iv_spd_data; + public: /// /// @brief default ctor @@ -67,9 +68,10 @@ class dimm_module_decoder /// @brief ctor /// dimm_module_decoder(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data): iv_target(i_target), iv_spd_data(i_spd_data) + const std::vector<uint8_t>& i_spd_data): + iv_target(i_target), + iv_data(i_spd_data) { - fapi2::toString(iv_target, iv_target_str_storage, fapi2::MAX_ECMD_STRING_LEN); } /// @@ -78,6 +80,33 @@ class dimm_module_decoder virtual ~dimm_module_decoder() = default; /// + /// @brief Gets decoder target + /// @return fapi2::Target<fapi2::TARGET_TYPE_DIMM> + /// + virtual fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_dimm_target() const + { + return iv_target; + } + + /// + /// @brief Gets decoder SPD data + /// @return std::vector<uint8_t> + /// + virtual std::vector<uint8_t> get_data() const + { + return iv_data; + } + + /// + /// @brief Sets decoder SPD data + /// @param[in] i_spd_data SPD data in a vector reference + /// + virtual void set_data(const std::vector<uint8_t>& i_spd_data) + { + iv_data = i_spd_data; + } + + /// /// @brief Decodes module nominal height max /// @param[out] o_output height range encoding from SPD /// @return FAPI2_RC_SUCCESS if okay @@ -122,8 +151,23 @@ class dimm_module_decoder } /// + /// @brief Decodes reference raw card used + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 130 (Bits 7~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode reference_raw_card(uint8_t& o_output) const + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// /// @brief Decodes number of registers used on RDIMM - /// @param[out] o_output encoding from SPD + /// @param[out] o_output encoding from SPD /// @return FAPI2_RC_SUCCESS if okay /// virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) const @@ -145,7 +189,7 @@ class dimm_module_decoder /// /// @brief Decodes register and buffer type for LRDIMMs - /// @param[out] o_output encoding from SPD + /// @param[out] o_output encoding from SPD /// @return FAPI2_RC_SUCCESS if okay /// virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output) const @@ -178,22 +222,11 @@ class dimm_module_decoder } /// - /// @brief Decodes number of continuation codes - /// @param[out] o_output drive strength encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// - virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output) const - { - o_output = 0; - return fapi2::FAPI2_RC_SUCCESS; - } - - /// /// @brief Decodes register manufacturer ID code /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCESS if okay /// - virtual fapi2::ReturnCode reg_manufacturer_id_code(uint8_t& o_output) const + virtual fapi2::ReturnCode reg_manufacturer_id_code(uint16_t& o_output) const { o_output = 0; return fapi2::FAPI2_RC_SUCCESS; @@ -312,7 +345,7 @@ class dimm_module_decoder /// /// @brief Decodes RCD output slew rate control - /// @param[out] o_output encoded drive strength + /// @param[out] o_output encoded slew rate /// @return FAPI2_RC_SUCCESS if okay /// virtual fapi2::ReturnCode slew_rate_control(uint8_t& o_output) const @@ -521,45 +554,8 @@ class dimm_module_decoder o_output = 0; return fapi2::FAPI2_RC_SUCCESS; } - - protected: - - char iv_target_str_storage[fapi2::MAX_ECMD_STRING_LEN]; - }; -/// -/// @brief data structure for byte fields -/// @note holds byte index, start bit and length of decoded field -/// -struct field_t -{ - const uint64_t iv_byte; - const uint64_t iv_start; - const uint64_t iv_length; - - // default ctor deleted - constexpr field_t() = delete; - - /// - /// @brief ctor - /// @param[in] i_byte_index - /// @param[in] i_start_bit - /// @param[in] i_bit_length - /// - constexpr field_t(const uint64_t i_byte_index, - const uint64_t i_start_bit, - const uint64_t i_bit_length) - : iv_byte(i_byte_index), iv_start(i_start_bit), iv_length(i_bit_length) - {} - - /// - /// @brief default dtor - /// - ~field_t() = default; - -};// field_t - }// spd }// mss diff --git a/src/import/generic/memory/lib/spd/common/spd_decoder_base.H b/src/import/generic/memory/lib/spd/common/spd_decoder_base.H index 53b931b40..878d2f27e 100644 --- a/src/import/generic/memory/lib/spd/common/spd_decoder_base.H +++ b/src/import/generic/memory/lib/spd/common/spd_decoder_base.H @@ -40,157 +40,140 @@ #include <memory> #include <fapi2.H> -#include <generic/memory/lib/spd/common/dimm_module_decoder.H> -#include <generic/memory/lib/spd/common/rcw_settings.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> +#include <generic/memory/lib/spd/spd_reader.H> namespace mss { + namespace spd { -/// -/// @brief Helper function to extract byte information -/// @tparam F the SPD field to extract -/// @param[in] i_target the dimm target -/// @param[in] i_spd_data the SPD data -/// @return extracted byte (right aligned) -/// -template< const field_t& F > -inline uint8_t extract_spd_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data) +class base_cnfg_decoder { - char l_target_str_storage[fapi2::MAX_ECMD_STRING_LEN]; - fapi2::toString(i_target, l_target_str_storage, fapi2::MAX_ECMD_STRING_LEN); - - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - l_target_str_storage, - F.iv_byte, - i_spd_data[F.iv_byte]); - - fapi2::buffer<uint8_t> l_buffer(i_spd_data[F.iv_byte]); + private: - // Extracting desired bits - uint8_t l_field_bits = 0; - l_buffer.extractToRight<F.iv_start, F.iv_length>(l_field_bits); - - return l_field_bits; -} + const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + std::vector<uint8_t> iv_data; -/// -/// @brief Helper function to extract byte information -/// @param[in] i_target the dimm target -/// @param[in] i_field the SPD field -/// @param[in] i_spd_data the SPD data -/// @return extracted byte (right aligned) -/// -inline uint8_t extract_spd_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const field_t& i_field, - const std::vector<uint8_t>& i_spd_data) -{ - char l_target_str_storage[fapi2::MAX_ECMD_STRING_LEN]; - fapi2::toString(i_target, l_target_str_storage, fapi2::MAX_ECMD_STRING_LEN); + public: - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - l_target_str_storage, - i_field.iv_byte, - i_spd_data[i_field.iv_byte]); + /// + /// @brief ctor + /// @param[in] i_target dimm target + /// @param[in] i_spd_data SPD data vector + /// + base_cnfg_decoder(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data) + : iv_target(i_target), + iv_data(i_spd_data) + { + } - fapi2::buffer<uint8_t> l_buffer(i_spd_data[i_field.iv_byte]); + /// + /// @brief dtor + /// + virtual ~base_cnfg_decoder() = default; - // Extracting desired bits - uint8_t l_field_bits = 0; - l_buffer.extractToRight( l_field_bits, i_field.iv_start, i_field.iv_length ); + /// + /// @brief Gets decoder target + /// @return fapi2::Target<fapi2::TARGET_TYPE_DIMM> + /// + virtual fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_dimm_target() const + { + return iv_target; + } - return l_field_bits; -} + /// + /// @brief Gets decoder SPD data + /// @return std::vector<uint8_t> + /// + virtual std::vector<uint8_t> get_data() const + { + return iv_data; + } -/// -/// @class decoder -/// @brief Base SPD DRAM decoder -/// -class decoder -{ - protected: - char iv_target_str_storage[fapi2::MAX_ECMD_STRING_LEN]; + /// + /// @brief Sets decoder SPD data + /// @param[in] i_spd_data SPD data in a vector reference + /// + virtual void set_data(const std::vector<uint8_t>& i_spd_data) + { + iv_data = i_spd_data; + } /// - /// @brief Helper function that turns Logical ranks in Primary SDRAM type - /// @param[out] o_logical_ranks number of logical ranks - /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @brief Decodes number of used SPD bytes + /// @param[out] o_value number of SPD bytes used + /// @return FAPI2_RC_SUCCESS iff okay /// - virtual fapi2::ReturnCode prim_sdram_logical_ranks( uint8_t& o_logical_ranks ) const + virtual fapi2::ReturnCode number_of_used_bytes( uint8_t& o_value ) const { - o_logical_ranks = 0; + o_value = 0; return fapi2::FAPI2_RC_SUCCESS; } /// - /// @brief Helper functions that returns Logical ranks in Secondary SDRAM type - /// @param[out] o_logical_ranks number of logical ranks - /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @brief Decodes SDP revision + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS iff okay /// - virtual fapi2::ReturnCode sec_sdram_logical_ranks( uint8_t& o_logical_ranks ) const + virtual fapi2::ReturnCode revision( uint8_t& o_value ) const { - o_logical_ranks = 0; + o_value = 0; return fapi2::FAPI2_RC_SUCCESS; } - public: - const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; - std::shared_ptr<dimm_module_decoder> iv_module_decoder; - std::vector<uint8_t> iv_spd_data; - rcw_settings iv_raw_card; - /// - /// @brief default ctor + /// @brief Decodes total number of SPD bytes + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS iff okay /// - decoder() = default; + virtual fapi2::ReturnCode number_of_total_bytes( uint8_t& o_value ) const + { + o_value = 0; + return fapi2::FAPI2_RC_SUCCESS; + } /// - /// @brief ctor - /// @param[in] i_target dimm target - /// @param[in] i_spd_data SPD data vector - /// @param[in] i_module_decoder shared_ptr to dimm module decoder - /// @param[in] i_raw_card raw pointer to rcd data + /// @brief Decodes DRAM device type + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS iff okay /// - decoder(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - const std::shared_ptr<dimm_module_decoder>& i_module_decoder, - const rcw_settings& i_raw_card) - : iv_target(i_target), - iv_module_decoder(i_module_decoder), - iv_spd_data(i_spd_data), - iv_raw_card(i_raw_card) + virtual fapi2::ReturnCode device_type( uint8_t& o_value ) const { - fapi2::toString(iv_target, iv_target_str_storage, fapi2::MAX_ECMD_STRING_LEN); + o_value = 0; + return fapi2::FAPI2_RC_SUCCESS; } /// - /// @brief Default dtor + /// @brief Decodes base module type + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS iff okay /// - virtual ~decoder() = default; - - ///////////////////////// - // Member Methods - ///////////////////////// + virtual fapi2::ReturnCode base_module( uint8_t& o_value ) const + { + o_value = 0; + return fapi2::FAPI2_RC_SUCCESS; + } /// - /// @brief Decodes number of used SPD bytes - /// @param[out] o_value number of SPD bytes used - /// @return FAPI2_RC_SUCCESS if okay + /// @brief Decodes hybrid media + /// @param[out] o_value number of total SPD bytes + /// @return FAPI2_RC_SUCCESS iff okay /// - virtual fapi2::ReturnCode number_of_used_bytes( uint16_t& o_value ) const + virtual fapi2::ReturnCode hybrid_media( uint8_t& o_value ) const { o_value = 0; return fapi2::FAPI2_RC_SUCCESS; } /// - /// @brief Decodes total number of SPD bytes + /// @brief Decodes hybrid /// @param[out] o_value number of total SPD bytes - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// - virtual fapi2::ReturnCode number_of_total_bytes( uint16_t& o_value ) const + virtual fapi2::ReturnCode hybrid( uint8_t& o_value ) const { o_value = 0; return fapi2::FAPI2_RC_SUCCESS; @@ -199,7 +182,7 @@ class decoder /// /// @brief Decodes SDRAM density from SPD /// @param[out] o_value SDRAM density in GBs - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode sdram_density( uint8_t& o_value ) const { @@ -210,7 +193,7 @@ class decoder /// /// @brief Decodes number of SDRAM banks bits from SPD /// @param[out] o_value Number of SDRAM bank bits - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode bank_bits( uint8_t& o_value ) const { @@ -221,7 +204,7 @@ class decoder /// /// @brief Decodes number of SDRAM bank groups bits from SPD /// @param[out] o_value Number of SDRAM bank groups bits - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode bank_group_bits( uint8_t& o_value ) const { @@ -232,7 +215,7 @@ class decoder /// /// @brief Decodes number of SDRAM column address bits /// @param[out] o_value Number of SDRAM bank bits - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode column_address_bits( uint8_t& o_value ) const { @@ -243,7 +226,7 @@ class decoder /// /// @brief Decodes number of SDRAM row address bits /// @param[out] o_value Number of SDRAM bank bits - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode row_address_bits( uint8_t& o_value ) const { @@ -254,7 +237,7 @@ class decoder /// /// @brief Decodes Primary SDRAM signal loading /// @param[out] o_value Number of SDRAM bank bits - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode prim_sdram_signal_loading( uint8_t& o_value ) const { @@ -265,7 +248,7 @@ class decoder /// /// @brief Decodes Primary SDRAM die count /// @param[out] o_value Number of SDRAM bank bits - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode prim_sdram_die_count( uint8_t& o_value ) const { @@ -275,7 +258,7 @@ class decoder /// /// @brief Decodes Primary SDRAM package type - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode prim_sdram_package_type( uint8_t& o_value ) const { @@ -285,9 +268,9 @@ class decoder /// /// @brief Decode SDRAM Maximum activate count - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// - virtual fapi2::ReturnCode maximum_activate_count( uint32_t& o_value ) const + virtual fapi2::ReturnCode maximum_activate_count( uint8_t& o_value ) const { o_value = 0; return fapi2::FAPI2_RC_SUCCESS; @@ -295,9 +278,9 @@ class decoder /// /// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// - virtual fapi2::ReturnCode maximum_activate_window_multiplier( uint32_t& o_value ) const + virtual fapi2::ReturnCode maximum_activate_window_multiplier( uint8_t& o_value ) const { o_value = 0; return fapi2::FAPI2_RC_SUCCESS; @@ -305,7 +288,7 @@ class decoder /// /// @brief Decode Post package repair (PPR) - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode post_package_repair( uint8_t& o_value ) const { @@ -315,7 +298,7 @@ class decoder /// /// @brief Decode Soft post package repair (soft PPR) - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode soft_post_package_repair( uint8_t& o_value ) const { @@ -325,7 +308,7 @@ class decoder /// /// @brief Decodes Secondary SDRAM signal loading - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode sec_sdram_signal_loading( uint8_t& o_value ) const { @@ -335,7 +318,7 @@ class decoder /// /// @brief Decodes Secondary DRAM Density Ratio - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode sec_dram_density_ratio( uint8_t& o_value ) const { @@ -345,7 +328,7 @@ class decoder /// /// @brief Decodes Secondary SDRAM die count - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode sec_sdram_die_count( uint8_t& o_value ) const { @@ -355,7 +338,7 @@ class decoder /// /// @brief Decodes Secondary SDRAM package type - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode sec_sdram_package_type( uint8_t& o_value ) const { @@ -366,7 +349,7 @@ class decoder /// /// @brief Decode Module Nominal Voltage, VDD /// @param[out] o_value enum representing if 1.2V is operable - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode operable_nominal_voltage( uint8_t& o_value ) const { @@ -377,17 +360,18 @@ class decoder /// /// @brief Decode Module Nominal Voltage, VDD /// @param[out] o_value enum representing if 1.2V is endurant - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode endurant_nominal_voltage( uint8_t& o_value ) const { o_value = 0; return fapi2::FAPI2_RC_SUCCESS; } + /// /// @brief Decodes SDRAM device width /// @param[out] o_value device width in bits - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode device_width( uint8_t& o_value ) const { @@ -398,7 +382,7 @@ class decoder /// /// @brief Decodes number of package ranks per DIMM /// @param[out] o_value number of package ranks per DIMM - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode num_package_ranks_per_dimm( uint8_t& o_value ) const { @@ -409,7 +393,7 @@ class decoder /// /// @brief Decodes Rank Mix /// @param[out] o_value rank mix value from SPD - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode rank_mix( uint8_t& o_value ) const { @@ -420,7 +404,7 @@ class decoder /// /// @brief Decodes primary bus width /// @param[out] o_value primary bus width in bits - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode prim_bus_width( uint8_t& o_value ) const { @@ -431,7 +415,7 @@ class decoder /// /// @brief Decodes bus width extension /// @param[out] o_value bus width extension in bits - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode bus_width_extension( uint8_t& o_value ) const { @@ -442,7 +426,7 @@ class decoder /// /// @brief Decode Module Thermal Sensor /// @param[out] o_value thermal sensor value from SPD - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode thermal_sensor( uint8_t& o_value ) const { @@ -453,7 +437,7 @@ class decoder /// /// @brief Decode Extended Base Module Type /// @param[out] o_value extended base module type value from SPD - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode extended_base_module_type( uint8_t& o_value ) const { @@ -464,7 +448,7 @@ class decoder /// /// @brief Decode Fine Timebase /// @param[out] o_value fine_timebase from SPD in picoseconds - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_timebase( int64_t& o_value ) const { @@ -475,7 +459,7 @@ class decoder /// /// @brief Decode Medium Timebase /// @param[out] o_value fine_timebase from SPD in picoseconds - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode medium_timebase( int64_t& o_value ) const { @@ -487,7 +471,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum Cycle Time in MTB /// @param[out] o_value tCKmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_tck( int64_t& o_value ) const { @@ -498,7 +482,7 @@ class decoder /// /// @brief Decodes SDRAM Maximum Cycle Time in MTB /// @param[out] o_value tCKmax in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode max_tck( int64_t& o_value ) const { @@ -509,7 +493,7 @@ class decoder /// /// @brief Decode CAS Latencies Supported /// @param[out] o_value bitmap of supported CAS latencies - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode supported_cas_latencies( uint64_t& o_value ) const { @@ -520,7 +504,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum CAS Latency Time in MTB /// @param[out] o_value tAAmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_taa( int64_t& o_value ) const { @@ -531,7 +515,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB /// @param[out] o_value tRCDmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_trcd( int64_t& o_value ) const { @@ -542,7 +526,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB /// @param[out] o_value tRPmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_trp( int64_t& o_value ) const { @@ -553,7 +537,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB /// @param[out] o_value tRASmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_tras( int64_t& o_value ) const { @@ -564,7 +548,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB /// @param[out] o_value tRCmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_trc( int64_t& o_value ) const { @@ -575,7 +559,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1 /// @param[out] o_value tRFC1min in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_trfc1( int64_t& o_value ) const { @@ -586,7 +570,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2 /// @param[out] o_value tRFC2min in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_trfc2( int64_t& o_value ) const { @@ -597,7 +581,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4 /// @param[out] o_value tRFC4min in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_trfc4( int64_t& o_value ) const { @@ -608,7 +592,7 @@ class decoder /// /// @brief Decodes SDRAM Minimum Four Activate Window Delay Time /// @param[out] o_value tFAWmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_tfaw( int64_t& o_value ) const { @@ -619,7 +603,7 @@ class decoder /// /// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group /// @param[out] o_value tRRD_Smin MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_trrd_s( int64_t& o_value ) const { @@ -630,7 +614,7 @@ class decoder /// /// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group /// @param[out] o_value tRRD_Lmin MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_trrd_l( int64_t& o_value ) const { @@ -641,7 +625,7 @@ class decoder /// /// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group /// @param[out] o_value tCCD_Lmin MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_tccd_l( int64_t& o_value ) const { @@ -652,7 +636,7 @@ class decoder /// /// @brief Decodes Minimum Write Recovery Time /// @param[out] o_value tWRmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_twr( int64_t& o_value ) const { @@ -663,7 +647,7 @@ class decoder /// /// @brief Decodes Minimum Write to Read Time - Different Bank Group /// @param[out] o_value tWRT_Smin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_twtr_s( int64_t& o_value ) const { @@ -674,7 +658,7 @@ class decoder /// /// @brief Decodes Minimum Write to Read Time - Same Bank Group /// @param[out] o_value tWRT_Lmin in MTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode min_twtr_l( int64_t& o_value ) const { @@ -707,7 +691,7 @@ class decoder /// /// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group /// @param[out] o_value tCCD_Lmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_offset_min_tccd_l( int64_t& o_value ) const { @@ -718,7 +702,7 @@ class decoder /// /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group /// @param[out] o_value tRRD_Lmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_offset_min_trrd_l( int64_t& o_value ) const { @@ -729,7 +713,7 @@ class decoder /// /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group /// @param[out] o_value tRRD_Smin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_offset_min_trrd_s( int64_t& o_value ) const { @@ -740,7 +724,7 @@ class decoder /// /// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time /// @param[out] o_value tRCmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_offset_min_trc( int64_t& o_value ) const { @@ -751,7 +735,7 @@ class decoder /// /// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time /// @param[out] o_value tRPmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_offset_min_trp( int64_t& o_value ) const { @@ -762,7 +746,7 @@ class decoder /// /// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time /// @param[out] o_value tRCDmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_offset_min_trcd( int64_t& o_value ) const { @@ -773,7 +757,7 @@ class decoder /// /// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time /// @param[out] o_value tAAmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_offset_min_taa( int64_t& o_value ) const { @@ -784,7 +768,7 @@ class decoder /// /// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time /// @param[out] o_value tCKmax offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_offset_max_tck( int64_t& o_value ) const { @@ -795,7 +779,7 @@ class decoder /// /// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time /// @param[out] o_value tCKmin offset in FTB units - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode fine_offset_min_tck( int64_t& o_value ) const { @@ -806,7 +790,7 @@ class decoder /// /// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section /// @param[out] o_value crc value from SPD - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode cyclical_redundancy_code( uint16_t& o_value ) const { @@ -817,7 +801,7 @@ class decoder /// /// @brief Decodes module manufacturer ID code /// @param[out] o_output module manufacturing id code - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode module_manufacturer_id_code( uint16_t& o_value ) const { @@ -828,7 +812,7 @@ class decoder /// /// @brief Decodes Module Manufacturing Location /// @param[out] o_value uint8_t identifier for manufacturing location of memory module - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode module_manufacturing_location( uint8_t& o_value ) const { @@ -839,7 +823,7 @@ class decoder /// /// @brief Decodesmodule manufacturing date /// @param[out] o_value the 2 byte date of manufacturing in BCD format - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay virtual fapi2::ReturnCode module_manufacturing_date( uint16_t& o_value ) const { o_value = 0; @@ -849,7 +833,7 @@ class decoder /// /// @brief Decodes module's unique serial number /// @param[out] o_value module's serial number - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode module_serial_number( uint32_t& o_value ) const { @@ -860,7 +844,7 @@ class decoder /// /// @brief Decodes Module Revision Code /// @param[out] o_value uint8_t identifier for revision code - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode module_revision_code( uint8_t& o_value ) const { @@ -871,7 +855,7 @@ class decoder /// /// @brief Decodes DRAM Manufacturer ID code /// @param[out] o_value dram manufacturing id code - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_value ) const { @@ -880,50 +864,16 @@ class decoder } /// - /// @brief Decodes RCD Manufacturer ID code - /// @param[out] o_value rcd manufacturing id code - /// @return FAPI2_RC_SUCCESS if okay - /// - virtual fapi2::ReturnCode reg_manufacturer_id_code( uint16_t& o_value ) const - { - o_value = 0; - return fapi2::FAPI2_RC_SUCCESS; - } - - /// - /// @brief Decodes Register Revision Number - /// @param[out] o_value register revision number - /// @return FAPI2_RC_SUCCESS if okay - /// - virtual fapi2::ReturnCode register_rev_num( uint8_t& o_value ) const - { - o_value = 0; - return fapi2::FAPI2_RC_SUCCESS; - } - - /// /// @brief Decodes DRAM Stepping /// @param[out] o_value uint8_t DRAM Stepping val - /// @return FAPI2_RC_SUCCESS if okay + /// @return FAPI2_RC_SUCCESS iff okay /// virtual fapi2::ReturnCode dram_stepping( uint8_t& o_value ) const { o_value = 0; return fapi2::FAPI2_RC_SUCCESS; } - - /// - /// @brief Returns Logical ranks per DIMM - /// @param[out] o_logical_ranks number of logical ranks - /// @return FAPI2_RC_SUCCESS if okay - /// - virtual fapi2::ReturnCode logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const - { - o_logical_rank_per_dimm = 0; - return fapi2::FAPI2_RC_SUCCESS; - } - -};// decoder +}; }// spd }// mss diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H index f8031274e..49220680c 100644 --- a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H +++ b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H @@ -39,84 +39,107 @@ #include <fapi2.H> #include <vector> +#include <generic/memory/lib/spd/spd_decoder_def.H> #include <generic/memory/lib/spd/common/dimm_module_decoder.H> +#include <generic/memory/lib/spd/spd_reader.H> namespace mss { namespace spd { -namespace ddr4 -{ -namespace lrdimm -{ /// -/// @brief LRDIMM module decoder for revision 1.0 +/// @brief LRDIMM module decoder +/// @tparam R SPD revision - partial specialization /// -class decoder_v1_0 : public dimm_module_decoder +template < rev R > +class decoder<DDR4, LRDIMM_MODULE, R > : public dimm_module_decoder { - public: - - // First field - SPD byte - // Second field - start bit - // Third field - bit length - constexpr static field_t MODULE_NOMINAL_HEIGHT{128, 3, 5}; - constexpr static field_t RAW_CARD_EXTENSION{128, 0, 3}; - - constexpr static field_t FRONT_MODULE_THICKNESS{129, 4, 4}; - constexpr static field_t BACK_MODULE_THICKNESS{129, 0, 4}; - - constexpr static field_t NUM_REGISTERS_USED{131, 6, 2}; - constexpr static field_t NUM_ROWS_OF_DRAMS{131, 4, 2}; - constexpr static field_t REGISTER_TYPE{131, 0, 4}; - - constexpr static field_t HEAT_SPREADER_THERM_CHAR{132, 1, 7}; - constexpr static field_t HEAT_SPREADER_SOLUTION{132, 0, 1}; - - constexpr static field_t CONTINUATION_CODES{133, 1, 7}; - constexpr static field_t ADDR_MAPPING{136, 7, 1}; - - constexpr static field_t CKE_DRIVE_STRENGTH{137, 6, 2}; - constexpr static field_t ODT_DRIVE_STRENGTH{137, 4, 2}; - constexpr static field_t CA_DRIVE_STRENGTH{137, 2, 2}; - constexpr static field_t CS_DRIVE_STRENGTH{137, 0, 2}; + private: - constexpr static field_t B_SIDE_DRIVE_STRENGTH{138, 6, 2}; - constexpr static field_t A_SIDE_DRIVE_STRENGTH{138, 4, 2}; - constexpr static field_t BCOM_BODT_BCKE_DRIVE_STRENGTH{138, 3, 1}; - constexpr static field_t BCK_DRIVE_STRENGTH{138, 2, 1}; - constexpr static field_t RCD_SLEW_CNTRL{138, 1, 1 }; + using fields_t = fields<DDR4, LRDIMM_MODULE>; + fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + std::vector<uint8_t> iv_data; - constexpr static field_t VREF_DQ_RANK0{140, 2, 6}; - constexpr static field_t VREF_DQ_RANK1{141, 2, 6}; - constexpr static field_t VREF_DQ_RANK2{142, 2, 6}; - constexpr static field_t VREF_DQ_RANK3{143, 2, 6}; - - constexpr static field_t DATA_BUFFER_MDQ{145, 1, 3}; - - constexpr static field_t DRAM_VREF_DQ_RANGE{155, 4, 4}; - constexpr static field_t DATA_BUFFER_VREF_DQ{155, 3, 1}; + /// + /// @brief Helper function to check for reserved values for DRAM interface MDQ Drive Strenth + /// @tparam T SPD revision + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[in] i_input value to check reserved bits against + /// @return FAPI2_RC_SUCCESS iff okay + /// + template < rev T > + fapi2::ReturnCode check_for_reserved_values(const uint64_t i_dimm_speed, + const uint8_t i_input) const + { + static_assert(T <= LRDIMM_MAX, "Invalid SPD revision"); + const std::vector<size_t> l_reserved_bits{0b011, 0b100, 0b110, 0b111}; + + // Lets make an additinal check that we aren't being set to a reserved field + FAPI_ASSERT( !std::binary_search(l_reserved_bits.begin(), l_reserved_bits.end(), i_input), + fapi2::MSS_INVALID_DB_MDQ_DRIVE_STRENGTH() + .set_DATA_RATE(i_dimm_speed) + .set_TARGET(iv_target), + "Reserved settings for data buffer MDQ drive strength received for dimm speed %d on %s", + i_dimm_speed, + spd::c_str(iv_target) ); + + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + return fapi2::current_err; + } - constexpr static field_t DATA_BUFFER_GAIN_ADJUST{156, 7, 1}; - constexpr static field_t DATA_BUFFER_DFE{156, 6, 1}; + public: // deleted default ctor - decoder_v1_0() = delete; + decoder() = delete; /// /// @brief ctor /// @param[in] i_target dimm target /// @param[in] i_spd_data vector DIMM SPD data /// - decoder_v1_0(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data) - : dimm_module_decoder(i_target, i_spd_data) - {} + decoder(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data): + dimm_module_decoder(i_target, i_spd_data), + iv_target(i_target), + iv_data(i_spd_data) + { + static_assert( R <= rev::LRDIMM_MAX, " R > rev::LRDIMM_MAX"); + } /// /// @brief default dtor /// - virtual ~decoder_v1_0() = default; + virtual ~decoder() = default; + + /// + /// @brief Gets decoder target + /// @return fapi2::Target<fapi2::TARGET_TYPE_DIMM> + /// + virtual fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_dimm_target() const + { + return iv_target; + } + + /// + /// @brief Gets decoder SPD data + /// @return std::vector<uint8_t> + /// + virtual std::vector<uint8_t> get_data() const + { + return iv_data; + } + + /// + /// @brief Sets decoder SPD data + /// @param[in] i_spd_data SPD data in a vector reference + /// + virtual void set_data(const std::vector<uint8_t>& i_spd_data) + { + iv_data = i_spd_data; + } /// /// @brief Decodes module nominal height max @@ -127,7 +150,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 55 /// - virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) const override; + virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_NOMINAL_HEIGHT, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes raw card extension @@ -138,7 +167,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 55 /// - virtual fapi2::ReturnCode raw_card_extension(uint8_t& o_output) const override; + virtual fapi2::ReturnCode raw_card_extension(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::RAW_CARD_EXT, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes front module maximum thickness max @@ -149,7 +184,14 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 55 /// - virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) const override; + virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::FRONT_MODULE_THICKNESS, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + + } /// /// @brief Decodes back module maximum thickness max @@ -160,7 +202,31 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 55 /// - virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) const override; + virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::BACK_MODULE_THICKNESS, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + + } + + /// + /// @brief Decodes reference raw card used + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 130 (Bits 7~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode reference_raw_card(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::REF_RAW_CARD, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes number of registers used on LRDIMM @@ -171,7 +237,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 57 /// - virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) const override; + virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::NUM_REGS_USED, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes number of rows of DRAMs on LRDIMM @@ -182,29 +254,49 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 57 /// - virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) const override; + virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::ROWS_OF_DRAMS, rev::V1_0>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + + } /// - /// @brief Decodes heat spreader solution - /// @param[out] o_output drive strength encoding from SPD + /// @brief Decodes register and data buffer types + /// @param[out] o_output encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 132 (Bit 7) + /// @note SPD Byte 131 (Bits 7~4) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12.2 - 58 + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 63 /// - virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) const override; + virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::REGISTER_TYPE, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + + } /// - /// @brief Decodes number of continuation codes + /// @brief Decodes heat spreader solution /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 133 (Bits 6~0) + /// @note SPD Byte 132 (Bit 7) /// @note Item JEDEC Standard No. 21-C /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 58 /// - virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output) const override; + virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::HEAT_SPREADER_SOL, rev::V1_0>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register manufacturer ID code @@ -215,7 +307,28 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 58 /// - virtual fapi2::ReturnCode reg_manufacturer_id_code(uint8_t& o_output) const override; + virtual fapi2::ReturnCode reg_manufacturer_id_code(uint16_t& o_output) const override + { + uint8_t l_cont_codes = 0; + uint8_t l_last_nonzero_byte = 0; + + FAPI_TRY( (mss::spd::reader<fields_t::CONTINUATION_CODES, R>(iv_target, iv_data, l_cont_codes)) ); + FAPI_TRY( (mss::spd::reader<fields_t::LAST_NON_ZERO_BYTE, R>(iv_target, iv_data, l_last_nonzero_byte)) ); + + { + fapi2::buffer<uint16_t> l_buffer; + rightAlignedInsert(l_buffer, l_last_nonzero_byte, l_cont_codes); + + o_output = l_buffer; + + FAPI_INF("%s.Module Manufacturer ID Code: 0x%04x", + spd::c_str(iv_target), + o_output); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register revision number @@ -226,7 +339,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 58 /// - virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) const override; + virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::REGISTER_REV, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes address mapping from register to dram @@ -237,7 +356,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 59 /// - virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) const override; + virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::ADDR_MAP_REG_TO_DRAM, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for CKE signal @@ -247,7 +372,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 60 /// - virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::CKE_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for ODT signal @@ -258,7 +389,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 60 /// - virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::ODT_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for command/address (CA) signal @@ -269,7 +406,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 60 /// - virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::CA_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for control signal (CS) signal @@ -280,7 +423,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 60 /// - virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::CS_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for clock (B side) @@ -291,7 +440,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 60 /// - virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::YO_Y2_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for clock (A side) @@ -302,7 +457,65 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 60 /// - virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::Y1_Y3_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE) + /// @param[out] o_output encoded drive strength + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bit 4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 66 + /// + virtual fapi2::ReturnCode bcom_bcke_bodt_drive_strength(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::BCOM_BODT_BCKE_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for data buffer control (BCK) + /// @param[out] o_output encoded drive strength + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bit 5) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 66 + /// + virtual fapi2::ReturnCode bck_output_drive_strength(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::BCK_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes RCD output slew rate control + /// @param[out] o_output encoded drive strength + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bit 6) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 4 + /// @note Page 4.1.2.L-4 - 70 + /// + virtual fapi2::ReturnCode slew_rate_control(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::RCD_SLEW_CNTRL, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } + /// /// @brief Decodes data buffer revision number @@ -313,7 +526,14 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 60 /// - virtual fapi2::ReturnCode data_buffer_rev(uint8_t& o_output) const override; + virtual fapi2::ReturnCode data_buffer_rev(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::DATA_BUFFER_REV, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } + /// /// @brief Decodes DRAM VrefDQ for Package Rank 0 @@ -324,7 +544,14 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 61 /// - virtual fapi2::ReturnCode dram_vref_dq_rank0(uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_vref_dq_rank0(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::VREF_DQ_RANK0, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } + /// /// @brief Decodes DRAM VrefDQ for Package Rank 1 @@ -335,7 +562,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 61 /// - virtual fapi2::ReturnCode dram_vref_dq_rank1(uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_vref_dq_rank1(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::VREF_DQ_RANK1, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes DRAM VrefDQ for Package Rank 2 @@ -346,7 +579,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 61 /// - virtual fapi2::ReturnCode dram_vref_dq_rank2(uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_vref_dq_rank2(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::VREF_DQ_RANK2, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes DRAM VrefDQ for Package Rank 3 @@ -357,7 +596,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 61 /// - virtual fapi2::ReturnCode dram_vref_dq_rank3(uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_vref_dq_rank3(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::VREF_DQ_RANK3, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes data buffer VrefDQ for DRAM interface @@ -368,7 +613,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 61 /// - virtual fapi2::ReturnCode data_buffer_vref_dq(uint8_t& o_output) const override; + virtual fapi2::ReturnCode data_buffer_vref_dq(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::DATA_BUFFER_VREF_DQ, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes DRAM interface MDQ Drive Strenth @@ -382,7 +633,49 @@ class decoder_v1_0 : public dimm_module_decoder /// @note Page 4.1.2.12.2 - 62 /// virtual fapi2::ReturnCode data_buffer_mdq_drive_strength(const uint64_t i_dimm_speed, - uint8_t& o_output) const override; + uint8_t& o_output) const override + { + switch(i_dimm_speed) + { + case mss::DIMM_SPEED_1600: + case mss::DIMM_SPEED_1866: + FAPI_TRY( (mss::spd::reader<fields_t::DB_MDQ_LTE_1866, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2133: + case mss::DIMM_SPEED_2400: + FAPI_TRY( (mss::spd::reader<fields_t::DB_MDQ_LTE_2400, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2666: + case mss::DIMM_SPEED_2933: + case mss::DIMM_SPEED_3200: + FAPI_TRY( (mss::spd::reader<fields_t::DB_MDQ_LTE_3200, R>(iv_target, iv_data, o_output)) ); + break; + + default: + FAPI_ASSERT(false, + fapi2::MSS_INVALID_DIMM_SPEED() + .set_DIMM_SPEED(i_dimm_speed) + .set_TARGET(iv_target), + "Invalid dimm speed received: %d for %s", i_dimm_speed, spd::c_str(iv_target)); + break; + } + + // Lets make an additinal check that we aren't being set to a reserved field + FAPI_TRY((check_for_reserved_values<R>(i_dimm_speed, o_output)), + "Failed reserved bit check for %s", spd::c_str(iv_target)); + + // If we are here we have a valid output, exit + // to avoid error path of fapi_try_exit + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + // A little output clean up if we fail out + o_output = 0; + return fapi2::current_err; + } + /// /// @brief Decodes DRAM interface MDQ read termination strength @@ -395,7 +688,41 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 62 /// - virtual fapi2::ReturnCode data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_output) const override; + virtual fapi2::ReturnCode data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_output) const override + { + switch(i_dimm_speed) + { + case mss::DIMM_SPEED_1600: + case mss::DIMM_SPEED_1866: + FAPI_TRY( (mss::spd::reader<fields_t::DB_MDQ_RTT_LTE_1866, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2133: + case mss::DIMM_SPEED_2400: + FAPI_TRY( (mss::spd::reader<fields_t::DB_MDQ_RTT_LTE_2400, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2666: + case mss::DIMM_SPEED_2933: + case mss::DIMM_SPEED_3200: + FAPI_TRY( (mss::spd::reader<fields_t::DB_MDQ_RTT_LTE_3200, R>(iv_target, iv_data, o_output)) ); + break; + + default: + FAPI_ASSERT(false, + fapi2::MSS_INVALID_DIMM_SPEED() + .set_DIMM_SPEED(i_dimm_speed) + .set_TARGET(iv_target), + "Invalid dimm speed received: %d for %s", i_dimm_speed, spd::c_str(iv_target)); + break; + } + + return fapi2::FAPI2_RC_SUCCESS; + + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes DRAM drive strenth @@ -408,7 +735,41 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 63 /// - virtual fapi2::ReturnCode dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) const override + { + switch(i_dimm_speed) + { + case mss::DIMM_SPEED_1600: + case mss::DIMM_SPEED_1866: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_DRIVE_STRENGTH_LTE_1866, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2133: + case mss::DIMM_SPEED_2400: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_DRIVE_STRENGTH_LTE_2400, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2666: + case mss::DIMM_SPEED_2933: + case mss::DIMM_SPEED_3200: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_DRIVE_STRENGTH_LTE_3200, R>(iv_target, iv_data, o_output)) ); + break; + + default: + FAPI_ASSERT(false, + fapi2::MSS_INVALID_DIMM_SPEED() + .set_DIMM_SPEED(i_dimm_speed) + .set_TARGET(iv_target), + "Invalid dimm speed received: %d for %s", i_dimm_speed, spd::c_str(iv_target)); + break; + } + + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + return fapi2::current_err; + } + /// /// @brief Decodes DRAM ODT for RTT_NOM @@ -421,7 +782,42 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - (64 - 65) /// - virtual fapi2::ReturnCode dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_output) const override + { + switch(i_dimm_speed) + { + case mss::DIMM_SPEED_1600: + case mss::DIMM_SPEED_1866: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_NOM_LTE_1866, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2133: + case mss::DIMM_SPEED_2400: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_NOM_LTE_2400, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2666: + case mss::DIMM_SPEED_2933: + case mss::DIMM_SPEED_3200: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_NOM_LTE_3200, R>(iv_target, iv_data, o_output)) ); + break; + + default: + FAPI_ASSERT(false, + fapi2::MSS_INVALID_DIMM_SPEED() + .set_DIMM_SPEED(i_dimm_speed) + .set_TARGET(iv_target), + "Invalid dimm speed received: %d for %s", i_dimm_speed, spd::c_str(iv_target)); + + break; + } + + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + return fapi2::current_err; + } + /// /// @brief Decodes DRAM ODT for RTT_WR @@ -434,7 +830,41 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - (64 - 65) /// - virtual fapi2::ReturnCode dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_output) const override + { + switch(i_dimm_speed) + { + case mss::DIMM_SPEED_1600: + case mss::DIMM_SPEED_1866: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_WR_LTE_1866, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2133: + case mss::DIMM_SPEED_2400: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_WR_LTE_2400, R>(iv_target, iv_data, o_output)) ); + break; + + case mss::DIMM_SPEED_2666: + case mss::DIMM_SPEED_2933: + case mss::DIMM_SPEED_3200: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_WR_LTE_3200, R>(iv_target, iv_data, o_output)) ); + break; + + default: + FAPI_ASSERT(false, + fapi2::MSS_INVALID_DIMM_SPEED() + .set_DIMM_SPEED(i_dimm_speed) + .set_TARGET(iv_target), + "Invalid dimm speed received: %d for %s", i_dimm_speed, spd::c_str(iv_target)); + + break; + } + + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 0 & 1 @@ -447,172 +877,95 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12.2 - 65 /// - virtual fapi2::ReturnCode dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_output) const override + { + switch(i_dimm_speed) + { + case mss::DIMM_SPEED_1600: + case mss::DIMM_SPEED_1866: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_PARK_R01_LTE_1866, R>(iv_target, iv_data, + o_output)) ); + break; - /// - /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3 - /// for a particular dimm speed - /// @param[in] i_dimm_speed the dimm speed in MT/s - /// @param[out] o_output ODT termination strength (in ohms) - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 152 - 154 (Bits 5~3) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12.2 - 65 - /// - virtual fapi2::ReturnCode dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_output) const override; - -};//decoder - -/// -/// @brief LRDIMM module decoder for revision 1.1 -/// -class decoder_v1_1 : public decoder_v1_0 -{ - public: - - // deleted default ctor - decoder_v1_1() = delete; - - /// - /// @brief ctor - /// @param[in] i_target dimm target - /// @param[in] i_spd_data vector DIMM SPD data - /// - decoder_v1_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data) - : decoder_v1_0(i_target, i_spd_data) - {} - - /// - /// @brief default dtor - /// - virtual ~decoder_v1_1() = default; - - /// - /// @brief Decodes register and data buffer types - /// @param[out] o_output encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 131 (Bits 7~4) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12.3 - 63 - /// - virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output) const override; - - /// - /// @brief Decodes register output drive strength for CKE signal - /// @param[out] o_output encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (Bits 1~0) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12.3 - 65 - /// - virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) const override; - - /// - /// @brief Decodes register output drive strength for ODT signal - /// @param[out] o_output encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (Bits 3~2) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12.3 - 65 - /// - virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) const override; - - /// - /// @brief Decodes register output drive strength for control signal (CS) signal - /// @param[out] o_output encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (Bits 6~7) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12.3 - 65 - /// - virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) const override; - - /// - /// @brief Decodes register output drive strength for clock (B side) - /// @param[out] o_output drive strength encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 138 (Bits 1~0) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12.3 - 66 - /// - virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) const override; - - /// - /// @brief Decodes register output drive strength for clock (A side) - /// @param[out] o_output drive strength encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 138 (Bits 3~2) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12.3 - 66 - /// - virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) const override; -}; + case mss::DIMM_SPEED_2133: + case mss::DIMM_SPEED_2400: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_PARK_R01_LTE_2400, R>(iv_target, iv_data, + o_output)) ); + break; -/// -/// @brief LRDIMM module decoder for revision 1.2 -/// -class decoder_v1_2 : public decoder_v1_1 -{ - public: + case mss::DIMM_SPEED_2666: + case mss::DIMM_SPEED_2933: + case mss::DIMM_SPEED_3200: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_PARK_R01_LTE_3200, R>(iv_target, iv_data, + o_output)) ); + break; - // deleted default ctor - decoder_v1_2() = delete; + default: + FAPI_ASSERT(false, + fapi2::MSS_INVALID_DIMM_SPEED() + .set_DIMM_SPEED(i_dimm_speed) + .set_TARGET(iv_target), + "Invalid dimm speed received: %d for %s", i_dimm_speed, spd::c_str(iv_target)); - /// - /// @brief ctor - /// @param[in] i_target dimm target - /// @param[in] i_spd_data vector DIMM SPD data - /// - decoder_v1_2(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data) - : decoder_v1_1(i_target, i_spd_data) - {} + break; + } - /// - /// @brief default dtor - /// - virtual ~decoder_v1_2() = default; + return fapi2::FAPI2_RC_SUCCESS; - /// - /// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE) - /// @param[out] o_output encoded drive strength - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 138 (Bit 4) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12.3 - 66 - /// - virtual fapi2::ReturnCode bcom_bcke_bodt_drive_strength(uint8_t& o_output) const override; + fapi_try_exit: + return fapi2::current_err; + } - /// - /// @brief Decodes register output drive strength for data buffer control (BCK) - /// @param[out] o_output encoded drive strength - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 138 (Bit 5) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12.3 - 66 - /// - virtual fapi2::ReturnCode bck_output_drive_strength(uint8_t& o_output) const override; /// - /// @brief Decodes RCD output slew rate control - /// @param[out] o_output encoded drive strength + /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3 + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output ODT termination strength (in ohms) /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 138 (Bit 6) + /// @note SPD Byte 152 - 154 (Bits 5~3) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 4 - /// @note Page 4.1.2.L-4 - 70 + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 65 /// - virtual fapi2::ReturnCode slew_rate_control(uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_output) const override + { + switch(i_dimm_speed) + { + case mss::DIMM_SPEED_1600: + case mss::DIMM_SPEED_1866: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_PARK_R23_LTE_1866, R>(iv_target, iv_data, + o_output)) ); + break; + + case mss::DIMM_SPEED_2133: + case mss::DIMM_SPEED_2400: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_PARK_R23_LTE_2400, R>(iv_target, iv_data, + o_output)) ); + break; + + case mss::DIMM_SPEED_2666: + case mss::DIMM_SPEED_2933: + case mss::DIMM_SPEED_3200: + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_ODT_RTT_PARK_R23_LTE_3200, R>(iv_target, iv_data, + o_output)) ); + break; + + default: + FAPI_ASSERT(false, + fapi2::MSS_INVALID_DIMM_SPEED() + .set_DIMM_SPEED(i_dimm_speed) + .set_TARGET(iv_target), + "Invalid dimm speed received: %d for %s", i_dimm_speed, spd::c_str(iv_target)); + + break; + } + + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes VrefDQ range for DRAM interface range @@ -623,7 +976,14 @@ class decoder_v1_2 : public decoder_v1_1 /// @note DDR4 SPD Document Release 4 /// @note Page 4.1.2.L-4 - 76 /// - virtual fapi2::ReturnCode dram_vref_dq_range(uint8_t& o_output) const override; + virtual fapi2::ReturnCode dram_vref_dq_range(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::DRAM_VREF_DQ_RANGE, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } + /// /// @brief Decodes data buffer VrefDQ range for DRAM interface range @@ -634,7 +994,13 @@ class decoder_v1_2 : public decoder_v1_1 /// @note DDR4 SPD Document Release 4 /// @note Page 4.1.2.L-4 - 76 /// - virtual fapi2::ReturnCode data_buffer_vref_dq_range(uint8_t& o_output) const override; + virtual fapi2::ReturnCode data_buffer_vref_dq_range(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::DATA_BUFFER_VREF_DQ_RANGE, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes data buffer gain adjustment @@ -645,7 +1011,13 @@ class decoder_v1_2 : public decoder_v1_1 /// @note DDR4 SPD Document Release 4 /// @note Page 4.1.2.L-4 - 77 /// - virtual fapi2::ReturnCode data_buffer_gain_adjustment(uint8_t& o_output) const override; + virtual fapi2::ReturnCode data_buffer_gain_adjustment(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::DATA_BUFFER_GAIN_ADJUST, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes data buffer Decision Feedback Equalization (DFE) @@ -656,11 +1028,16 @@ class decoder_v1_2 : public decoder_v1_1 /// @note DDR4 SPD Document Release 4 /// @note Page 4.1.2.L-4 - 77 /// - virtual fapi2::ReturnCode data_buffer_dfe(uint8_t& o_output) const override; -}; + virtual fapi2::ReturnCode data_buffer_dfe(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::DATA_BUFFER_DFE, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } + +};//decoder -}// lrdimm -}// ddr4 }// spd }// mss diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_0.C b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_0.C deleted file mode 100644 index dc3ef9cad..000000000 --- a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_0.C +++ /dev/null @@ -1,1368 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_0.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2018 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -/// -/// @file lrdimm_decoder_v1_0.C -/// @brief LRDIMM module SPD decoder definitions for revision 1.0 -/// -// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> -// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> -// *HWP Team: Memory -// *HWP Level: 3 -// *HWP Consumed by: HB:FSP - -// std lib -#include <vector> - -// fapi2 -#include <fapi2.H> - -// mss lib -#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <generic/memory/lib/spd/spd_checker.H> -#include <generic/memory/lib/utils/c_str.H> -#include <generic/memory/lib/utils/find.H> - -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_MCS; -using fapi2::TARGET_TYPE_DIMM; - - -namespace mss -{ -namespace spd -{ -namespace ddr4 -{ -namespace lrdimm -{ - -///////////////////////// -// Non-member helper functions -// For LRDIMM module rev 1.0 -///////////////////////// - -/// -/// @brief Helper function to find SPD byte based on freq -/// @param[in] i_dimm_speed DIMM speed in MT/s -/// @param[out] o_byte byte to extract spd from -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400, -/// -static fapi2::ReturnCode mdq_helper(const uint64_t i_dimm_speed, uint8_t& o_byte) -{ - switch(i_dimm_speed) - { - case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: - o_byte = 145; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: - case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: - o_byte = 146; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: - o_byte = 147; - break; - - default: - FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - break; - } - - return fapi2::FAPI2_RC_SUCCESS; -}; - -/// -/// @brief Helper function to find start bit based on freq -/// @param[in] i_dimm_speed DIMM speed in MT/s -/// @param[out] o_start_bit start bit to extract SPD from -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400, -/// -static fapi2::ReturnCode drive_strength_start_bit_finder(const uint64_t i_dimm_speed, size_t& o_start_bit) -{ - switch(i_dimm_speed) - { - case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: - o_start_bit = 6; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: - case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: - o_start_bit = 4; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: - o_start_bit = 2; - break; - - default: - FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - break; - } - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Helper function to find SPD byte based on freq -/// @param[in] i_dimm_speed DIMM speed in MT/s -/// @param[out] o_byte byte to extract spd from -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400, -/// -static fapi2::ReturnCode rtt_wr_and_nom_byte_finder(const uint64_t i_dimm_speed, size_t& o_byte) -{ - switch(i_dimm_speed) - { - case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: - o_byte = 149; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: - case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: - o_byte = 150; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: - o_byte = 151; - break; - - default: - FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - break; - } - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Helper function to find SPD byte based on freq -/// @param[in] i_dimm_speed DIMM speed in MT/s -/// @param[out] o_byte byte to extract spd from -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400, -/// -static fapi2::ReturnCode rtt_park_byte_finder(const uint64_t i_dimm_speed, size_t& o_byte) -{ - switch(i_dimm_speed) - { - case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: - o_byte = 152; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: - case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: - o_byte = 153; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: - o_byte = 154; - break; - - default: - FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - break; - } - - return fapi2::FAPI2_RC_SUCCESS; -} - -///////////////////////// -// Member Method implementation -// For LRDIMM module rev 1.0 -///////////////////////// - -/// -/// @brief Decodes module nominal height max -/// @param[out] o_output height range encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 128 (Bits 4~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 55 -/// -fapi2::ReturnCode decoder_v1_0::max_module_nominal_height(uint8_t& o_output) const -{ - const uint8_t l_field_bits = extract_spd_field< MODULE_NOMINAL_HEIGHT >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 0b11111; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - MODULE_NOMINAL_HEIGHT.iv_byte, - l_field_bits, - "Failed bound check for module nominal height max") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Max module nominal height: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes raw card extension -/// @param[out] o_output raw card rev. encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 128 (Bits 7~5) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 55 -/// -fapi2::ReturnCode decoder_v1_0::raw_card_extension(uint8_t& o_output) const -{ - const uint8_t l_field_bits = extract_spd_field< RAW_CARD_EXTENSION >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 0b111; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - RAW_CARD_EXTENSION.iv_byte, - l_field_bits, - "Failed bound check for raw card extension") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Raw card extension: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes front module maximum thickness max -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 129 (Bits 3~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 55 -/// -fapi2::ReturnCode decoder_v1_0::front_module_max_thickness(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< FRONT_MODULE_THICKNESS >(iv_target, iv_spd_data); - - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 0b1111; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - FRONT_MODULE_THICKNESS.iv_byte, - l_field_bits, - "Failed bound check for front module max thickness") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Front module max thickness: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes back module maximum thickness max -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 129 (Bits 7~4) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 55 -/// -fapi2::ReturnCode decoder_v1_0::back_module_max_thickness(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< BACK_MODULE_THICKNESS >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 0b1111; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - BACK_MODULE_THICKNESS.iv_byte, - l_field_bits, - "Failed bound check for back module max thickness") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Back module max thickness: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes number of registers used on LRDIMM -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 131 (Bits 1~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 57 -/// -fapi2::ReturnCode decoder_v1_0::num_registers_used(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< NUM_REGISTERS_USED >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 0b10; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, - NUM_REGISTERS_USED.iv_byte, - l_field_bits, - "Failed bound check for number of registers used on RDIMM ") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Number of registers used on LRDIMM : %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of rows of DRAMs on LRDIMM -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 131 (Bits 3~2) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 57 -/// -fapi2::ReturnCode decoder_v1_0::num_rows_of_drams(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< NUM_ROWS_OF_DRAMS >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 0b11; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, - NUM_REGISTERS_USED.iv_byte, - l_field_bits, - "Failed bound check for number of rows of DRAMs on LRDIMM ") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Number of rows of DRAMs on LRDIMM : %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes heat spreader solution -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 132 (Bit 7) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 58 -/// -fapi2::ReturnCode decoder_v1_0::heat_spreader_solution(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< HEAT_SPREADER_SOLUTION >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - HEAT_SPREADER_SOLUTION.iv_byte, - l_field_bits, - "Failed bound check for heat spreader solution") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Heat spreader solution: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes number of continuation codes -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 133 (bit 6~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 58 -/// -fapi2::ReturnCode decoder_v1_0::num_continuation_codes(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< CONTINUATION_CODES >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 10; // JEP106AS spec - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - CONTINUATION_CODES.iv_byte, - l_field_bits, - "Failed bound check for number of continuation codes") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Number of continuation codes: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register manufacturer ID code -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 134 (bit 7~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 58 -/// -fapi2::ReturnCode decoder_v1_0::reg_manufacturer_id_code(uint8_t& o_output) const -{ - constexpr size_t BYTE_INDEX = 134; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - l_raw_byte); - - // All bits used for encoding, no bounds to check - o_output = l_raw_byte; - - FAPI_INF("%s. Register revision number: %d", - iv_target_str_storage, - o_output); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes register revision number -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 135 (bit 7~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 58 -/// -fapi2::ReturnCode decoder_v1_0::register_rev_num(uint8_t& o_output) const -{ - constexpr size_t BYTE_INDEX = 135; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - l_raw_byte); - - // All bits used for encoding, no bounds to check - o_output = l_raw_byte; - - FAPI_INF("%s. Register revision number: %d", - iv_target_str_storage, - o_output); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes address mapping from register to dram -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 136 (bit 0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 59 -/// -fapi2::ReturnCode decoder_v1_0::register_to_dram_addr_mapping(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< ADDR_MAPPING >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - ADDR_MAPPING.iv_byte, - l_field_bits, - "Failed bound check for to register to dram addr mapping") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Address mapping from register to dram: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for CKE signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 1~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 60 -/// -fapi2::ReturnCode decoder_v1_0::cke_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< CKE_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - CKE_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for CKE") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CKE: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for ODT signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 3~2) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 60 -/// -fapi2::ReturnCode decoder_v1_0::odt_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< ODT_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - ODT_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for ODT") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for ODT: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for command/address (CA) signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 5~4) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 60 -/// -fapi2::ReturnCode decoder_v1_0::ca_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< CA_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t INVALID_VAL = 4; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < INVALID_VAL, // extract sanity check - CA_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for CA") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CA: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for control signal (CS) signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 6~7) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 60 -/// -fapi2::ReturnCode decoder_v1_0::cs_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< CS_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - CS_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for CS") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CS: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for clock (B side) -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (bit 1~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 60 -/// -fapi2::ReturnCode decoder_v1_0::b_side_clk_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< B_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - B_SIDE_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for clock (Y0,Y2)") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for clock (A side) -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (bit 3~2) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 60 -/// -fapi2::ReturnCode decoder_v1_0::a_side_clk_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< A_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, - A_SIDE_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for clock (Y1,Y3)") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes data buffer revision number -/// @param[out] o_output revision number -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 139 (Bits 7~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 60 -/// -fapi2::ReturnCode decoder_v1_0::data_buffer_rev(uint8_t& o_output) const -{ - // Extracting desired bits - constexpr size_t BYTE_INDEX = 139; - const uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - l_raw_byte); - - // This checks JEDEC range is met - constexpr size_t UNDEFINED = 0xFF; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_raw_byte != UNDEFINED, - BYTE_INDEX, - l_raw_byte, - "Failed bounds check for data buffer revision number") ); - - // Update output only if check passes - o_output = l_raw_byte; - - FAPI_INF("%s. Data buffer rev: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes DRAM VrefDQ for Package Rank 0 -/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 140 (Bits 5~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 61 -/// -fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank0(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK0 >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // JESD79-4 specification - constexpr size_t RESERVED = 0b110011; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, - VREF_DQ_RANK0.iv_byte, - l_field_bits, - "Failed bounds check for DRAM VrefDQ for Package Rank 0") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM VrefDQ for Package Rank 0: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM VrefDQ for Package Rank 1 -/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 141 (Bits 5~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 61 -/// -fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank1(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK1 >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // JESD79-4 specification - constexpr size_t RESERVED = 0b110011; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, - VREF_DQ_RANK1.iv_byte, - l_field_bits, - "Failed bounds check for DRAM VrefDQ for Package Rank 1") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM VrefDQ for Package Rank 1: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM VrefDQ for Package Rank 2 -/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 142 (Bits 5~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 61 -/// -fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank2(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK2 >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // JESD79-4 specification - constexpr size_t RESERVED = 0b110011; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, - VREF_DQ_RANK2.iv_byte, - l_field_bits, - "Failed bounds check for DRAM VrefDQ for Package Rank 2") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM VrefDQ for Package Rank 2: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM VrefDQ for Package Rank 3 -/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 143 (Bits 5~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 4 -/// @note Page 4.1.2.12.2 - 61 -/// -fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank3(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK3 >(iv_target, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // JESD79-4 specification - constexpr size_t RESERVED = 0b110011; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, - VREF_DQ_RANK3.iv_byte, - l_field_bits, - "Failed bounds check for DRAM VrefDQ for Package Rank 3") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM VrefDQ for Package Rank 3: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes data buffer VrefDQ for DRAM interface -/// @param[out] o_output encoding of F5BC6x in DDR4DB01 spec -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 144 (Bits 5~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 61 -/// -fapi2::ReturnCode decoder_v1_0::data_buffer_vref_dq(uint8_t& o_output) const -{ - constexpr size_t BYTE_INDEX = 144; - uint8_t l_raw_data = iv_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - l_raw_data); - - // DDR4DB01 spec - constexpr size_t RESERVED = 0b00110011; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_raw_data < RESERVED, - BYTE_INDEX, - l_raw_data, - "Failed bounds check for data buffer VrefDQ for DRAM interface") ); - - // Update output only if check passes - o_output = l_raw_data; - - FAPI_INF("%s. Data buffer VrefDQ for DRAM interface: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM interface MDQ Drive Strenth -/// of the data buffer component for a particular dimm speed -/// @param[in] i_dimm_speed the dimm speed in MT/s -/// @param[out] o_output encoding of F5BC6x in -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 145 - 147 (Bits 6~4) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 62 -/// -fapi2::ReturnCode decoder_v1_0::data_buffer_mdq_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) const -{ - uint8_t l_byte = 0; - - FAPI_TRY( mdq_helper(i_dimm_speed, l_byte) ); - - { - constexpr size_t START = 1; - constexpr size_t LEN = 3; - const field_t MDQ_DRIVE_STRENGTH(l_byte, START, LEN); - - const uint8_t l_field_bits = extract_spd_field( iv_target, MDQ_DRIVE_STRENGTH, iv_spd_data ); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // Lets make sure we aren't being set to a reserved field - bool is_reserved_bit = false; - - switch(l_field_bits) - { - case 0b011: - case 0b100: - case 0b110: - case 0b111: - is_reserved_bit = true; - break; - - default: - is_reserved_bit = false; - break; - } - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 7; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - (l_field_bits <= MAX_VALID_VALUE) && - (is_reserved_bit != true), - l_byte, - l_field_bits, - "Failed bounds check for DRAM interface MDQ Drive Strenth") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM interface MDQ Drive Strenth: %d", - iv_target_str_storage, - o_output); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM interface MDQ read termination strength -/// of the data buffer component for a particular dimm speed -/// @param[in] i_dimm_speed the dimm speed in MT/s -/// @param[out] o_output encoding of F5BC6x in -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 145 - 147 (Bits 2~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 62 -/// -fapi2::ReturnCode decoder_v1_0::data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_output) const -{ - uint8_t l_byte = 0; - - FAPI_TRY( mdq_helper(i_dimm_speed, l_byte) ); - - { - constexpr size_t START = 1; - constexpr size_t LEN = 3; - const field_t DATA_BUFFER_MDQ_RTT(l_byte, START, LEN); - - const uint8_t l_field_bits = extract_spd_field( iv_target, DATA_BUFFER_MDQ_RTT, iv_spd_data ); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 7; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - l_byte, - l_field_bits, - "Failed bounds check for DRAM interface MDQ RTT:") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM interface MDQ RTT: %d", - iv_target_str_storage, - o_output); - } -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM drive strenth -/// for a particular dimm speed -/// @param[in] i_dimm_speed the dimm speed in MT/s -/// @param[out] o_output DRAM drive strength (encoding) -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 148 (Bits 5~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 63 -/// -fapi2::ReturnCode decoder_v1_0::dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) const -{ - size_t l_start = 0; - FAPI_TRY( drive_strength_start_bit_finder(i_dimm_speed, l_start) ); - - { - constexpr size_t BYTE_INDEX = 148; - constexpr size_t LEN = 2; - const field_t DRAM_DRIVE_STRENGTH(BYTE_INDEX, l_start, LEN); - - const uint8_t l_field_bits = extract_spd_field( iv_target, DRAM_DRIVE_STRENGTH, iv_spd_data ); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // SPD JEDEC specification - constexpr size_t RESERVED = 0b11; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, - BYTE_INDEX, - l_field_bits, - "Failed bounds check for DRAM VrefDQ for Package Rank 3") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM drive strenth: %d", - iv_target_str_storage, - o_output); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM ODT for RTT_NOM -/// for a particular dimm speed -/// @param[in] i_dimm_speed the dimm speed in MT/s -/// @param[out] o_output ODT termination strength (encoding) -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 149 - 151 (Bits 2~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - (64 - 65) -/// -fapi2::ReturnCode decoder_v1_0::dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_output) const -{ - size_t l_byte = 0; - FAPI_TRY( rtt_wr_and_nom_byte_finder(i_dimm_speed, l_byte) ); - - { - constexpr size_t START = 5; - constexpr size_t LEN = 3; - const field_t DRAM_RTT_NOM(l_byte, START, LEN); - - const uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_NOM, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 7; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - l_byte, - l_field_bits, - "Failed bounds check for DRAM RTT_NOM") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM RTT_NOM: %d", - iv_target_str_storage, - o_output); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM ODT for RTT_WR -/// for a particular dimm speed -/// @param[in] i_dimm_speed the dimm speed in MT/s -/// @param[out] o_output ODT termination strength (encoding) -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 149 - 151 (Bits 5~3) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - (64 - 65) -/// -fapi2::ReturnCode decoder_v1_0::dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_output) const -{ - size_t l_byte = 0; - FAPI_TRY( rtt_wr_and_nom_byte_finder(i_dimm_speed, l_byte) ); - - { - constexpr size_t START = 2; - constexpr size_t LEN = 3; - const field_t DRAM_RTT_WR(l_byte, START, LEN); - - const uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_WR, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // Lets make sure we aren't being set to a reserved field - bool is_reserved_bit = false; - - switch(l_field_bits) - { - case 0b101: - case 0b110: - case 0b111: - is_reserved_bit = true; - break; - - default: - is_reserved_bit = false; - break; - } - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 7; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - (l_field_bits <= MAX_VALID_VALUE) && - (is_reserved_bit != true), - l_byte, - l_field_bits, - "Failed bounds check for DRAM RTT_WR") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM_RTT_WR: %d", - iv_target_str_storage, - o_output); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM ODT for RTT_PARK, package ranks 0 & 1 -/// for a particular dimm speed -/// @param[in] i_dimm_speed the dimm speed in MT/s -/// @param[out] o_output ODT termination strength (encoding) -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 152 - 154 (Bits 2~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 65 -/// -fapi2::ReturnCode decoder_v1_0::dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_output) const -{ - size_t l_byte = 0; - FAPI_TRY( rtt_park_byte_finder(i_dimm_speed, l_byte) ); - - { - constexpr size_t START = 5; - constexpr size_t LEN = 3; - const field_t DRAM_RTT_PARK(l_byte, START, LEN); - - const uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_PARK, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 7; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - l_byte, - l_field_bits, - "Failed bounds check for DRAM RTT_PARK (package ranks 0,1)") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM RTT_PARK (package ranks 0,1): %d", - iv_target_str_storage, - o_output); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3 -/// for a particular dimm speed -/// @param[in] i_dimm_speed the dimm speed in MT/s -/// @param[out] o_output ODT termination strength (encoding) -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 152 - 154 (Bits 5~3) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12.2 - 65 -/// -fapi2::ReturnCode decoder_v1_0::dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_output) const -{ - size_t l_byte = 0; - FAPI_TRY( rtt_park_byte_finder(i_dimm_speed, l_byte) ); - - { - constexpr size_t START = 2; - constexpr size_t LEN = 3; - const field_t DRAM_RTT_PARK(l_byte, START, LEN); - - const uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_PARK, iv_spd_data); - FAPI_INF("%s Field Bits value: %d", iv_target_str_storage, l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 7; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - l_byte, - l_field_bits, - "Failed bounds check for DRAM RTT_PARK (package ranks 2,3)") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. DRAM RTT_PARK (package ranks 2,3): %d", - iv_target_str_storage, - o_output); - } - -fapi_try_exit: - return fapi2::current_err; -} - -}// lrdimm -}// ddr4 -}// spd -}// mss diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_1.C b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_1.C deleted file mode 100644 index 3cccbb654..000000000 --- a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_1.C +++ /dev/null @@ -1,276 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_1.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2018 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -/// -/// @file lrdimm_decoder_v1_1.C -/// @brief LRDIMM module SPD decoder definitions for revision 1.1 -/// -// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> -// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> -// *HWP Team: Memory -// *HWP Level: 3 -// *HWP Consumed by: HB:FSP - -// std lib -#include <vector> - -// fapi2 -#include <fapi2.H> - -// mss lib -#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <generic/memory/lib/spd/spd_checker.H> -#include <generic/memory/lib/utils/c_str.H> -#include <generic/memory/lib/utils/find.H> - -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_MCS; -using fapi2::TARGET_TYPE_DIMM; - -namespace mss -{ -namespace spd -{ -namespace ddr4 -{ -namespace lrdimm -{ - -/// -/// @brief Decodes register and data buffer types -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 131 (Bits 7~4) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 3 -/// @note Page 4.1.2.12.3 - 63 -/// -fapi2::ReturnCode decoder_v1_1::register_and_buffer_type(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< REGISTER_TYPE >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - REGISTER_TYPE.iv_byte, - l_field_bits, - "Failed bounds check for Register and Data Buffer Types") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register and Data Buffer Types: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes register output drive strength for CKE signal -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (Bits 1~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 3 -/// @note Page 4.1.2.12.3 - 65 -/// -fapi2::ReturnCode decoder_v1_1::cke_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< CKE_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - CKE_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for CKE") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CKE: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for ODT signal -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (Bits 3~2) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 3 -/// @note Page 4.1.2.12.3 - 65 -/// -fapi2::ReturnCode decoder_v1_1::odt_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< ODT_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - ODT_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for ODT") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for ODT: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for control signal (CS) signal -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (Bits 6~7) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 3 -/// @note Page 4.1.2.12.3 - 65 -/// -fapi2::ReturnCode decoder_v1_1::cs_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< CS_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - CS_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for CS") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CS: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for clock (B side) -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (Bits 1~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 3 -/// @note Page 4.1.2.12.3 - 66 -/// -fapi2::ReturnCode decoder_v1_1::b_side_clk_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< B_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - B_SIDE_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for clock (Y0,Y2)") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for clock (A side) -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (Bits 3~2) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 3 -/// @note Page 4.1.2.12.3 - 66 -/// -fapi2::ReturnCode decoder_v1_1::a_side_clk_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< A_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, - A_SIDE_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for clock (Y1,Y3)") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -}// lrdimm -}// ddr4 -}// spd -}// mss diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_2.C b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_2.C deleted file mode 100644 index 029ad635e..000000000 --- a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_2.C +++ /dev/null @@ -1,310 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_2.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2018 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -/// -/// @file lrdimm_decoder_v1_2.C -/// @brief LRDIMM module SPD decoder definitions for revision 1.2 -/// -// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> -// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> -// *HWP Team: Memory -// *HWP Level: 3 -// *HWP Consumed by: HB:FSP - -// std lib -#include <vector> - -// fapi2 -#include <fapi2.H> - -// mss lib -#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <generic/memory/lib/spd/spd_checker.H> -#include <generic/memory/lib/utils/c_str.H> -#include <generic/memory/lib/utils/find.H> - -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_MCS; -using fapi2::TARGET_TYPE_DIMM; - -namespace mss -{ -namespace spd -{ -namespace ddr4 -{ -namespace lrdimm -{ - -/// -/// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE) -/// @param[out] o_output encoded drive strength -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (Bit 4) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 4 -/// @note Page 4.1.2.12.3 - 76 -/// -fapi2::ReturnCode decoder_v1_2::bcom_bcke_bodt_drive_strength(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< BCOM_BODT_BCKE_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, - BCOM_BODT_BCKE_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for data buffer control (BCOM, BODT, BCKE)") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for data buffer control (BCOM, BODT, BCKE): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for data buffer control (BCK) -/// @param[out] o_output encoded drive strength -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (Bit 5) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 4 -/// @note Page 4.1.2.12.3 - 76 -/// -fapi2::ReturnCode decoder_v1_2::bck_output_drive_strength(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< BCK_DRIVE_STRENGTH >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, - BCK_DRIVE_STRENGTH.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for data buffer control (BCK)") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for data buffer control (BCK): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes RCD output slew rate control -/// @param[out] o_output encoded drive strength -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (Bit 6) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 4 -/// @note Page 4.1.2.L-4 - 76 -/// -fapi2::ReturnCode decoder_v1_2::slew_rate_control(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< RCD_SLEW_CNTRL >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 0b1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - RCD_SLEW_CNTRL.iv_byte, - l_field_bits, - "Failed bound check for RCD output slew rate control") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. RCD output slew rate control: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes VrefDQ range for DRAM interface range -/// @param[out] o_output spd encoding -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 155 (Bits 3~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 4 -/// @note Page 4.1.2.L-4 - 76 -/// -fapi2::ReturnCode decoder_v1_2::dram_vref_dq_range(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< DRAM_VREF_DQ_RANGE >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 0b1111; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - DRAM_VREF_DQ_RANGE.iv_byte, - l_field_bits, - "Failed bound check for VrefDQ range for DRAM interface range ") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. VrefDQ range for DRAM interface range: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes data buffer VrefDQ range for DRAM interface range -/// @param[out] o_output spd encoding -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 155 (Bit 4) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 4 -/// @note Page 4.1.2.L-4 - 76 -/// -fapi2::ReturnCode decoder_v1_2::data_buffer_vref_dq_range(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< DATA_BUFFER_VREF_DQ >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - DATA_BUFFER_VREF_DQ.iv_byte, - l_field_bits, - "Failed bound check for data buffer VrefDQ range for DRAM interface range") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Data buffer VrefDQ range for DRAM interface range: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes data buffer gain adjustment -/// @param[out] o_output spd encoding -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 156 (Bit 0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 4 -/// @note Page 4.1.2.L-4 - 77 -/// -fapi2::ReturnCode decoder_v1_2::data_buffer_gain_adjustment(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< DATA_BUFFER_GAIN_ADJUST >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - DATA_BUFFER_GAIN_ADJUST.iv_byte, - l_field_bits, - "Failed bound check for data buffer gain adjustment") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Data buffer gain adjustment: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes data buffer Decision Feedback Equalization (DFE) -/// @param[out] o_output spd encoding -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 156 (Bit 1) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 4 -/// @note Page 4.1.2.L-4 - 77 -/// -fapi2::ReturnCode decoder_v1_2::data_buffer_dfe(uint8_t& o_output) const -{ - // Extracting desired bits - uint8_t l_field_bits = extract_spd_field< DATA_BUFFER_DFE >(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VAL = 1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VAL, // extract sanity check - DATA_BUFFER_DFE.iv_byte, - l_field_bits, - "Failed bound check for data buffer Decision Feedback Equalization (DFE)") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Data buffer Decision Feedback Equalization (DFE): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -}// lrdimm -}// ddr4 -}// spd -}// mss diff --git a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H index 0ec15c90e..96290460b 100644 --- a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H +++ b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H @@ -38,137 +38,79 @@ #include <fapi2.H> #include <generic/memory/lib/spd/common/dimm_module_decoder.H> +#include <generic/memory/lib/spd/spd_decoder_def.H> +#include <generic/memory/lib/spd/spd_traits_ddr4.H> +#include <generic/memory/lib/spd/spd_reader.H> namespace mss { namespace spd { -namespace ddr4 -{ -namespace rdimm -{ /// /// @class decoder -/// @brief RDIMM module SPD DRAM decoder for rev 1.0 +/// @tparam R SPD revision - partial specialization +/// @brief RDIMM module SPD DRAM decoder /// -class decoder_v1_0 : public dimm_module_decoder +template < rev R > +class decoder<DDR4, RDIMM_MODULE, R > : public dimm_module_decoder { - protected: + private: - enum - { - // Byte 128 - MODULE_NOM_HEIGHT_START = 3, - MODULE_NOM_HEIGHT_LEN = 5, - RAW_CARD_EXT_START = 0, - RAW_CARD_EXT_LEN = 3, - - // Byte 129 - FRONT_MODULE_THICKNESS_START = 4, - FRONT_MODULE_THICKNESS_LEN = 4, - BACK_MODULE_THICKNESS_START = 0, - BACK_MODULE_THICKNESS_LEN = 4, - - // Byte 130 - REF_RAW_CARD_START = 3, - REF_RAW_CARD_LEN = 5, - REF_RAW_CARD_REV_START = 1, - REF_RAW_CARD_REV_LEN = 2, - REF_RAW_CARD_EXT_START = 0, - REF_RAW_CARD_EXT_LEN = 1, - - // Byte 131 - REGS_USED_START = 6, - REGS_USED_LEN = 2, - ROWS_OF_DRAMS_START = 4, - ROWS_OF_DRAMS_LEN = 2, - REGISTER_TYPE_START = 0, - REGISTER_TYPE_LEN = 4, - - // Byte 132 - HEAT_SPREADER_CHAR_START = 1, - HEAT_SPREADER_CHAR_LEN = 7, - HEAT_SPREADER_SOL_START = 0, - HEAT_SPREADER_SOL_LEN = 1, - - // Byte 133 - CONTINUATION_CODES_START = 1, - CONTINUATION_CODES_LEN = 7, - - // Byte 134 - whole byte taken - // Byte 135 - whole byte taken - - // Byte 136 - ADDR_MAPPING_START = 7, - ADDR_MAPPING_LEN = 1, - - // Byte 137 - CKE_DRIVER_START = 6, - CKE_DRIVER_LEN = 2, - ODT_DRIVER_START = 4, - ODT_DRIVER_LEN = 2, - CA_DRIVER_START = 2, - CA_DRIVER_LEN = 2, - CS_DRIVER_START = 0, - CS_DRIVER_LEN = 2, - - // Byte 138 - YO_Y2_DRIVER_START = 6, - YO_Y2_DRIVER_LEN = 2, - Y1_Y3_DRIVER_START = 4, - Y1_Y3_DRIVER_LEN = 2, - }; - - enum addr_mapping - { - STANDARD = 0, - MIRRORED = 1, - }; + using fields_t = fields<DDR4, RDIMM_MODULE>; + fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + std::vector<uint8_t> iv_data; public: - // First field - SPD byte - // Second field - start bit - // Third field - bit length - static constexpr field_t MODULE_NOMINAL_HEIGHT{128, MODULE_NOM_HEIGHT_START, MODULE_NOM_HEIGHT_LEN}; - static constexpr field_t RAW_CARD_EXTENSION{128, RAW_CARD_EXT_START, RAW_CARD_EXT_LEN}; - static constexpr field_t FRONT_MODULE_THICKNESS{129, FRONT_MODULE_THICKNESS_START, FRONT_MODULE_THICKNESS_LEN}; - static constexpr field_t BACK_MODULE_THICKNESS{129, BACK_MODULE_THICKNESS_START, BACK_MODULE_THICKNESS_LEN}; - static constexpr field_t REF_RAW_CARD{130, REF_RAW_CARD_START, REF_RAW_CARD_LEN}; - static constexpr field_t REF_RAW_CARD_REV{130, REF_RAW_CARD_REV_START, REF_RAW_CARD_REV_LEN}; - static constexpr field_t REF_RAW_CARD_EXT{130, REF_RAW_CARD_EXT_START, REF_RAW_CARD_EXT_LEN}; - static constexpr field_t NUM_REGS_USED{131, REGS_USED_START, REGS_USED_LEN}; - static constexpr field_t ROWS_OF_DRAMS{131, ROWS_OF_DRAMS_START, ROWS_OF_DRAMS_LEN}; - static constexpr field_t REGISTER_TYPE{131, REGISTER_TYPE_START, REGISTER_TYPE_LEN}; - static constexpr field_t HEAT_SPREADER_CHAR{132, HEAT_SPREADER_CHAR_START, HEAT_SPREADER_CHAR_LEN}; - static constexpr field_t HEAT_SPREADER_SOL{132, HEAT_SPREADER_SOL_START, HEAT_SPREADER_SOL_LEN}; - static constexpr field_t CONTINUATION_CODES{133, CONTINUATION_CODES_START, CONTINUATION_CODES_LEN}; - static constexpr field_t ADDR_MAPPING{136, ADDR_MAPPING_START, ADDR_MAPPING_LEN}; - static constexpr field_t CKE_DRIVER{137, CKE_DRIVER_START, CKE_DRIVER_LEN}; - static constexpr field_t ODT_DRIVER{137, ODT_DRIVER_START, ODT_DRIVER_LEN}; - static constexpr field_t CA_DRIVER{137, CA_DRIVER_START, CA_DRIVER_LEN}; - static constexpr field_t CS_DRIVER{137, CS_DRIVER_START, CS_DRIVER_LEN}; - static constexpr field_t YO_Y2_DRIVER{138, YO_Y2_DRIVER_START, YO_Y2_DRIVER_LEN}; - static constexpr field_t Y1_Y3_DRIVER{138, Y1_Y3_DRIVER_START, Y1_Y3_DRIVER_LEN}; - // deleted default ctor - decoder_v1_0() = delete; + decoder() = delete; /// /// @brief ctor /// @param[in] i_target dimm target /// @param[in] i_spd_data vector DIMM SPD data /// - decoder_v1_0(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data): - dimm_module_decoder(i_target, i_spd_data) - {} + decoder(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data): + dimm_module_decoder(i_target, i_spd_data), + iv_target(i_target), + iv_data(i_spd_data) + { + static_assert( R <= rev::RDIMM_MAX, " R > rev::RDIMM_MAX"); + } /// /// @brief default dtor /// - virtual ~decoder_v1_0() = default; + virtual ~decoder() = default; + + /// + /// @brief Gets decoder target + /// @return fapi2::Target<fapi2::TARGET_TYPE_DIMM> + /// + virtual fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_dimm_target() const + { + return iv_target; + } + + /// + /// @brief Gets decoder SPD data + /// @return std::vector<uint8_t> + /// + virtual std::vector<uint8_t> get_data() const + { + return iv_data; + } + + /// + /// @brief Sets decoder SPD data + /// @param[in] i_spd_data SPD data in a vector reference + /// + virtual void set_data(const std::vector<uint8_t>& i_spd_data) + { + iv_data = i_spd_data; + } /// /// @brief Decodes module nominal height max, in mm @@ -179,7 +121,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 48 /// - virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) const override; + virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::MODULE_NOMINAL_HEIGHT, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes front module maximum thickness max, in mm @@ -190,7 +138,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 48 /// - virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) const override; + virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::FRONT_MODULE_THICKNESS, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes back module maximum thickness max, in mm @@ -201,7 +155,30 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 48 /// - virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) const override; + virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::BACK_MODULE_THICKNESS, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes reference raw card used + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 130 (Bits 7~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12 - 48 + /// + virtual fapi2::ReturnCode reference_raw_card(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::REF_RAW_CARD, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes number of registers used on RDIMM @@ -212,7 +189,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 50 /// - virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) const override; + virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::NUM_REGS_USED, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes number of rows of DRAMs on RDIMM @@ -223,7 +206,31 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 50 /// - virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) const override; + virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::ROWS_OF_DRAMS, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + + } + + /// + /// @brief Decodes register types + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 131 (Bits 7~4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 63 + /// + virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::REGISTER_TYPE, R>(iv_target, iv_data, o_output)) ); + fapi_try_exit: + return fapi2::current_err; + + } /// /// @brief Decodes heat spreader thermal characteristics @@ -234,7 +241,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 51 /// - virtual fapi2::ReturnCode heat_spreader_thermal_char(uint8_t& o_output) const override; + virtual fapi2::ReturnCode heat_spreader_thermal_char(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::HEAT_SPREADER_CHAR, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes heat spreader solution @@ -245,18 +258,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 51 /// - virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) const override; + virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::HEAT_SPREADER_SOL, R>(iv_target, iv_data, o_output)) ); - /// - /// @brief Decodes number of continuation codes - /// @param[out] o_output drive strength encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 133 (bit 6~0) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 51 - /// - virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output) const override; + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register manufacturer ID code @@ -267,7 +275,28 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 51 /// - virtual fapi2::ReturnCode reg_manufacturer_id_code(uint8_t& o_output) const override; + virtual fapi2::ReturnCode reg_manufacturer_id_code(uint16_t& o_output) const override + { + uint8_t l_cont_codes = 0; + uint8_t l_last_nonzero_byte = 0; + + FAPI_TRY( (mss::spd::reader<fields_t::CONTINUATION_CODES, R>(iv_target, iv_data, l_cont_codes)) ); + FAPI_TRY( (mss::spd::reader<fields_t::LAST_NON_ZERO_BYTE, R>(iv_target, iv_data, l_last_nonzero_byte)) ); + + { + fapi2::buffer<uint16_t> l_buffer; + rightAlignedInsert(l_buffer, l_last_nonzero_byte, l_cont_codes); + + o_output = l_buffer; + + FAPI_INF("%s. Register Manufacturer ID Code: 0x%04x", + spd::c_str(iv_target), + o_output); + } + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register revision number @@ -278,7 +307,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 51 /// - virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) const override; + virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::REGISTER_REV, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes address mapping from register to dram @@ -289,7 +324,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 52 /// - virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) const override; + virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::ADDR_MAP_REG_TO_DRAM, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for CKE signal @@ -300,7 +341,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 53 /// - virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::CKE_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for ODT signal @@ -311,7 +358,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 53 /// - virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::ODT_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for command/address (CA) signal @@ -322,7 +375,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 53 /// - virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::CA_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for control signal (CS) signal @@ -333,7 +392,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 53 /// - virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::CS_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for clock (B side) @@ -344,7 +409,13 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 53 /// - virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::YO_Y2_DRIVER, R>(iv_target, iv_data, o_output)) ); + + fapi_try_exit: + return fapi2::current_err; + } /// /// @brief Decodes register output drive strength for clock (A side) @@ -355,106 +426,17 @@ class decoder_v1_0 : public dimm_module_decoder /// @note DDR4 SPD Document Release 2 /// @note Page 4.1.2.12 - 53 /// - virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) const override; - -};// decoder_v1_0 - -/// -/// @class decoder -/// @brief RDIMM module SPD DRAM decoder for rev 1.1 -/// -class decoder_v1_1 : public decoder_v1_0 -{ - public: - - // deleted default ctor - decoder_v1_1() = delete; - - /// - /// @brief ctor - /// @param[in] i_target dimm target - /// @param[in] i_spd_data vector DIMM SPD data - /// - decoder_v1_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data): - decoder_v1_0(i_target, i_spd_data) - {} - - /// - /// @brief default dtor - /// - virtual ~decoder_v1_1() = default; - - /// - /// @brief Decodes register types - /// @param[out] o_output encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 131 (Bits 7~4) - /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 3 - /// @note Page 4.1.2.12.3 - 63 - /// - virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output) const override; - - /// - /// @brief Decodes register output drive strength for CKE signal - /// @param[out] o_output drive strength encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (bit 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 76 - /// @note DDR4 SPD Document Release 4 - /// - virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) const override; - - /// - /// @brief Decodes register output drive strength for ODT signal - /// @param[out] o_output drive strength encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (bit 3~2) - /// @note Item JC-45-2220.01x - /// @note Page 76 - /// @note DDR4 SPD Document Release 4 - /// - virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) const override; - - /// - /// @brief Decodes register output drive strength for control signal (CS) signal - /// @param[out] o_output drive strength encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (bit 6~7) - /// @note Item JC-45-2220.01x - /// @note Page 76 - /// @note DDR4 SPD Document Release 4 - /// - virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) const override; + virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) const override + { + FAPI_TRY( (mss::spd::reader<fields_t::Y1_Y3_DRIVER, R>(iv_target, iv_data, o_output)) ); - /// - /// @brief Decodes register output drive strength for clock (B side) - /// @param[out] o_output drive strength encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 138 (bit 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 76 - /// @note DDR4 SPD Document Release 4 - /// - virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) const override; + fapi_try_exit: + return fapi2::current_err; + } - /// - /// @brief Decodes register output drive strength for clock (A side) - /// @param[out] o_output drive strength encoding from SPD - /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 138 (bit 3~2) - /// @note Item JC-45-2220.01x - /// @note Page 76 - /// @note DDR4 SPD Document Release 4 - /// - virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) const override; -};//decoder_v1_1 +};// decoder -}// rdimm -}// ddr4 }// spd }// mss diff --git a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_0.C b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_0.C deleted file mode 100644 index 021130412..000000000 --- a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_0.C +++ /dev/null @@ -1,644 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_0.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2018 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -/// -/// @file rdimm_decoder.C -/// @brief RDIMM module specific SPD decoder definitions -/// -// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> -// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> -// *HWP Team: Memory -// *HWP Level: 3 -// *HWP Consumed by: HB:FSP - -// std lib -#include <vector> - -// fapi2 -#include <fapi2.H> - -// mss lib -#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <generic/memory/lib/spd/spd_checker.H> -#include <generic/memory/lib/utils/c_str.H> -#include <generic/memory/lib/utils/find.H> - -using fapi2::TARGET_TYPE_MCBIST; -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_MCS; -using fapi2::TARGET_TYPE_DIMM; - - -namespace mss -{ -namespace spd -{ -namespace ddr4 -{ -namespace rdimm -{ - -///////////////////////// -// Member Method implementation -// For RDIMM module rev 1.0 -///////////////////////// - -/// -/// @brief Decodes module nominal height max, in mm -/// @param[out] o_output height range encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 128 (Bits 4~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 48 -/// -fapi2::ReturnCode decoder_v1_0::max_module_nominal_height(uint8_t& o_output) const -{ - const uint8_t l_field_bits = extract_spd_field<MODULE_NOMINAL_HEIGHT>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 0b11111; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - MODULE_NOMINAL_HEIGHT.iv_byte, - l_field_bits, - "Failed bound check for module nominal height max") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Max module nominal height: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes front module maximum thickness max, in mm -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 129 (Bits 3~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 48 -/// -fapi2::ReturnCode decoder_v1_0::front_module_max_thickness(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<FRONT_MODULE_THICKNESS>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 0b1111; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - FRONT_MODULE_THICKNESS.iv_byte, - l_field_bits, - "Failed bound check for front module max thickness") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Front module max thickness: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes back module maximum thickness max, in mm -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 129 (Bits 7~4) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 48 -/// -fapi2::ReturnCode decoder_v1_0::back_module_max_thickness(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<BACK_MODULE_THICKNESS>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 0b1111; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - BACK_MODULE_THICKNESS.iv_byte, - l_field_bits, - "Failed bound check for back module max thickness") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Back module max thickness: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes number of registers used on RDIMM -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 131 (Bits 1~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 50 -/// -fapi2::ReturnCode decoder_v1_0::num_registers_used(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<NUM_REGS_USED>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 0b11; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - NUM_REGS_USED.iv_byte, - l_field_bits, - "Failed bound check for number of registers used on RDIMM ") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Number of registers used on RDIMM : %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes number of rows of DRAMs on RDIMM -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 131 (Bits 3~2) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 50 -/// -fapi2::ReturnCode decoder_v1_0::num_rows_of_drams(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<ROWS_OF_DRAMS>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 0b11; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - ROWS_OF_DRAMS.iv_byte, - l_field_bits, - "Failed bound check for number of rows of DRAMs on RDIMM ") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Number of rows of DRAMs on RDIMM : %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes heat spreader thermal characteristics -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCEawSS if okay -/// @note SPD Byte 132 (Bits 6~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 51 -/// -fapi2::ReturnCode decoder_v1_0::heat_spreader_thermal_char(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<HEAT_SPREADER_CHAR>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - HEAT_SPREADER_CHAR.iv_byte, - l_field_bits, - "Failed bound check for heat spreader thermal characteristics") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Heat spreader thermal characteristics: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes heat spreader solution -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 132 (Bit 7) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 51 -/// -fapi2::ReturnCode decoder_v1_0::heat_spreader_solution(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<HEAT_SPREADER_SOL>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 1; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - HEAT_SPREADER_SOL.iv_byte, - l_field_bits, - "Failed bound check for heat spreader solution") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Heat spreader solution: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - - -/// -/// @brief Decodes number of continuation codes -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 133 (bit 6~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 51 -/// -fapi2::ReturnCode decoder_v1_0::num_continuation_codes(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<CONTINUATION_CODES>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t MAX_VALID_VALUE = 10; // JEP106AS - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits <= MAX_VALID_VALUE, - CONTINUATION_CODES.iv_byte, - l_field_bits, - "Failed bound check for number of continuation codes") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Number of continuation codes: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes register manufacturer ID code -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 134 (bit 7~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 51 -/// -fapi2::ReturnCode decoder_v1_0::reg_manufacturer_id_code(uint8_t& o_output) const -{ - constexpr size_t BYTE_INDEX = 134; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - l_raw_byte); - - o_output = l_raw_byte; - - FAPI_INF("%s. Manufacturer ID code: %d", - iv_target_str_storage, - o_output); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes register revision number -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 135 (bit 7~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 51 -/// -fapi2::ReturnCode decoder_v1_0::register_rev_num(uint8_t& o_output) const -{ - constexpr size_t BYTE_INDEX = 135; - uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - iv_target_str_storage, - BYTE_INDEX, - l_raw_byte); - - o_output = l_raw_byte; - - FAPI_INF("%s. Register revision number: %d", - iv_target_str_storage, - o_output); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Decodes address mapping from register to dram -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 136 (bit 0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 52 -/// -fapi2::ReturnCode decoder_v1_0::register_to_dram_addr_mapping(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<ADDR_MAPPING>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 0b11; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - ADDR_MAPPING.iv_byte, - l_field_bits, - "Failed bound check for to register to dram addr mapping") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Address mapping from register to dram: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for CKE signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 1~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 53 -/// -fapi2::ReturnCode decoder_v1_0::cke_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<CKE_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - CKE_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for CKE") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CKE: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for ODT signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 3~2) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 53 -/// -fapi2::ReturnCode decoder_v1_0::odt_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<ODT_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - ODT_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for ODT") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for ODT: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for command/address (CA) signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 5~4) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 53 -/// -fapi2::ReturnCode decoder_v1_0::ca_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<CA_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t INVALID_VAL = 3; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < INVALID_VAL, // extract sanity check - CA_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for CA") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CA: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for control signal (CS) signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 6~7) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 53 -/// -fapi2::ReturnCode decoder_v1_0::cs_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<CS_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - CS_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for CS") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CS: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for clock (B side) -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (bit 1~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 53 -/// -fapi2::ReturnCode decoder_v1_0::b_side_clk_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<YO_Y2_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, // extract sanity check - YO_Y2_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for clock (Y0,Y2)") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for clock (A side) -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (bit 3~2) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @note Page 4.1.2.12 - 53 -/// -fapi2::ReturnCode decoder_v1_0::a_side_clk_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<Y1_Y3_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field_Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - l_field_bits < RESERVED, - Y1_Y3_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for clock (Y1,Y3)") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -}// rdimm -}// ddr4 -}// spd -}// mss diff --git a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_1.C b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_1.C deleted file mode 100644 index 9a6aa5446..000000000 --- a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_1.C +++ /dev/null @@ -1,268 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_1.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2018 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -// std lib -#include <vector> - -// fapi2 -#include <fapi2.H> - -// mss lib -#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <generic/memory/lib/spd/spd_checker.H> -#include <generic/memory/lib/utils/c_str.H> -#include <generic/memory/lib/utils/find.H> - -using fapi2::TARGET_TYPE_MCBIST; -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_MCS; -using fapi2::TARGET_TYPE_DIMM; - - -namespace mss -{ -namespace spd -{ -namespace ddr4 -{ -namespace rdimm -{ - -///////////////////////// -// Member Method implementation -// For RDIMM module rev 1.1 -///////////////////////// - -/// -/// @brief Decodes register type -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 131 (Bits 7~4) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 3 -/// @note Page 4.1.2.12.3 - 63 -/// -fapi2::ReturnCode decoder_v1_1::register_and_buffer_type(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<REGISTER_TYPE>(iv_target, iv_spd_data); - FAPI_INF("Field Bits value: %d", l_field_bits); - - // This checks my extracting params returns a value within bound - constexpr size_t RESERVED = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - (l_field_bits < RESERVED), // extract sanity check - REGISTER_TYPE.iv_byte, - l_field_bits, - "Failed bounds check for Register and Data Buffer Types") ); - - // Update output only if check passes - o_output = l_field_bits; - - FAPI_INF("%s. Register Types: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Decodes register output drive strength for CKE signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 1~0) -/// @note Item JC-45-2220.01x -/// @note Page 76 -/// @note DDR4 SPD Document Release 4 -/// -fapi2::ReturnCode decoder_v1_1::cke_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<CKE_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // This really just checks my extract gives me a valid value - constexpr size_t MAX_VALID_VALUE = 0b11; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - (l_field_bits <= MAX_VALID_VALUE), // extract sanity check - CKE_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for CKE") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CKE: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for ODT signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 3~2) -/// @note Item JC-45-2220.01x -/// @note Page 76 -/// @note DDR4 SPD Document Release 4 -/// -fapi2::ReturnCode decoder_v1_1::odt_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<ODT_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // This really just checks my extract gives me a valid value - constexpr size_t MAX_VALID_VALUE = 0b11; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - (l_field_bits <= MAX_VALID_VALUE), // extract sanity check - ODT_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for ODT") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for ODT: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for control signal (CS) signal -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 137 (bit 6~7) -/// @note Item JC-45-2220.01x -/// @note Page 76 -/// @note DDR4 SPD Document Release 4 -/// -fapi2::ReturnCode decoder_v1_1::cs_signal_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<CS_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // This really just checks my extract gives me a valid value - constexpr size_t MAX_VALID_VALUE = 0b11; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - (l_field_bits <= MAX_VALID_VALUE), // extract sanity check - CS_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for chip select") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for CS: %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for clock (B side) -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (bit 1~0) -/// @note Item JC-45-2220.01x -/// @note Page 76 -/// @note DDR4 SPD Document Release 4 -/// -fapi2::ReturnCode decoder_v1_1::b_side_clk_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<YO_Y2_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // This really just checks my extract gives me a valid value - constexpr size_t MAX_VALID_VAL = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - (l_field_bits <= MAX_VALID_VAL), // extract sanity check - YO_Y2_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for clock (Y0,Y2)") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes register output drive strength for clock (A side) -/// @param[out] o_output drive strength encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 138 (bit 3~2) -/// @note Item JC-45-2220.01x -/// @note Page 76 -/// @note DDR4 SPD Document Release 4 -/// -fapi2::ReturnCode decoder_v1_1::a_side_clk_output_driver(uint8_t& o_output) const -{ - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field<Y1_Y3_DRIVER>(iv_target, iv_spd_data); - FAPI_DBG("Field Bits value: %d", l_field_bits); - - // This really just checks my extract gives me a valid value - constexpr size_t MAX_VALID_VAL = 2; - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, - (l_field_bits <= MAX_VALID_VAL), // extract sanity check - Y1_Y3_DRIVER.iv_byte, - l_field_bits, - "Failed bounds check for Register Output Driver for clock (Y1,Y3)") ); - - o_output = l_field_bits; - - FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d", - iv_target_str_storage, - o_output); - -fapi_try_exit: - return fapi2::current_err; -} - -}// rdimm -}// ddr4 -}// spd -}// mss diff --git a/src/import/generic/memory/lib/spd/spd_checker.H b/src/import/generic/memory/lib/spd/spd_checker.H index d3a85aaa4..a26ac4741 100644 --- a/src/import/generic/memory/lib/spd/spd_checker.H +++ b/src/import/generic/memory/lib/spd/spd_checker.H @@ -23,42 +23,130 @@ /* */ /* IBM_PROLOG_END_TAG */ +/// +/// @file spd_checker.H +/// @brief SPD functions to check boundaries +/// +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: HB:FSP + #ifndef _SPD_CHECKER_H_ #define _SPD_CHECKER_H_ #include <fapi2.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> namespace mss { -namespace check + +/// +/// @brief Selectors for timing limits +/// @note BITS12 stands for a 12 bit range +/// @note BITS16 stands for a 16 bit range +/// +enum bit_len +{ + BITS12 = 12, + BITS16 = 16, +}; + +/// +/// @class bitRangeTraits +/// @brief Traits class to select +/// @tparam T bit_len selector +/// +template <bit_len T> +struct bitRangeTraits; + +/// +/// @class bitRangeTraits +/// @brief Traits class to select - BITS12 specialization +/// +template<> +struct bitRangeTraits<BITS12> +{ + enum + { + LOWER_BOUND = 0x1, + UPPER_BOUND = 0xfff, + }; +}; + +/// +/// @class bitRangeTraits +/// @brief Traits class to select - BITS16 specialization +/// +template<> +struct bitRangeTraits<BITS16> { + enum + { + LOWER_BOUND = 0x1, + UPPER_BOUND = 0xffff, + }; +}; + namespace spd { +namespace check +{ + +/// +/// @brief SPD timing boundary check +/// @tparam BL bit_len selector +/// @tparam T the TargetType +/// @tparam TT defaulted to bitRangeTraits<TB> +/// @param[in] i_target fapi2 target +/// @param[in] i_timing the timing value +/// @param[in] i_ffdc ffdc function code +/// @return FAPI2_RC_SUCCESS iff okay +/// +template < bit_len BL, fapi2::TargetType T, typename TT = bitRangeTraits<BL> > +fapi2::ReturnCode max_timing_range(const fapi2::Target<T>& i_target, + const int64_t i_timing, + const generic_ffdc_codes i_ffdc) +{ + FAPI_ASSERT( (i_timing <= TT::UPPER_BOUND) && + (i_timing >= TT::LOWER_BOUND), + fapi2::MSS_SPD_TIMING_FAIL() + .set_FUNCTION_CODE(i_ffdc) + .set_TARGET(i_target), + "Failed timing parameter check for %s", + spd::c_str(i_target)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} /// -/// @brief Checks conditional passes and implements traces & exits if it fails -/// @tparam T input data of any size -/// @param[in] i_target fapi2 dimm target -/// @param[in] i_conditional conditional that we are testing against -/// @param[in] i_spd_byte_index current SPD byte -/// @param[in] i_spd_data debug data -/// @param[in] i_err_str error string to print out when conditional fails -/// @return ReturnCode +/// @brief Checks conditional passes and implements traces & exits if it fails +/// @tparam T input data of any size +/// @param[in] i_target fapi2 dimm target +/// @param[in] i_conditional conditional that we are testing against +/// @param[in] i_spd_byte_index current SPD byte +/// @param[in] i_spd_data debug data +/// @param[in] i_err_str error string to print out when conditional fails +/// @return FAPI2_RC_SUCCESS iff okay /// template< typename T > inline fapi2::ReturnCode fail_for_invalid_value(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, const bool i_conditional, const size_t i_spd_byte_index, const T i_spd_data, - const char* i_err_str) + const char* i_err_str = "") { FAPI_ASSERT(i_conditional, fapi2::MSS_BAD_SPD(). set_VALUE(i_spd_data). set_BYTE(i_spd_byte_index). set_DIMM_TARGET(i_target), - "%s %s Byte %d, Data returned: %d.", - c_str(i_target), + "%s %s Byte %d, data 0x%02x, extracted value: 0x%02x.", + spd::c_str(i_target), i_err_str, i_spd_byte_index, i_spd_data); @@ -67,70 +155,136 @@ inline fapi2::ReturnCode fail_for_invalid_value(const fapi2::Target<fapi2::TARGE fapi_try_exit: return fapi2::current_err; -} // fail_for_invalid_value() +} // fail_for_invalid_value /// -/// @brief Checks conditional passes and implements traces if it fails. No FFDC collected. -/// @tparam T input data of any size -/// @param[in] i_target fapi2 dimm target -/// @param[in] i_conditional that we are testing against -/// @param[in] i_spd_byte_index -/// @param[in] i_spd_data debug data -/// @param[in] i_err_str string to print out when conditional fails -/// @return void +/// @brief Helper function to test if a DRAM generation is valid +/// @param[in] i_dram_gen the DRAM gen from SPD +/// @return true if this DRAM gen is valid, else false /// -template< typename T > -inline void warn_for_invalid_value(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const bool i_conditional, - const size_t i_spd_byte_index, - const T i_spd_data, - const char* i_err_str) +static inline bool is_dram_gen_valid(const uint8_t i_dram_gen) +{ + bool l_result = false; + + switch(i_dram_gen) + { + case DDR4: + l_result = true; + break; + + default: + l_result = false; + break; + } + + return l_result; +} + +/// +/// @brief Checks for valid DRAM generation +/// @param[in] i_target the DIMM target +/// @param[in] i_dram_gen the DRAM gen from SPD +/// @param[in] i_func_code mss ffdc code +/// @return FAPI2_RC_SUCCESS iff okay +/// +inline fapi2::ReturnCode dram_gen(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const uint8_t i_dram_gen, + const generic_ffdc_codes i_func_code) +{ + FAPI_ASSERT(is_dram_gen_valid(i_dram_gen), + fapi2::MSS_INVALID_DRAM_GEN() + .set_DRAM_GEN(i_dram_gen) + .set_FUNCTION(i_func_code) + .set_DIMM_TARGET(i_target), + "Invalid DRAM gen recieved (%d) for %s", + i_dram_gen, spd::c_str(i_target)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function to test if a DIMM type is valid +/// @param[in] i_dimm_type the DIMM type from SPD +/// @return true if this DIMM type is valid, else false +/// +static inline bool is_dimm_type_valid(const uint8_t i_dimm_type) { - // Don't print warning conditional if true - if(!i_conditional) + bool l_result = false; + + switch(i_dimm_type) { - FAPI_IMP("%s. %s. Byte %d, Data returned: %d.", - c_str(i_target), - i_err_str, - i_spd_byte_index, - i_spd_data ); + case RDIMM: + case LRDIMM: + l_result = true; + break; + + default: + l_result = false; + break; } -}// warn_for_invalid_value - -/// -/// @brief Checks if valid factory parameters are given -/// @param[in] i_target fapi2 dimm target -/// @param[in] i_dimm_type DIMM type enumeration -/// @param[in] i_encoding_rev SPD encoding level rev number -/// @param[in] i_additions_rev SPD additions level rev number -/// @param[in] i_err_str string to print out when conditional fails -/// @return fapi2::ReturnCode -/// -inline fapi2::ReturnCode invalid_factory_sel(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const uint8_t i_dimm_type, - const uint8_t i_encoding_rev, - const uint8_t i_additions_rev, - const char* i_err_str) + + return l_result; +} + +/// +/// @brief Checks for valid DIMM type +/// @param[in] i_target the DIMM target +/// @param[in] i_dram_gen the DIMM type from SPD +/// @param[in] i_func_code mss ffdc code +/// @return FAPI2_RC_SUCCESS iff okay +/// +inline fapi2::ReturnCode dimm_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const uint8_t i_dimm_type, + const generic_ffdc_codes i_func_code) { - FAPI_ASSERT(false, - fapi2::MSS_INVALID_DIMM_REV_COMBO(). - set_DIMM_TYPE(i_dimm_type). - set_ENCODING_REV(i_encoding_rev). - set_ADDITIONS_REV(i_additions_rev). - set_DIMM_TARGET(i_target), - "%s. %s. Invalid combination for dimm type: %d, rev: %d.%d", - c_str(i_target), - i_err_str, - i_dimm_type, - i_encoding_rev, - i_additions_rev); + FAPI_ASSERT(is_dimm_type_valid(i_dimm_type), + fapi2::MSS_INVALID_DIMM_TYPE() + .set_DIMM_TYPE(i_dimm_type) + .set_FUNCTION(i_func_code) + .set_DIMM_TARGET(i_target), + "Invalid DIMM type recieved (%d) for %s", + i_dimm_type, spd::c_str(i_target)); + return fapi2::FAPI2_RC_SUCCESS; + fapi_try_exit: return fapi2::current_err; -}// invalid_factory_sel +} + +/// +/// @brief Helper function to check for reserved values +/// @tparam TT FAPI2 target type +/// @param[in] i_target the fapi2 target +/// @param[in] i_reserved_bits vector of SORTED reserved bits to sort through +/// @param[in] i_ffdc ffdc function code +/// @param[in] i_input value to check +/// @return FAPI2_RC_SUCCESS iff okay +/// +template < fapi2::TargetType TT > +inline fapi2::ReturnCode reserved_values(const fapi2::Target<TT>& i_target, + const std::vector<uint8_t>& i_reserved_bits, + const generic_ffdc_codes i_ffdc, + const uint8_t i_input) +{ + // Lets make an additional check that we aren't being set to a reserved field + FAPI_ASSERT( !std::binary_search(i_reserved_bits.begin(), i_reserved_bits.end(), i_input), + fapi2::MSS_INVALID_SPD_RESERVED_BITS() + .set_FUNCTION_CODE(i_ffdc) + .set_TARGET(i_target), + "Reserved bits seen on %s", + spd::c_str(i_target) ); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} -}// spd }// check +}// spd }// mss #endif diff --git a/src/import/generic/memory/lib/spd/spd_decoder_def.H b/src/import/generic/memory/lib/spd/spd_decoder_def.H index fe2ecc46b..9d8378145 100644 --- a/src/import/generic/memory/lib/spd/spd_decoder_def.H +++ b/src/import/generic/memory/lib/spd/spd_decoder_def.H @@ -22,3 +22,38 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file spd_decoder_def.H +/// @brief SPD decoder definition +/// +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_SPD_DECODER_DEF_H_ +#define _MSS_SPD_DECODER_DEF_H_ + +#include <generic/memory/lib/spd/spd_field.H> + +namespace mss +{ +namespace spd +{ + +/// +/// @class decoder +/// @tparam D device type (DDR4, etc.) +/// @tparam S JEDEC SPD parameters (LRDIMM_MODULE, GEN_SEC, etc.) +/// @tparam R SPD revision (e.g. rev 1.1, 1.2, etc.) +/// @brief Base SPD DRAM decoder +/// +template < device_type D, parameters S, rev R > +class decoder; + +}// spd +}// mss + +#endif //_MSS_SPD_DECODER_DEF_H_ diff --git a/src/import/generic/memory/lib/spd/spd_facade.H b/src/import/generic/memory/lib/spd/spd_facade.H index 440d9498a..5c86d7895 100644 --- a/src/import/generic/memory/lib/spd/spd_facade.H +++ b/src/import/generic/memory/lib/spd/spd_facade.H @@ -22,3 +22,1637 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +#ifndef _MSS_SPD_FACADE_H_ +#define _MSS_SPD_FACADE_H_ + +#include <generic/memory/lib/spd/spd_factory_pattern.H> +#include <generic/memory/lib/utils/find.H> +#include <fapi2_spd_access.H> + +namespace mss +{ +namespace spd +{ + +/// +/// @brief Retrieve SPD data +/// @param[in] i_target the DIMM target +/// @param[out] o_spd reference to std::vector +/// @return FAPI2_RC_SUCCESS iff okay +/// +inline fapi2::ReturnCode get_raw_data(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + std::vector<uint8_t>& o_spd) +{ + // Get SPD blob size + size_t l_size = 0; + FAPI_TRY( fapi2::getSPD(i_target, nullptr, l_size), + "%s. Failed to retrieve SPD blob size", spd::c_str(i_target) ); + + // Reassign container size with the retrieved size + // Arbitrarily set the data to zero since it will be overwritten + o_spd.assign(l_size, 0); + + // Retrieve SPD data content + FAPI_TRY( fapi2::getSPD(i_target, o_spd.data(), l_size), + "%s. Failed to retrieve SPD data", spd::c_str(i_target) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @class facade +/// @brief SDP facade to simplify decoder interface +/// @note the facade should be a pass through class, +/// shouldn't be subclassed. Factories should be the work horse. +/// +class facade final +{ + private: + + const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + std::vector<uint8_t> iv_data; + std::shared_ptr<dimm_module_decoder> iv_dimm_module_decoder; + std::shared_ptr<base_cnfg_decoder> iv_base_cnfg_decoder; + + public: + + /// + /// @brief ctor + /// @param[in] i_target the DIMM target + /// @param[in] i_spd_data SPD data in a vector reference + /// @param[out] o_rc FAPI2_RC_SUCCESS iff okay + /// + facade( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data, + fapi2::ReturnCode& o_rc): + iv_target(i_target), + iv_data(i_spd_data) + { + factories l_factories(i_target, i_spd_data, o_rc); + FAPI_TRY(o_rc, "Failed to instantiate factories object for %s", spd::c_str(i_target)); + + FAPI_TRY(l_factories.create_decoder(iv_dimm_module_decoder)); + FAPI_TRY(l_factories.create_decoder(iv_base_cnfg_decoder)); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + + fapi_try_exit: + o_rc = fapi2::current_err; + } + + /// + /// @brief dtor + /// + ~facade() = default; + + /// + /// @brief Gets facade target + /// @return fapi2::Target<fapi2::TARGET_TYPE_DIMM> + /// + fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_dimm_target() const + { + return iv_target; + } + + /// + /// @brief Gets facade SPD data + /// @return std::vector<uint8_t> + /// + std::vector<uint8_t> get_data() const + { + return iv_data; + } + + /// + /// @brief Sets facade SPD data + /// @param[in] i_spd_data SPD data in a vector reference + /// + void set_data(const std::vector<uint8_t>& i_spd_data) + { + // Keep SPD data changes consistent through decoders + iv_data = i_spd_data; + iv_base_cnfg_decoder->set_data(i_spd_data); + iv_dimm_module_decoder->set_data(i_spd_data); + } + + /// + /// @brief Decodes number of used SPD bytes + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode number_of_used_bytes( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->number_of_used_bytes(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes total SPD encoding for total bytes + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode number_of_total_bytes( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->number_of_total_bytes(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDP revision + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode revision( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->revision(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM device type + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode device_type( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->device_type(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes base module type + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode base_module( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->base_module(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM density from SPD + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode sdram_density( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->sdram_density(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes hybrid media + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode hybrid_media( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->hybrid_media(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes hybrid + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode hybrid( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->hybrid(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes number of SDRAM banks bits from SPD + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode bank_bits( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->bank_bits(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes number of SDRAM bank groups bits from SPD + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode bank_group_bits( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->bank_group_bits(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes number of SDRAM column address bits + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode column_address_bits( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->column_address_bits(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes number of SDRAM row address bits + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode row_address_bits( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->row_address_bits(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Primary SDRAM signal loading + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode prim_sdram_signal_loading( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->prim_sdram_signal_loading(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Primary SDRAM die count + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode prim_sdram_die_count( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->prim_sdram_die_count(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Primary SDRAM package type + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode prim_sdram_package_type( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->prim_sdram_package_type(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode SDRAM Maximum activate count + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode maximum_activate_count( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->maximum_activate_count(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode maximum_activate_window_multiplier( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->maximum_activate_window_multiplier(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode Post package repair (PPR) + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode post_package_repair( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->post_package_repair(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode Soft post package repair (soft PPR) + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode soft_post_package_repair( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->soft_post_package_repair(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Secondary SDRAM signal loading + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode sec_sdram_signal_loading( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->sec_sdram_signal_loading(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Secondary DRAM Density Ratio + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode sec_dram_density_ratio( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->sec_dram_density_ratio(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Secondary SDRAM die count + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode sec_sdram_die_count( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->sec_sdram_die_count(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Secondary SDRAM package type + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode sec_sdram_package_type( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->sec_sdram_package_type(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode Module Nominal Voltage, VDD + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode operable_nominal_voltage( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->operable_nominal_voltage(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode Module Nominal Voltage, VDD + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode endurant_nominal_voltage( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->endurant_nominal_voltage(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM device width + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode device_width( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->device_width(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes number of package ranks per DIMM + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode num_package_ranks_per_dimm( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->num_package_ranks_per_dimm(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Rank Mix + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode rank_mix( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->rank_mix(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes primary bus width + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode prim_bus_width( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->prim_bus_width(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes bus width extension + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode bus_width_extension( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->bus_width_extension(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode Module Thermal Sensor + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode thermal_sensor( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->thermal_sensor(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode Extended Base Module Type + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode extended_base_module_type( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->extended_base_module_type(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode Fine Timebase + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_timebase( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_timebase(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode Medium Timebase + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode medium_timebase( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->medium_timebase(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// + /// @brief Decodes SDRAM Minimum Cycle Time in MTB + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_tck( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_tck(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Maximum Cycle Time in MTB + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode max_tck( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->max_tck(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decode CAS Latencies Supported + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode supported_cas_latencies( uint64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->supported_cas_latencies(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Minimum CAS Latency Time in MTB + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_taa( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_taa(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_trcd( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_trcd(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_trp( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_trp(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_tras( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_tras(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_trc( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_trc(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1 + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_trfc1( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_trfc1(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2 + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_trfc2( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_trfc2(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4 + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_trfc4( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_trfc4(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes SDRAM Minimum Four Activate Window Delay Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_tfaw( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_tfaw(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_trrd_s( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_trrd_s(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_trrd_l( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_trrd_l(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_tccd_l( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_tccd_l(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Minimum Write Recovery Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_twr( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_twr(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Minimum Write to Read Time - Different Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_twtr_s( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_twtr_s(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Minimum Write to Read Time - Same Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode min_twtr_l( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->min_twtr_l(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Package Rank Map + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode package_rank_map( std::vector<uint8_t>& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->package_rank_map(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Nibble Map + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode nibble_map( std::vector<uint8_t>& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->nibble_map(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_min_tccd_l( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_tccd_l(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_min_trrd_l( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_trrd_l(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_min_trrd_s( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_trrd_s(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_min_trc( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_trc(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_min_trp( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_trp(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_min_trcd( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_trcd(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_min_taa( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_taa(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_max_tck( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_max_tck(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode fine_offset_min_tck( int64_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_tck(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode cyclical_redundancy_code( uint16_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->cyclical_redundancy_code(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes module manufacturer ID code + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode module_manufacturer_id_code( uint16_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->module_manufacturer_id_code(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Module Manufacturing Location + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode module_manufacturing_location( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->module_manufacturing_location(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodesmodule manufacturing date + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + fapi2::ReturnCode module_manufacturing_date( uint16_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->module_manufacturing_date(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes module's unique serial number + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode module_serial_number( uint32_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->module_serial_number(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes Module Revision Code + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode module_revision_code( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->module_revision_code(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM Manufacturer ID code + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->dram_manufacturer_id_code(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM Stepping + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode dram_stepping( uint8_t& o_value ) const + { + FAPI_TRY( iv_base_cnfg_decoder->dram_stepping(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + /// + /// @brief Decodes module nominal height max + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode max_module_nominal_height(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->max_module_nominal_height(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes raw card extension + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode raw_card_extension(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->raw_card_extension(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes front module maximum thickness max + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode front_module_max_thickness(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->front_module_max_thickness(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes back module maximum thickness max + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode back_module_max_thickness(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->back_module_max_thickness(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes reference raw card used + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode reference_raw_card(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->reference_raw_card(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes number of registers used on RDIMM + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode num_registers_used(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->num_registers_used(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes number of rows of DRAMs on RDIMM + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode num_rows_of_drams(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->num_rows_of_drams(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register and buffer type for LRDIMMs + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode register_and_buffer_type(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->register_and_buffer_type(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes heat spreader thermal characteristics + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCEawSS if okay + /// + fapi2::ReturnCode heat_spreader_thermal_char(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->heat_spreader_thermal_char(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes heat spreader solution + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode heat_spreader_solution(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->heat_spreader_solution(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register manufacturer ID code + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode reg_manufacturer_id_code(uint16_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->reg_manufacturer_id_code(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register revision number + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode register_rev_num(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->register_rev_num(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes address mapping from register to dram + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->register_to_dram_addr_mapping(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for CKE signal + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->cke_signal_output_driver(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for ODT signal + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->odt_signal_output_driver(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for command/address (CA) signal + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->ca_signal_output_driver(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for control signal (CS) signal + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->cs_signal_output_driver(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for clock (B side) + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->b_side_clk_output_driver(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for clock (A side) + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->a_side_clk_output_driver(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE) + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode bcom_bcke_bodt_drive_strength(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->bcom_bcke_bodt_drive_strength(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes register output drive strength for data buffer control (BCK) + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode bck_output_drive_strength(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->bck_output_drive_strength(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes RCD output slew rate control + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode slew_rate_control(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->slew_rate_control(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes data buffer revision number + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode data_buffer_rev(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->data_buffer_rev(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 0 + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_vref_dq_rank0(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_vref_dq_rank0(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 1 + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_vref_dq_rank1(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_vref_dq_rank1(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 2 + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_vref_dq_rank2(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_vref_dq_rank2(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 3 + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_vref_dq_rank3(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_vref_dq_rank3(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes data buffer VrefDQ for DRAM interface + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode data_buffer_vref_dq(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->data_buffer_vref_dq(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM interface MDQ Drive Strenth + /// of the data buffer component for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode data_buffer_mdq_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->data_buffer_mdq_drive_strength(i_dimm_speed, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM interface MDQ read termination strength + /// of the data buffer component for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->data_buffer_mdq_rtt(i_dimm_speed, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM drive strenth + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_drive_strength(i_dimm_speed, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM ODT for RTT_NOM + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_rtt_nom(i_dimm_speed, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM ODT for RTT_WR + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_rtt_wr(i_dimm_speed, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 0 & 1 + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_rtt_park_ranks0_1(i_dimm_speed, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3 + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_rtt_park_ranks2_3(i_dimm_speed, o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes VrefDQ range for DRAM interface range + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_vref_dq_range(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->dram_vref_dq_range(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes data buffer VrefDQ range for DRAM interface range + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode data_buffer_vref_dq_range(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->data_buffer_vref_dq_range(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes data buffer gain adjustment + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode data_buffer_gain_adjustment(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->data_buffer_gain_adjustment(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Decodes data buffer Decision Feedback Equalization (DFE) + /// @param[out] o_value SPD encoded value + /// @return FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode data_buffer_dfe(uint8_t& o_value) const + { + FAPI_TRY( iv_dimm_module_decoder->data_buffer_dfe(o_value) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Helper function to append SPD decoder to the end of a vector +/// @param[in] i_target the DIMM target +/// @param[in] i_spd_data SPD data in a vector reference +/// @param[in,out] io_spd_decoder reference to std::vector of SPD facades +/// @return FAPI2_RC_SUCCESS iff okay +/// +static fapi2::ReturnCode add_decoder_to_list( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data, + std::vector< facade >& io_spd_decoder ) +{ + fapi2::ReturnCode l_rc; + facade l_spd_decoder(i_target, i_spd_data, l_rc); + FAPI_TRY(l_rc, "Failed to instantiate SPD facade for %s", spd::c_str(i_target)); + + io_spd_decoder.push_back(l_spd_decoder); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Creates a list of SPD decoder from target +/// @tparam T the fapi2 target +/// @param[in] i_target the DIMM target +/// @param[out] o_spd_decoder reference to std::vector of SPD facades +/// @return FAPI2_RC_SUCCESS iff okay +/// +template < fapi2::TargetType T > +fapi2::ReturnCode get_spd_decoder_list( const fapi2::Target<T>& i_target, + std::vector< facade >& o_spd_decoder ) +{ + o_spd_decoder.clear(); + + for( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) ) + { + std::vector<uint8_t> l_spd; + FAPI_TRY( get_raw_data(l_dimm, l_spd) ); + + FAPI_TRY( add_decoder_to_list(l_dimm, l_spd, o_spd_decoder) ); + }// dimms + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Creates a list of SPD decoder of SPD data to target +/// @tparam T the fapi2 target +/// @param[in] i_target the DIMM target +/// @param[in] i_spd_data SPD data +/// @param[out] o_spd_decoder reference to std::vector of SPD facades +/// @return FAPI2_RC_SUCCESS iff okay +/// +template < fapi2::TargetType T > +fapi2::ReturnCode get_spd_decoder_list( const fapi2::Target<T>& i_target, + const std::vector<uint8_t>& i_spd_data, + std::vector< facade >& o_spd_decoder ) +{ + o_spd_decoder.clear(); + + for( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) ) + { + FAPI_TRY( add_decoder_to_list(l_dimm, i_spd_data, o_spd_decoder) ); + }// dimms + +fapi_try_exit: + return fapi2::current_err; +} + +}// spd +}// mss + +#endif //_MSS_SPD_FACADE_H_ diff --git a/src/import/generic/memory/lib/spd/spd_factory_pattern.C b/src/import/generic/memory/lib/spd/spd_factory_pattern.C index bc58ff24f..dceb944fa 100644 --- a/src/import/generic/memory/lib/spd/spd_factory_pattern.C +++ b/src/import/generic/memory/lib/spd/spd_factory_pattern.C @@ -22,3 +22,334 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +/// +/// @file spd_factory_pattern.C +/// @brief SPD factory pattern implementation +/// + +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +#include <generic/memory/lib/spd/spd_factory_pattern.H> + +namespace mss +{ +namespace spd +{ + +/// +/// @brief constexpr ctor +/// @param[in] i_dram_gen DRAM generation +/// @param[in] i_spd_param DIMM type +/// @param[in] i_rev SPD revision +/// +module_key::module_key(const uint8_t i_dram_gen, + const parameters i_spd_param, + const uint8_t i_rev): + iv_rev(i_rev), + iv_dram_gen(i_dram_gen), + iv_param(i_spd_param) +{} + +/// +/// @brief less-than operator +/// @param[in] i_rhs the module_key +/// @return true or false +/// +bool module_key::operator<(const module_key& i_rhs) const +{ + // Impose weak strict ordering for dram_gen + // by dram gen, dimm type, and then revision + if(iv_dram_gen != i_rhs.iv_dram_gen) + { + return iv_dram_gen < i_rhs.iv_dram_gen; + } + + // If we are here than iv_param == i_key.iv_param + // Impose weak strict ordering for encoding_level + if( iv_param != i_rhs.iv_param) + { + return iv_param < i_rhs.iv_param; + } + + // If we are here than iv_encoding_level == i_key.iv_encoding_leve + // Impose weak strict ordering for additions_level + if( iv_rev != i_rhs.iv_rev) + { + return iv_rev < i_rhs.iv_rev; + } + + return false; +} + +/// +/// @brief ctor +/// @param[in] i_target the DIMM target +/// @param[in] i_key the module_key +/// +rev_fallback::rev_fallback(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const module_key& i_key): + iv_target(i_target), + iv_key(i_key), + iv_encoding_level(0), + iv_additions_level(0), + LRDIMM_DDR4_V1_0{DDR4, LRDIMM_MODULE, rev::V1_0}, + LRDIMM_DDR4_V1_1{DDR4, LRDIMM_MODULE, rev::V1_1}, + LRDIMM_DDR4_V1_2{DDR4, LRDIMM_MODULE, rev::V1_2}, + RDIMM_DDR4_V1_0{DDR4, RDIMM_MODULE, rev::V1_0}, + RDIMM_DDR4_V1_1{DDR4, RDIMM_MODULE, rev::V1_1}, + NVDIMM_DDR4_V1_0{DDR4, NVDIMM_MODULE, rev::V1_0}, + NVDIMM_DDR4_V1_1{DDR4, NVDIMM_MODULE, rev::V1_1} +{ + // Member variable initialization + fapi2::buffer<uint8_t> l_buffer(i_key.iv_rev); + l_buffer.extractToRight<ENCODINGS_REV_START, LEN>(iv_encoding_level); + l_buffer.extractToRight<ADDITIONS_REV_START, LEN>(iv_additions_level); + + // Setup pre-defined maps available to search through + // 3 diff mappings because each map has an independently + // managed revision. + iv_rdimm_rev_map[RDIMM_DDR4_V1_0] = rev::V1_0; + iv_rdimm_rev_map[RDIMM_DDR4_V1_1] = rev::V1_1; + + iv_lrdimm_rev_map[LRDIMM_DDR4_V1_0] = rev::V1_0; + iv_lrdimm_rev_map[LRDIMM_DDR4_V1_1] = rev::V1_1; + iv_lrdimm_rev_map[LRDIMM_DDR4_V1_2] = rev::V1_2; + + iv_nvdimm_rev_map[NVDIMM_DDR4_V1_0] = rev::V1_1; + iv_nvdimm_rev_map[NVDIMM_DDR4_V1_1] = rev::V1_1; + + // Another small map to select the right map based on module + iv_spd_param_map[RDIMM_MODULE] = iv_rdimm_rev_map; + iv_spd_param_map[LRDIMM_MODULE] = iv_lrdimm_rev_map; + iv_spd_param_map[NVDIMM_MODULE] = iv_nvdimm_rev_map; +} + +/// +/// @brief Retrieves highest supported SPD revision +/// @param[out] o_rev SPD revision +/// @return FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode rev_fallback::get_supported_rev(uint8_t& o_rev) const +{ + std::map<module_key, uint8_t> l_map; + + auto it = iv_spd_param_map.find(iv_key.iv_param); + FAPI_ASSERT(it != iv_spd_param_map.end(), + fapi2::MSS_INVALID_SPD_PARAMETER_RECEIVED() + .set_SPD_PARAM(iv_key.iv_param) + .set_FUNCTION_CODE(GET_SUPPORTED_REV) + .set_TARGET(iv_target), + "Invalid SPD parameter received %d for %s", + iv_key.iv_param, spd::c_str(iv_target)); + + l_map = it->second; + FAPI_TRY( check_encoding_level(l_map) ); + + // The logic is easier to handle only additions level changes. + // This source will need to be updated to handle encodings level changes + // (rare occurance that hasn't happened yet...) and will be caught with the conditional above. + select_highest_rev(l_map, o_rev); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function to select the largest SPD revision +/// @param[in] i_map a map of supported SPD revisions for a certain SPD param +/// @param[out] o_rev the SPD Revision +/// @return FAPI2_RC_SUCCESS iff okay +/// +void rev_fallback::select_highest_rev( const std::map<module_key, uint8_t>& i_map, + uint8_t& o_rev) const +{ + // When encoding revisions are the same and only + // addition revisions differ, setting are backward + // compatible. This means if we hit a case where + // the additions level is not in our existing list of + // decoders we can default to the highest decoded revision. + // (e.g. If the DRAM is rev 1.3 but we have only decoded up + // to rev 1.1, we can safely default to rev 1.1 accepting + // that we lose features that may exist in higher revisions). + auto it = i_map.end(); + o_rev = (--it)->second; +} + +/// +/// @brief Helper function to check non-backward compatible encoding level changes +/// @param[in] i_map Map of supported SPD revisions for a certain SPD param +/// @return FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode rev_fallback::check_encoding_level(const std::map<module_key, uint8_t>& i_map) const +{ + // A change in encoding revision breaks backward compatability, + // (e.g. revision 2.# is not backwards compatible with revision 1.#, + // for some integer #). + auto it = --(i_map.end()); + const uint8_t l_highest_possible_rev = it->second; + const fapi2::buffer<uint8_t> l_buffer(l_highest_possible_rev); + + uint8_t l_last_valid_encoding_lvl = 0; + l_buffer.extractToRight<ENCODINGS_REV_START, LEN>(l_last_valid_encoding_lvl); + + FAPI_INF("Highest valid rev 0x%02x, Highest valid encoding level %d, encoding level received %d for %s", + l_highest_possible_rev, l_last_valid_encoding_lvl, iv_encoding_level, spd::c_str(iv_target)); + + FAPI_ASSERT( iv_encoding_level <= l_last_valid_encoding_lvl, + fapi2::MSS_SPD_REV_ENCODING_LEVEL_NOT_SUPPORTED() + .set_ENCODING_LEVEL(iv_encoding_level) + .set_TARGET(iv_target), + "SPD revision encoding level (%d) is greater than largest decode (%d) for %s", + iv_encoding_level, l_last_valid_encoding_lvl, spd::c_str(iv_target)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief ctor +/// @param[in] i_target the DIMM target +/// @param[in] i_spd_data SPD data in a vector reference +/// @param[out] o_rc FAPI2_RC_SUCCESS iff okay +/// +factories::factories(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data, + fapi2::ReturnCode& o_rc): + iv_target(i_target), + iv_spd_data(i_spd_data) +{ + FAPI_TRY( (reader<init_fields::REVISION, spd::rev::GEN_SEC_MAX>(i_target, i_spd_data, iv_rev)), + "Failed to read REVISION field for %s", spd::c_str(i_target) ); + FAPI_TRY( (reader<init_fields::BASE_MODULE, spd::rev::GEN_SEC_MAX>(i_target, i_spd_data, iv_dimm_type)), + "Failed to read BASE_MODULE field for %s", spd::c_str(i_target) ); + FAPI_TRY( (reader<init_fields::DEVICE_TYPE, spd::rev::GEN_SEC_MAX>(i_target, i_spd_data, iv_dram_gen)), + "Failed to read DEVICE_TYPE field for %s", spd::c_str(i_target) ); + FAPI_TRY( (reader<init_fields::HYBRID, spd::rev::GEN_SEC_MAX>(i_target, i_spd_data, iv_hybrid)), + "Failed to read HYBRID field for %s", spd::c_str(i_target) ); + FAPI_TRY( (reader<init_fields::HYBRID_MEDIA, spd::rev::GEN_SEC_MAX>(i_target, i_spd_data, iv_hybrid_media)), + "Failed to read HYBRID_MEDIA field for %s", spd::c_str(i_target) ); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; +} + +/// +/// @brief creates base_cnfg_decoder object +/// @param[out] o_decoder_ptr the base_cnfg_decoder object ptr +/// @return FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode factories::create_decoder( std::shared_ptr<base_cnfg_decoder>& o_decoder_ptr ) const +{ + parameters l_param = UNINITIALIZED; + FAPI_TRY(base_cfg_select_param(l_param)); + + { + auto l_factory_key = module_key(iv_dram_gen, l_param, iv_rev); + + const module_factory<base_cnfg_decoder> l_decoder(iv_target, iv_spd_data); + FAPI_TRY( l_decoder.make_object(l_factory_key, o_decoder_ptr) ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief creates dimm_module_decoder object +/// @param[out] o_decoder_ptr the dimm_module_decoder object ptr +/// @return FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode factories::create_decoder( std::shared_ptr<dimm_module_decoder>& o_decoder_ptr ) const +{ + parameters l_param = UNINITIALIZED; + FAPI_TRY(dimm_module_select_param(l_param)); + + { + auto l_factory_key = module_key(iv_dram_gen, l_param, iv_rev); + + const module_factory<dimm_module_decoder> l_decoder(iv_target, iv_spd_data); + FAPI_TRY( l_decoder.make_object(l_factory_key, o_decoder_ptr) ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper to select SPD parameter for the dimm module +/// @param[out] o_param SPD parameter +/// @return FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode factories::dimm_module_select_param(parameters& o_param) const +{ + switch(iv_dimm_type) + { + case RDIMM: + o_param = RDIMM_MODULE; + break; + + case LRDIMM: + o_param = LRDIMM_MODULE; + break; + + default: + FAPI_ASSERT(false, + fapi2::MSS_INVALID_DIMM_TYPE() + .set_DIMM_TYPE(iv_dimm_type) + .set_FUNCTION(DIMM_MODULE_PARAM_SELECT) + .set_DIMM_TARGET(iv_target), + "Invalid DIMM type recieved (%d) for %s", + iv_dimm_type, spd::c_str(iv_target)); + break; + } + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper to select SPD parameter for the base cfg +/// @param[out] o_param SPD parameter +/// @return FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode factories::base_cfg_select_param(parameters& o_param) const +{ + if(iv_hybrid == HYBRID && iv_hybrid_media == NVDIMM_HYBRID) + { + // The general section used for NVDIMMs is different than + // those for LRDIMM and RDIMM modules. + o_param = NVDIMM_MODULE; + return fapi2::FAPI2_RC_SUCCESS; + } + + // If we are here let's make sure we are not hybrid, sanity + // check to assure we don't have invalid hybrid combination + FAPI_ASSERT(iv_hybrid == NOT_HYBRID && + iv_hybrid_media == NOT_HYBRID, + fapi2::MSS_INVALID_HYBRID_MODULE(). + set_HYBRID(iv_hybrid). + set_HYBRID_MEDIA(iv_hybrid_media). + set_FUNCTION(BASE_CFG_PARAM_SELECT). + set_TARGET(iv_target), + "Invalid hybrid (%d) or hybrid_media (%d) for %s", + iv_hybrid, iv_hybrid_media, spd::c_str(iv_target)); + + FAPI_TRY(dimm_module_select_param(o_param)); + +fapi_try_exit: + return fapi2::current_err; +} + +}// spd +}// mss diff --git a/src/import/generic/memory/lib/spd/spd_factory_pattern.H b/src/import/generic/memory/lib/spd/spd_factory_pattern.H index c0629c5c9..9d36738d4 100644 --- a/src/import/generic/memory/lib/spd/spd_factory_pattern.H +++ b/src/import/generic/memory/lib/spd/spd_factory_pattern.H @@ -22,3 +22,487 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +/// +/// @file spd_factory_pattern.H +/// @brief SPD factory pattern declaration +/// + +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_SPD_FACTORY_PATTERN_H_ +#define _MSS_SPD_FACTORY_PATTERN_H_ + +#include <fapi2.H> +#include <cstdint> +#include <map> +#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> +#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H> +#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H> +#include <generic/memory/lib/spd/spd_checker.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> + +namespace mss +{ +/// +/// @class moduleFactoryTraits +/// @brief class that holds module factory traits +/// @tparam T the decoder type we want the factory to generate +/// +template < typename T > +struct moduleFactoryTraits; + +/// +/// @class moduleFactoryTraits - base_cnfg_decoder specialization +/// @brief class that holds module factory traits +/// +template< > +struct moduleFactoryTraits<spd::base_cnfg_decoder> +{ + static constexpr generic_ffdc_codes MODULE_FACTORY_FFDC_CODE = BASE_CFG_FACTORY; +}; + +/// +/// @class moduleFactoryTraits - dimm_module_decoder specialization +/// @brief class that holds module factory traits +/// +template< > +struct moduleFactoryTraits<spd::dimm_module_decoder> +{ + static constexpr generic_ffdc_codes MODULE_FACTORY_FFDC_CODE = DIMM_MODULE_FACTORY; +}; + +namespace spd +{ + +/// +/// @class module_key +/// @brief SPD module key for factory +/// +struct module_key +{ + uint8_t iv_rev; + uint8_t iv_dram_gen; + parameters iv_param; + + /// + /// @brief default ctor + /// + module_key() = default; + + /// + /// @brief constexpr ctor + /// @param[in] i_dram_gen DRAM generation + /// @param[in] i_spd_param DIMM type + /// @param[in] i_rev SPD revision + /// + module_key(const uint8_t i_dram_gen, + const parameters i_spd_param, + const uint8_t i_rev); + + /// + /// @brief default dtor + /// + ~module_key() = default; + + /// + /// @brief less-than operator + /// @param[in] i_rhs the module_key + /// @return true or false + /// + bool operator<(const module_key& i_rhs) const; + +};// module_key + +/// +/// @brief Class that performs revision fallback +/// @class rev_fallback +/// +class rev_fallback +{ + public: + + /// + /// @brief ctor + /// @param[in] i_target the DIMM target + /// @param[in] i_key the module_key + /// + rev_fallback(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const module_key& i_key); + + /// + /// @brief dtor + /// + ~rev_fallback() = default; + + /// + /// @brief Retrieves highest supported SPD revision + /// @param[out] o_rev SPD revision + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode get_supported_rev(uint8_t& o_rev) const; + + private: + + enum + { + LEN = 4, + ENCODINGS_REV_START = 0, + ADDITIONS_REV_START = 4, + }; + + fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + module_key iv_key; + uint8_t iv_encoding_level; + uint8_t iv_additions_level; + + // Constants convenient for map indexing + const module_key LRDIMM_DDR4_V1_0; + const module_key LRDIMM_DDR4_V1_1; + const module_key LRDIMM_DDR4_V1_2; + + const module_key RDIMM_DDR4_V1_0; + const module_key RDIMM_DDR4_V1_1; + + const module_key NVDIMM_DDR4_V1_0; + const module_key NVDIMM_DDR4_V1_1; + + std::map<module_key, uint8_t> iv_lrdimm_rev_map; + std::map<module_key, uint8_t> iv_rdimm_rev_map; + std::map<module_key, uint8_t> iv_nvdimm_rev_map; + std::map< parameters, std::map<module_key, uint8_t> > iv_spd_param_map; + + /// + /// @brief Helper function to select the largest SPD revision + /// @param[in] i_map a map of supported SPD revisions for a certain SPD param + /// @param[out] o_rev the SPD Revision + /// @return FAPI2_RC_SUCCESS iff okay + /// + void select_highest_rev( const std::map<module_key, uint8_t>& i_map, + uint8_t& o_rev) const; + + /// + /// @brief Helper function to check non-backward compatible encoding level changes + /// @param[in] i_map Map of supported SPD revisions for a certain SPD param + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode check_encoding_level(const std::map<module_key, uint8_t>& i_map) const; +}; + +/// +/// @class module_factory +/// @tparam T module decoder type (e.g. base_cnfg_decoder, dimm_module_decoder) +/// @tparam TT defaulted to moduleFactoryTraits<T> +/// @brief Factory method for SPD module parameters +/// +template < typename T, typename TT = moduleFactoryTraits<T> > +class module_factory +{ + public: + + /// + /// @brief ctor + /// @param[in] i_target the DIMM target + /// @param[in] i_spd_data SPD data in a vector reference + /// + module_factory(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data): + iv_target(i_target), + LRDIMM_DDR4_REV_1_0{DDR4, LRDIMM_MODULE, rev::V1_0}, + LRDIMM_DDR4_REV_1_1{DDR4, LRDIMM_MODULE, rev::V1_1}, + LRDIMM_DDR4_REV_1_2{DDR4, LRDIMM_MODULE, rev::V1_2}, + RDIMM_DDR4_REV_1_0{DDR4, RDIMM_MODULE, rev::V1_0}, + RDIMM_DDR4_REV_1_1{DDR4, RDIMM_MODULE, rev::V1_1}, + NVDIMM_DDR4_REV_1_0{DDR4, NVDIMM_MODULE, rev::V1_0}, + NVDIMM_DDR4_REV_1_1{DDR4, NVDIMM_MODULE, rev::V1_1} + { + // Setup pre-defined maps available to search through + init_map_vars(i_spd_data, iv_decoder_map); + } + + /// + /// @brief default dtor + /// + ~module_factory() = default; + + /// + /// @brief creates module_decoder object from key + /// @param[in,out] io_key the module key + /// @param[out] o_decoder_ptr the dimm_module_decoder object ptr + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode make_object(module_key& io_key, + std::shared_ptr<T>& o_decoder_ptr) const + { + auto it = iv_decoder_map.find(io_key); + + // If we found matching key, return that associated decoder + if(it != iv_decoder_map.end()) + { + o_decoder_ptr = it->second; + return fapi2::FAPI2_RC_SUCCESS; + } + + // If we are here that means we didn't find a matching key-value pair. + // So we will dig deeper to evaluate the issue and try to fallback to + // a supported (backward compatible) SPD revision. + FAPI_TRY( try_fallback(io_key, o_decoder_ptr) ); + + fapi_try_exit: + return fapi2::current_err; + } + + private: + + const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + + // Indexing member vars for convenient map indexing + const module_key LRDIMM_DDR4_REV_1_0; + const module_key LRDIMM_DDR4_REV_1_1; + const module_key LRDIMM_DDR4_REV_1_2; + const module_key RDIMM_DDR4_REV_1_0; + const module_key RDIMM_DDR4_REV_1_1; + const module_key NVDIMM_DDR4_REV_1_0; + const module_key NVDIMM_DDR4_REV_1_1; + + std::map< module_key, std::shared_ptr<T> > iv_decoder_map; + + /// + /// @brief Helper function to initialize base_cnfg_decoder map + /// @param[out] o_map base_cnfg_decoder map + /// + void init_map_vars(const std::vector<uint8_t>& i_spd_data, + std::map< module_key, std::shared_ptr<base_cnfg_decoder> >& o_map) + { + // + // RDIMMs + // + + // Rev 1.0 + // Life starts out at base revision level + o_map[RDIMM_DDR4_REV_1_0] = std::make_shared< decoder<DDR4, BASE_CNFG, rev::V1_0> >(iv_target, i_spd_data); + + // Rev 1.1 + // Changes to both the general section & rdimm section occured + o_map[RDIMM_DDR4_REV_1_1] = std::make_shared< decoder<DDR4, BASE_CNFG, rev::V1_1> >(iv_target, i_spd_data); + + // + // LRDIMMs + // + + // Rev 1.0 + // Life starts out at base revision level + o_map[LRDIMM_DDR4_REV_1_0] = std::make_shared< decoder<DDR4, BASE_CNFG, rev::V1_0> >(iv_target, i_spd_data); + + // Rev 1.1 + // Changes to both the general section & lrdimm section occured + o_map[LRDIMM_DDR4_REV_1_1] = std::make_shared< decoder<DDR4, BASE_CNFG, rev::V1_1> >(iv_target, i_spd_data); + + // Rev 1.2 + // Changes lrdimm section occured + // General section remained the same + o_map[LRDIMM_DDR4_REV_1_2] = std::make_shared< decoder<DDR4, BASE_CNFG, rev::V1_1> >(iv_target, i_spd_data); + + // + // NVDIMMs + // + + // Rev 1.0 + // NVDIMMs start out life w/the updated general section. + o_map[NVDIMM_DDR4_REV_1_0] = std::make_shared< decoder<DDR4, BASE_CNFG, rev::V1_1> >(iv_target, i_spd_data); + + // Rev 1.1 + // Changes to the NVDIMM module occured, general section remains the same + o_map[NVDIMM_DDR4_REV_1_1] = std::make_shared< decoder<DDR4, BASE_CNFG, rev::V1_1> >(iv_target, i_spd_data); + } + + /// + /// @brief Helper function to initialize dimm_module_decoder map + /// @param[out] o_map dimm_module_decoder map + /// + void init_map_vars(const std::vector<uint8_t>& i_spd_data, + std::map< module_key, std::shared_ptr<dimm_module_decoder> >& o_map) + { + // + // RDIMMs + // + + // Rev 1.0 + // Life starts out at base revision level + o_map[RDIMM_DDR4_REV_1_0] = std::make_shared< decoder<DDR4, RDIMM_MODULE, rev::V1_0> >(iv_target, i_spd_data); + + // Rev 1.1 + // Changes to both the general section & rdimm section occured + o_map[RDIMM_DDR4_REV_1_1] = std::make_shared< decoder<DDR4, RDIMM_MODULE, rev::V1_1> >(iv_target, i_spd_data); + + // + // LRDIMMs + // + + // Rev 1.0 + // Life starts out at base revision level + o_map[LRDIMM_DDR4_REV_1_0] = std::make_shared< decoder<DDR4, LRDIMM_MODULE, rev::V1_0> >(iv_target, i_spd_data); + + // Rev 1.1 + // Changes to both the general section & lrdimm section occured + o_map[LRDIMM_DDR4_REV_1_1] = std::make_shared< decoder<DDR4, LRDIMM_MODULE, rev::V1_1> >(iv_target, i_spd_data); + + // Rev 1.2 + // Changes lrdimm section occured + // General section remained the same + o_map[LRDIMM_DDR4_REV_1_2] = std::make_shared< decoder<DDR4, LRDIMM_MODULE, rev::V1_2> >(iv_target, i_spd_data); + } + + /// + /// @brief Try to fallback to a supported backward compatible decoder + /// @param[in,out] io_key the module key + /// @param[out] o_rev SPD revision we are falling back to + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode find_backward_compatible_rev(module_key& io_key) const + { + const rev_fallback l_rev_fallback(iv_target, io_key); + + // Overwrite io_key.iv_rev with a supported revision + FAPI_TRY(l_rev_fallback.get_supported_rev(io_key.iv_rev)); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Create a decoder with the fallback module_key + /// @param[in] i_key the module key + /// @param[out] o_decoder_ptr decoder ptr + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode create_fallback_decoder(const module_key& i_key, + std::shared_ptr<T>& o_decoder_ptr) const + { + auto it = iv_decoder_map.find(i_key); + + // Sanity check, should never fail unless it's a programming error... + constexpr generic_ffdc_codes FFDC_CODE = TT::MODULE_FACTORY_FFDC_CODE; + + FAPI_ASSERT( it != iv_decoder_map.end(), + fapi2::MSS_FAILED_SPD_REVISION_FALLBACK() + .set_FAILED_REVISION(i_key.iv_rev) + .set_FUNCTION_CODE(FFDC_CODE) + .set_TARGET(iv_target), + "Failed to find a map value for the key (rev 0x%02, param %d, dram gen: %d", + i_key.iv_rev, i_key.iv_param, i_key.iv_dram_gen); + + // Update SPD rev to fallback rev + { + constexpr size_t REV_BYTE = 1; + o_decoder_ptr = it->second; + std::vector<uint8_t> l_spd_data = o_decoder_ptr->get_data(); + l_spd_data[REV_BYTE] = i_key.iv_rev; + o_decoder_ptr->set_data(l_spd_data); + } + + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Try to fallback to a supported backward compatible decoder + /// @param[in,out] io_key the module key + /// @param[out] o_decoder_ptr the o_decoder_ptr object ptr + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode try_fallback(module_key& io_key, + std::shared_ptr<T>& o_decoder_ptr) const + { + const uint8_t l_dimm_type = io_key.iv_param == RDIMM_MODULE ? RDIMM : LRDIMM; + + // Invalid DRAM gen is a hard fail + FAPI_TRY(check::dram_gen(iv_target, io_key.iv_dram_gen, TT::MODULE_FACTORY_FFDC_CODE)); + + // Invalid DIMM type is a hard fail + FAPI_TRY(check::dimm_type(iv_target, l_dimm_type, TT::MODULE_FACTORY_FFDC_CODE)); + + // We can circumvent SPD revision fails by using backward compatible revisions + FAPI_TRY(find_backward_compatible_rev(io_key)); + + // Let's create a new decoder that we can fall back to + FAPI_TRY(create_fallback_decoder(io_key, o_decoder_ptr)); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @class factories +/// @brief Factory method that creates the right decoder based on SPD data +/// +class factories +{ + public: + + /// + /// @brief ctor + /// @param[in] i_target the DIMM target + /// @param[in] i_spd_data SPD data in a vector reference + /// @param[out] o_rc FAPI2_RC_SUCCESS iff okay + /// + factories(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data, + fapi2::ReturnCode& o_rc); + + /// + /// @brief default dtor + /// + ~factories() = default; + + + /// + /// @brief creates base_cnfg_decoder object + /// @param[out] o_decoder_ptr the base_cnfg_decoder object ptr + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode create_decoder( std::shared_ptr<base_cnfg_decoder>& o_decoder_ptr ) const; + + /// + /// @brief creates dimm_module_decoder object + /// @param[out] o_decoder_ptr the dimm_module_decoder object ptr + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode create_decoder( std::shared_ptr<dimm_module_decoder>& o_decoder_ptr ) const; + + private: + + const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + std::vector<uint8_t> iv_spd_data; + uint8_t iv_rev; + uint8_t iv_dram_gen; + uint8_t iv_dimm_type; + uint8_t iv_hybrid; + uint8_t iv_hybrid_media; + + /// + /// @brief Helper to select SPD parameter for the dimm module + /// @param[out] o_param SPD parameter + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode dimm_module_select_param(parameters& o_param) const; + + /// + /// @brief Helper to select SPD parameter for the base cfg + /// @param[out] o_param SPD parameter + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode base_cfg_select_param(parameters& o_param) const; + +}; + +}// spd +}// mss + +#endif //_MSS_SPD_FACTORY_PATTERN_H_ diff --git a/src/import/generic/memory/lib/spd/spd_fields_ddr4.H b/src/import/generic/memory/lib/spd/spd_fields_ddr4.H index 97413367d..15c95ff77 100644 --- a/src/import/generic/memory/lib/spd/spd_fields_ddr4.H +++ b/src/import/generic/memory/lib/spd/spd_fields_ddr4.H @@ -460,7 +460,6 @@ class fields<DDR4, BASE_CNFG> static constexpr field_t OFFSET_TCK_MIN{125, OFFSET_TCK_MIN_START, OFFSET_TCK_MIN_LEN}; static constexpr field_t CRC_LSB{126, CRC_LSB_START, CRC_LSB_LEN}; static constexpr field_t CRC_MSB{127, CRC_MSB_START, CRC_MSB_LEN}; - static constexpr field_t REF_RAW_CARD{130, REF_RAW_CARD_START, REF_RAW_CARD_LEN}; static constexpr field_t CONTINUATION_CODES{320, CONTINUATION_CODES_START, CONTINUATION_CODES_LEN}; static constexpr field_t LAST_NON_ZERO_BYTE{321, LAST_NON_ZERO_BYTE_START, LAST_NON_ZERO_BYTE_LEN}; static constexpr field_t MODULE_MFG_LOCATION{322, MODULE_MFG_LOC_START, MODULE_MFG_LOC_LEN}; diff --git a/src/import/generic/memory/lib/spd/spd_reader.H b/src/import/generic/memory/lib/spd/spd_reader.H index 90b9df1da..c67db544b 100644 --- a/src/import/generic/memory/lib/spd/spd_reader.H +++ b/src/import/generic/memory/lib/spd/spd_reader.H @@ -51,6 +51,94 @@ namespace spd { /// +/// @brief Helper function to find bit length of an integral type +/// @tparam T integral type +/// @return bit length for given integral type +/// +template < typename T > +constexpr size_t get_bit_length() +{ + return sizeof(T) * BITS_PER_BYTE; +} + +/// +/// @brief Helper function to find bit length of an input param +/// @tparam T input type +/// @param[in] i_input argument we want to get bit length of +/// @return bit length for given input +/// +template < typename T > +constexpr size_t get_bit_length(const T& i_input) +{ + return sizeof(T) * BITS_PER_BYTE; +} + +/// +/// @brief Variadic helper function to find bit length of integral types +/// @tparam T input type +/// @tparam Types input type for a list in input params +/// @param[in] i_first first argument we want to get bit length of +/// @param[in] i_args list of arguments we want to get the total bit length of +/// @return total bit length for given input +// +template < typename T, typename... Types > +constexpr size_t get_bit_length (const T& i_first, const Types& ... i_args) +{ + // Recursive-ish pattern to add up bit length of passed in params + return get_bit_length(i_first) + get_bit_length(i_args...); +} + +/// +/// @tparam T input type +/// @tparam T +/// @param[in] i_data data to insert +/// @param[in,out] io_out buffer we wish to insert values to +/// +template <size_t INPUT_BIT_LEN, typename T, typename OT> +static void set_buffer_helper(const T i_data, fapi2::buffer<OT>& io_out) +{ + constexpr size_t l_output_bit_length = get_bit_length<OT>(); + + constexpr size_t l_start_bit = l_output_bit_length - INPUT_BIT_LEN; + constexpr size_t l_len = get_bit_length<T>(); + + FAPI_DBG("Total input bit length %d, output bit length %d, insert start bit %d, insert length %d, data %d", + INPUT_BIT_LEN, l_output_bit_length, l_start_bit, l_len, i_data); + + io_out.template insertFromRight<l_start_bit, l_len >(i_data); +} + +/// +/// @brief Helper function to insert entire values of any integral value into a buffer +/// @tparam T input type +/// @tparam OT output type of fapi2::buffer +/// @param[in,out] io_out buffer we wish to insert values to +/// @param[in] i_input argument we want to get bit length of +/// +template <typename T, typename OT> +void rightAlignedInsert(fapi2::buffer<OT>& io_out, const T& i_input) +{ + constexpr size_t l_input_total_args_bit_length = get_bit_length(i_input); + set_buffer_helper<l_input_total_args_bit_length>(i_input, io_out); +} + +/// +/// @tparam T input type +/// @tparam Types input type for a list in input params +/// @param[in,out] io_out buffer we wish to insert values to +/// @param[in] i_first first argument we want to get bit length of +/// @param[in] i_args list of arguments we want to get the total bit length of +/// +template <typename T, typename OT, typename... Types> +void rightAlignedInsert(fapi2::buffer<OT>& io_out, const T& first, const Types& ... args) +{ + constexpr size_t l_input_total_args_bit_length = get_bit_length(first, args...); + set_buffer_helper<l_input_total_args_bit_length>(first, io_out); + + rightAlignedInsert(io_out, args...); +} + +/// /// @brief Helper function to extract byte information /// @tparam F the SPD field to extract /// @param[in] i_target the dimm target @@ -85,6 +173,8 @@ fapi2::ReturnCode extract_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_ o_value); } + return fapi2::FAPI2_RC_SUCCESS; + fapi_try_exit: return fapi2::current_err; } @@ -107,18 +197,20 @@ fapi2::ReturnCode reader( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target OT& o_value) { T l_temp = 0; - FAPI_TRY(extract_field<F>(i_target, i_spd_data, l_temp)); + FAPI_TRY( extract_field<F>(i_target, i_spd_data, l_temp), + "Failed extract_field() for %s", spd::c_str(i_target) ); FAPI_DBG("extracted %s value: 0x%02x for %s", TT::FIELD_STR, l_temp, spd::c_str(i_target)); // Test if retrieved data seems valid - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - conditional( l_temp, - TT::COMPARISON_VAL, - typename TT::template COMPARISON_OP<T>() ), - F.get_byte(), - l_temp) ); + FAPI_TRY( check::fail_for_invalid_value(i_target, + conditional( l_temp, + TT::COMPARISON_VAL, + typename TT::template COMPARISON_OP<T>() ), + F.get_byte(), + l_temp), + "Failed fail_for_invalid_value() for %s", spd::c_str(i_target) ); // Output should only change if data check passes o_value = static_cast<OT>(l_temp); diff --git a/src/import/generic/memory/lib/spd/spd_traits.H b/src/import/generic/memory/lib/spd/spd_traits.H index 9eb546302..b05f2c447 100644 --- a/src/import/generic/memory/lib/spd/spd_traits.H +++ b/src/import/generic/memory/lib/spd/spd_traits.H @@ -67,9 +67,8 @@ bool conditional(const T i_spd_field, /// @brief trait structure to hold static SPD information /// @tparam F holds SPD field info /// @tparam R the revision of the SPD field -/// @tparam B boolean required to activate trait class - defaulted to true_type /// -template< const field_t& F, rev R, typename B = std::true_type > +template< const field_t& F, rev R > class readerTraits; /// diff --git a/src/import/generic/memory/lib/spd/spd_traits_ddr4.H b/src/import/generic/memory/lib/spd/spd_traits_ddr4.H index 5d2323bba..e9bda39ea 100644 --- a/src/import/generic/memory/lib/spd/spd_traits_ddr4.H +++ b/src/import/generic/memory/lib/spd/spd_traits_ddr4.H @@ -46,19 +46,15 @@ namespace mss namespace spd { -// Note: The 3rd template parameter is a compile-time conditional -// to activate trait class based on a valid SPD revision. - /// /// @class readerTraits /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note BYTES_USED field partial specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template<rev R> -class readerTraits < fields<DDR4, BASE_CNFG>::BYTES_USED, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::BYTES_USED, R> { public: @@ -74,11 +70,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::BYTES_USED, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TOTAL_BYTES field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template<rev R> -class readerTraits < fields<DDR4, BASE_CNFG>::TOTAL_BYTES, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TOTAL_BYTES, R > { public: @@ -94,11 +89,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TOTAL_BYTES, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note REVISION field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::REVISION, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::REVISION, R > { public: @@ -136,8 +130,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::DEVICE_TYPE, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::DEVICE_TYPE, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::DEVICE_TYPE, R > { public: @@ -153,11 +146,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::DEVICE_TYPE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note BASE_MODULE field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::BASE_MODULE, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::BASE_MODULE, R > { public: @@ -193,8 +185,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID, rev::V1_0 > /// @note valid for rev >= 1.1 specialization /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID, R > { public: @@ -227,11 +218,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID_MEDIA, rev::V1_0 > /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note HYBRID_MEDIA field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID_MEDIA, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID_MEDIA, R > { public: @@ -247,11 +237,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::HYBRID_MEDIA, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note BANK_GROUP_BITS field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::BANK_GROUP_BITS, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::BANK_GROUP_BITS, R > { public: @@ -270,8 +259,7 @@ class readerTraits < fields<DDR4, BASE_CNFG>::BANK_GROUP_BITS, R, /// @note rev 1.0 specialization /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::BANKS_ADDR_BITS, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::BANKS_ADDR_BITS, R > { public: @@ -304,11 +292,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::SDRAM_CAPACITY, rev::V1_0 > /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note SDRAM_CAPACITY, field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::SDRAM_CAPACITY, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::SDRAM_CAPACITY, R > { public: @@ -324,11 +311,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::SDRAM_CAPACITY, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note COL_ADDR_BITS field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::COL_ADDR_BITS, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::COL_ADDR_BITS, R > { public: @@ -344,11 +330,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::COL_ADDR_BITS, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note ROW_ADDR_BITS field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::ROW_ADDR_BITS, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::ROW_ADDR_BITS, R > { public: @@ -364,11 +349,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::ROW_ADDR_BITS, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note PRIM_SIGNAL_LOADING field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::PRIM_SIGNAL_LOADING, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::PRIM_SIGNAL_LOADING, R > { public: @@ -384,11 +368,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::PRIM_SIGNAL_LOADING, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note PRIM_DIE_COUNT field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::PRIM_DIE_COUNT, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::PRIM_DIE_COUNT, R > { public: @@ -404,11 +387,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::PRIM_DIE_COUNT, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note PRIM_PACKAGE_TYPE field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::PRIM_PACKAGE_TYPE, R, - std::integral_constant<bool, (R >= rev::V1_0)> > +class readerTraits< fields<DDR4, BASE_CNFG>::PRIM_PACKAGE_TYPE, R > { public: @@ -424,11 +406,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::PRIM_PACKAGE_TYPE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MAC field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MAC, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MAC, R > { public: @@ -447,8 +428,7 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MAC, R, /// @note rev 1.0 specialization /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::TMAW, R, - std::integral_constant<bool, (R >= rev::V1_0)> > +class readerTraits< fields<DDR4, BASE_CNFG>::TMAW, R > { public: @@ -464,11 +444,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::TMAW, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note PPR field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::PPR, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::PPR, R > { public: @@ -483,32 +462,15 @@ class readerTraits < fields<DDR4, BASE_CNFG>::PPR, R, /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note SOFT_PPR field specialization -/// @note rev 1.0 specialization -/// -template<> -class readerTraits< fields<DDR4, BASE_CNFG>::SOFT_PPR, rev::V1_0 > -{ - public: - - static constexpr size_t COMPARISON_VAL = 0; - static constexpr const char* FIELD_STR = "Soft post package repair (SPPR)"; - - template <typename T> - using COMPARISON_OP = std::equal_to<T>; -}; - -/// -/// @class readerTraits -/// @brief trait structure to hold static SPD information -/// @note SOFT_PPR field specialization -/// @note valid for rev >= 1.1 +/// @note valid for revs /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::SOFT_PPR, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::SOFT_PPR, R > { public: + // Some existing HW has a soft PPR value of 0b01 despite being rev 1.0 + // So we'll allow even thought it doesn't match the SPD spec.... static constexpr size_t COMPARISON_VAL = 0b01; static constexpr const char* FIELD_STR = "Soft post package repair (SPPR)"; @@ -541,8 +503,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::SEC_SIGNAL_LOADING, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::SEC_SIGNAL_LOADING, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::SEC_SIGNAL_LOADING, R > { public: @@ -578,8 +539,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DENSITY_RATIO, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DENSITY_RATIO, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DENSITY_RATIO, R > { public: @@ -615,8 +575,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DIE_COUNT, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DIE_COUNT, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::SEC_DIE_COUNT, R > { public: @@ -652,8 +611,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::SEC_PACKAGE_TYPE, V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::SEC_PACKAGE_TYPE, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::SEC_PACKAGE_TYPE, R > { public: @@ -669,11 +627,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::SEC_PACKAGE_TYPE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OPERABLE_FLD field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OPERABLE_FLD, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OPERABLE_FLD, R > { public: @@ -689,11 +646,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OPERABLE_FLD, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note ENDURANT_FLD field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::ENDURANT_FLD, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::ENDURANT_FLD, R > { public: @@ -709,11 +665,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::ENDURANT_FLD, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note SDRAM_WIDTH field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::SDRAM_WIDTH, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::SDRAM_WIDTH, R > { public: @@ -749,8 +704,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::PACKAGE_RANKS, rev::V1_0 > /// @note valid for rev >= 1.1 specialization /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::PACKAGE_RANKS, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::PACKAGE_RANKS, R > { public: @@ -786,8 +740,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::RANK_MIX, rev::V1_0 > /// @note rev 1.1 specialization /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::RANK_MIX, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::RANK_MIX, R > { public: @@ -803,11 +756,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::RANK_MIX, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note BUS_WIDTH field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::BUS_WIDTH, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::BUS_WIDTH, R > { public: @@ -823,11 +775,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::BUS_WIDTH, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note BUS_EXT_WIDTH field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::BUS_EXT_WIDTH, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::BUS_EXT_WIDTH, R > { public: @@ -843,11 +794,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::BUS_EXT_WIDTH, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note THERM_SENSOR field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::THERM_SENSOR, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::THERM_SENSOR, R > { public: @@ -863,11 +813,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::THERM_SENSOR, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note EXTENDED_MODULE_TYPE field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::EXTENDED_MODULE_TYPE, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::EXTENDED_MODULE_TYPE, R > { public: @@ -883,11 +832,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::EXTENDED_MODULE_TYPE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MED_TIMEBASE field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MEDIUM_TIMEBASE, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MEDIUM_TIMEBASE, R > { public: @@ -903,11 +851,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MEDIUM_TIMEBASE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note FINE_TIMEBASE field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::FINE_TIMEBASE, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::FINE_TIMEBASE, R > { public: @@ -923,11 +870,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::FINE_TIMEBASE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TCK_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TCK_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TCK_MIN, R > { public: @@ -943,11 +889,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TCK_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TCK_MAX field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TCK_MAX, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TCK_MAX, R > { public: @@ -963,11 +908,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TCK_MAX, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note CL_FIRST_BYTE field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::CL_FIRST_BYTE, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::CL_FIRST_BYTE, R > { public: @@ -984,11 +928,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::CL_FIRST_BYTE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note CL_SECOND_BYTE field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::CL_SECOND_BYTE, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::CL_SECOND_BYTE, R > { public: @@ -1024,8 +967,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::CL_THIRD_BYTE, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::CL_THIRD_BYTE, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::CL_THIRD_BYTE, R > { public: @@ -1061,8 +1003,7 @@ class readerTraits< fields<DDR4, BASE_CNFG>::CL_FOURTH_BYTE, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, BASE_CNFG>::CL_FOURTH_BYTE, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, BASE_CNFG>::CL_FOURTH_BYTE, R > { public: @@ -1078,11 +1019,10 @@ class readerTraits< fields<DDR4, BASE_CNFG>::CL_FOURTH_BYTE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TAA_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TAA_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TAA_MIN, R > { public: @@ -1098,11 +1038,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TAA_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRCD_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRCD_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRCD_MIN, R > { public: @@ -1118,11 +1057,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRCD_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRP_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRP_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRP_MIN, R > { public: @@ -1138,11 +1076,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRP_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRASMIN_MSN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRASMIN_MSN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRASMIN_MSN, R > { public: @@ -1158,11 +1095,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRASMIN_MSN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRASMIN_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRASMIN_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRASMIN_LSB, R > { public: @@ -1178,11 +1114,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRASMIN_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRCMIN_MSN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRCMIN_MSN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRCMIN_MSN, R > { public: @@ -1197,11 +1132,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRCMIN_MSN, R, /// @class readerTraits /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRCMIN_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRCMIN_LSB, R > { public: @@ -1217,11 +1151,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRCMIN_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRFC1MIN_MSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRFC1MIN_MSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRFC1MIN_MSB, R > { public: @@ -1237,11 +1170,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRFC1MIN_MSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRFC1MIN_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRFC1MIN_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRFC1MIN_LSB, R > { public: @@ -1257,11 +1189,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRFC1MIN_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRFC2MIN_MSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRFC2MIN_MSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRFC2MIN_MSB, R > { public: @@ -1277,11 +1208,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRFC2MIN_MSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRFC2MIN_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRFC2MIN_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRFC2MIN_LSB, R > { public: @@ -1297,11 +1227,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRFC2MIN_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRFC4MIN_MSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRFC4MIN_MSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRFC4MIN_MSB, R > { public: @@ -1318,11 +1247,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRFC4MIN_MSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRFC4MIN_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRFC4MIN_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRFC4MIN_LSB, R > { public: @@ -1338,11 +1266,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRFC4MIN_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TFAWMIN_MSN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TFAWMIN_MSN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TFAWMIN_MSN, R > { public: @@ -1358,11 +1285,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TFAWMIN_MSN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TFAWMIN_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TFAWMIN_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TFAWMIN_LSB, R > { public: @@ -1378,11 +1304,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TFAWMIN_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRRD_S_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRRD_S_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRRD_S_MIN, R > { public: @@ -1398,11 +1323,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRRD_S_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TRRD_L_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TRRD_L_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TRRD_L_MIN, R > { public: @@ -1418,11 +1342,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TRRD_L_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TCCD_L_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TCCD_L_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TCCD_L_MIN, R > { public: @@ -1439,11 +1362,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TCCD_L_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TWRMIN_MSN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TWRMIN_MSN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TWRMIN_MSN, R > { public: @@ -1459,11 +1381,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TWRMIN_MSN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TWRMIN_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TWRMIN_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TWRMIN_LSB, R > { public: @@ -1480,11 +1401,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TWRMIN_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TWTRMIN_S_MSN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_S_MSN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_S_MSN, R > { public: @@ -1500,11 +1420,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_S_MSN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TWTRMIN_S_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_S_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_S_LSB, R > { public: @@ -1520,11 +1439,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_S_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TWTRMIN_L_MSN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_L_MSN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_L_MSN, R > { public: @@ -1541,11 +1459,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_L_MSN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note TWTRMIN_L_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_L_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_L_LSB, R > { public: @@ -1562,11 +1479,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::TWTRMIN_L_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OFFSET_TCCD_L_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCCD_L_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCCD_L_MIN, R > { public: @@ -1584,11 +1500,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCCD_L_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OFFSET_TRRD_L_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRRD_L_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRRD_L_MIN, R > { public: @@ -1605,11 +1520,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRRD_L_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OFFSET_TRRD_S_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRRD_S_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRRD_S_MIN, R > { public: @@ -1626,11 +1540,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRRD_S_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OFFSET_TRC_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRC_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRC_MIN, R > { public: @@ -1646,11 +1559,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRC_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OFFSET_TRP_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRP_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRP_MIN, R > { public: @@ -1667,11 +1579,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRP_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OFFSET_TAA_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TAA_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TAA_MIN, R > { public: @@ -1687,11 +1598,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TAA_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OFFSET_TRCD_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRCD_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRCD_MIN, R > { public: @@ -1707,11 +1617,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TRCD_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OFFSET_TCK_MIN field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCK_MIN, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCK_MIN, R > { public: @@ -1727,11 +1636,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCK_MIN, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note OFFSET_TCK_MAX field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCK_MAX, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCK_MAX, R > { public: @@ -1747,11 +1655,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::OFFSET_TCK_MAX, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note CRC_MSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::CRC_MSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::CRC_MSB, R > { public: @@ -1767,11 +1674,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::CRC_MSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note CRC_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::CRC_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::CRC_LSB, R > { public: @@ -1787,11 +1693,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::CRC_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note CONTINUATION_CODES field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::CONTINUATION_CODES, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::CONTINUATION_CODES, R > { public: @@ -1807,11 +1712,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::CONTINUATION_CODES, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note LAST_NON_ZERO_BYTE field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::LAST_NON_ZERO_BYTE, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::LAST_NON_ZERO_BYTE, R > { public: @@ -1827,11 +1731,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::LAST_NON_ZERO_BYTE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_MFG_LOCATION field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_LOCATION, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_LOCATION, R > { public: @@ -1847,11 +1750,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_LOCATION, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_MFG_DATE_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_DATE_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_DATE_LSB, R > { public: @@ -1867,11 +1769,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_DATE_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_MFG_DATE_MSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_DATE_MSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_DATE_MSB, R > { public: @@ -1887,11 +1788,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_MFG_DATE_MSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_SERIAL_NUM_BYTE1 field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE1, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE1, R > { public: @@ -1907,11 +1807,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE1, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_SERIAL_NUM_BYTE2 field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE2, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE2, R > { public: @@ -1927,11 +1826,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE2, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_SERIAL_NUM_BYTE3 field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE3, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE3, R > { public: @@ -1947,11 +1845,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE3, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_SERIAL_NUM_BYTE4 field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE4, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE4, R > { public: @@ -1967,11 +1864,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_SERIAL_NUM_BYTE4, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_REV_CODE field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_REV_CODE, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_REV_CODE, R > { public: @@ -1987,11 +1883,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::MODULE_REV_CODE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_MFR_ID_CODE_LSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_MFR_ID_CODE_LSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_MFR_ID_CODE_LSB, R > { public: @@ -2007,11 +1902,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_MFR_ID_CODE_LSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_MFR_ID_CODE_MSB field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_MFR_ID_CODE_MSB, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_MFR_ID_CODE_MSB, R > { public: @@ -2027,11 +1921,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_MFR_ID_CODE_MSB, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_STEPPING field specialization -/// @note valid for revisions up to rev::GEN_SEC_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_STEPPING, R, - std::integral_constant<bool, (R <= rev::GEN_SEC_MAX)> > +class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_STEPPING, R > { public: @@ -2047,11 +1940,10 @@ class readerTraits < fields<DDR4, BASE_CNFG>::DRAM_STEPPING, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_NOMINAL_HEIGHT field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::MODULE_NOMINAL_HEIGHT, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::MODULE_NOMINAL_HEIGHT, R > { public: @@ -2068,11 +1960,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::MODULE_NOMINAL_HEIGHT, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note FRONT_MODULE_THICKNESS field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::FRONT_MODULE_THICKNESS, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::FRONT_MODULE_THICKNESS, R > { public: @@ -2089,11 +1980,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::FRONT_MODULE_THICKNESS, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note BACK_MODULE_THICKNESS field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::BACK_MODULE_THICKNESS, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::BACK_MODULE_THICKNESS, R > { public: @@ -2109,11 +1999,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::BACK_MODULE_THICKNESS, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note REF_RAW_CARD field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::REF_RAW_CARD, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::REF_RAW_CARD, R > { public: @@ -2129,11 +2018,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::REF_RAW_CARD, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note NUM_REGS_USED field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::NUM_REGS_USED, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::NUM_REGS_USED, R > { public: @@ -2149,11 +2037,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::NUM_REGS_USED, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note ROWS_OF_DRAMS field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::ROWS_OF_DRAMS, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::ROWS_OF_DRAMS, R > { public: @@ -2169,11 +2056,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::ROWS_OF_DRAMS, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note REGISTER_TYPE field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::REGISTER_TYPE, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::REGISTER_TYPE, R > { public: @@ -2189,11 +2075,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::REGISTER_TYPE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note HEAT_SPREADER_CHAR field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::HEAT_SPREADER_CHAR, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::HEAT_SPREADER_CHAR, R > { public: @@ -2209,11 +2094,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::HEAT_SPREADER_CHAR, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note HEAT_SPREADER_SOL field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::HEAT_SPREADER_SOL, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::HEAT_SPREADER_SOL, R > { public: @@ -2229,11 +2113,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::HEAT_SPREADER_SOL, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note CONTINUATION_CODES field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::CONTINUATION_CODES, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::CONTINUATION_CODES, R > { public: @@ -2249,11 +2132,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::CONTINUATION_CODES, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note LAST_NON_ZERO_BYTE field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::LAST_NON_ZERO_BYTE, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::LAST_NON_ZERO_BYTE, R > { public: @@ -2269,11 +2151,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::LAST_NON_ZERO_BYTE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note REGISTER_REV field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::REGISTER_REV, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::REGISTER_REV, R > { public: @@ -2289,12 +2170,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::REGISTER_REV, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note ADDR_MAP_REG_TO_DRAM field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::ADDR_MAP_REG_TO_DRAM, R, - - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::ADDR_MAP_REG_TO_DRAM, R > { public: @@ -2309,7 +2188,7 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::ADDR_MAP_REG_TO_DRAM, R, /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note CKE_DRIVER field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template<> class readerTraits< fields<DDR4, RDIMM_MODULE>::CKE_DRIVER, rev::V1_0 > @@ -2327,11 +2206,10 @@ class readerTraits< fields<DDR4, RDIMM_MODULE>::CKE_DRIVER, rev::V1_0 > /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note CKE_DRIVER field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::CKE_DRIVER, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::CKE_DRIVER, R > { public: @@ -2346,7 +2224,7 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::CKE_DRIVER, R, /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note ODT_DRIVER field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template<> class readerTraits< fields<DDR4, RDIMM_MODULE>::ODT_DRIVER, rev::V1_0 > @@ -2364,11 +2242,10 @@ class readerTraits< fields<DDR4, RDIMM_MODULE>::ODT_DRIVER, rev::V1_0 > /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note ODT_DRIVER field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::ODT_DRIVER, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::ODT_DRIVER, R > { public: @@ -2384,11 +2261,10 @@ class readerTraits < fields<DDR4, RDIMM_MODULE>::ODT_DRIVER, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note CA_DRIVER field specialization -/// @note valid for revisions up to rev::RDIMM_MAX (largest decoded rev) +/// @note valid for all revisionsRDIMM_MAX (largest decoded rev) /// template< rev R > -class readerTraits < fields<DDR4, RDIMM_MODULE>::CA_DRIVER, R, - std::integral_constant<bool, (R <= rev::RDIMM_MAX)> > +class readerTraits < fields<DDR4, RDIMM_MODULE>::CA_DRIVER, R > { public: @@ -2424,8 +2300,7 @@ class readerTraits< fields<DDR4, RDIMM_MODULE>::CS_DRIVER, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, RDIMM_MODULE>::CS_DRIVER, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, RDIMM_MODULE>::CS_DRIVER, R > { public: @@ -2461,8 +2336,7 @@ class readerTraits< fields<DDR4, RDIMM_MODULE>::YO_Y2_DRIVER, rev::V1_0 > /// @note rev 1.1 specialization /// template< rev R > -class readerTraits< fields<DDR4, RDIMM_MODULE>::YO_Y2_DRIVER, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, RDIMM_MODULE>::YO_Y2_DRIVER, R > { public: @@ -2498,8 +2372,7 @@ class readerTraits< fields<DDR4, RDIMM_MODULE>::Y1_Y3_DRIVER, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, RDIMM_MODULE>::Y1_Y3_DRIVER, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, RDIMM_MODULE>::Y1_Y3_DRIVER, R > { public: @@ -2515,11 +2388,10 @@ class readerTraits< fields<DDR4, RDIMM_MODULE>::Y1_Y3_DRIVER, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note MODULE_NOMINAL_HEIGHT field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::MODULE_NOMINAL_HEIGHT, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::MODULE_NOMINAL_HEIGHT, R > { public: @@ -2535,11 +2407,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::MODULE_NOMINAL_HEIGHT, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note RAW_CARD_EXT field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::RAW_CARD_EXT, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::RAW_CARD_EXT, R > { public: @@ -2555,11 +2426,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::RAW_CARD_EXT, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note FRONT_MODULE_THICKNESS field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::FRONT_MODULE_THICKNESS, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::FRONT_MODULE_THICKNESS, R > { public: @@ -2575,11 +2445,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::FRONT_MODULE_THICKNESS, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note BACK_MODULE_THICKNESS field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::BACK_MODULE_THICKNESS, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::BACK_MODULE_THICKNESS, R > { public: @@ -2595,11 +2464,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::BACK_MODULE_THICKNESS, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note REF_RAW_CARD field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::REF_RAW_CARD, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::REF_RAW_CARD, R > { public: @@ -2615,11 +2483,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::REF_RAW_CARD, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note NUM_REGS_USED field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::NUM_REGS_USED, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::NUM_REGS_USED, R > { public: @@ -2635,11 +2502,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::NUM_REGS_USED, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note ROWS_OF_DRAMS field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::ROWS_OF_DRAMS, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::ROWS_OF_DRAMS, R > { public: @@ -2655,11 +2521,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::ROWS_OF_DRAMS, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note REGISTER_TYPE field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::REGISTER_TYPE, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::REGISTER_TYPE, R > { public: @@ -2675,11 +2540,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::REGISTER_TYPE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note HEAT_SPREADER_SOL field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::HEAT_SPREADER_SOL, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::HEAT_SPREADER_SOL, R > { public: @@ -2695,11 +2559,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::HEAT_SPREADER_SOL, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note CONTINUATION_CODES field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::CONTINUATION_CODES, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::CONTINUATION_CODES, R > { public: @@ -2715,11 +2578,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::CONTINUATION_CODES, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note LAST_NON_ZERO_BYTE field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::LAST_NON_ZERO_BYTE, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::LAST_NON_ZERO_BYTE, R > { public: @@ -2735,11 +2597,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::LAST_NON_ZERO_BYTE, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note REGISTER_REV field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::REGISTER_REV, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::REGISTER_REV, R > { public: @@ -2755,11 +2616,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::REGISTER_REV, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note ADDR_MAP_REG_TO_DRAM field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::ADDR_MAP_REG_TO_DRAM, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::ADDR_MAP_REG_TO_DRAM, R > { public: @@ -2796,8 +2656,7 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::CKE_DRIVER, rev::V1_0 > /// @note valid for rev >= 1.1 specialization /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::CKE_DRIVER, R, - std::integral_constant<bool, R >= rev::V1_1 > > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::CKE_DRIVER, R > { public: @@ -2833,8 +2692,7 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::ODT_DRIVER, rev::V1_0 > /// @note valid for rev >= 1.1 specialization /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::ODT_DRIVER, R, - std::integral_constant<bool, R >= rev::V1_1 > > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::ODT_DRIVER, R > { public: @@ -2850,11 +2708,10 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::ODT_DRIVER, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note CA_DRIVER field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::CA_DRIVER, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::CA_DRIVER, R > { public: @@ -2890,8 +2747,7 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::CS_DRIVER, rev::V1_0 > /// @note valid for rev >= 1.1 specialization /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::CS_DRIVER, R, - std::integral_constant<bool, R >= rev::V1_1 > > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::CS_DRIVER, R > { public: @@ -2928,8 +2784,7 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::YO_Y2_DRIVER, rev::V1_0 > /// @note valid for rev >= 1.1 specialization /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::YO_Y2_DRIVER, R, - std::integral_constant<bool, R >= rev::V1_1> > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::YO_Y2_DRIVER, R > { public: @@ -2965,8 +2820,7 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::Y1_Y3_DRIVER, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::Y1_Y3_DRIVER, R, - std::integral_constant<bool, R >= rev::V1_1> > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::Y1_Y3_DRIVER, R > { public: @@ -3002,8 +2856,7 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCOM_BODT_BCKE_DRIVER, rev::V1_ /// @note valid for rev >= 1.1 specialization /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCOM_BODT_BCKE_DRIVER, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCOM_BODT_BCKE_DRIVER, R > { public: @@ -3039,8 +2892,7 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCK_DRIVER, rev::V1_0 > /// @note valid for rev >= 1.1 /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCK_DRIVER, R, - std::integral_constant<bool, (R >= rev::V1_1)> > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCK_DRIVER, R > { public: @@ -3055,11 +2907,28 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::BCK_DRIVER, R, /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note RCD_SLEW_CNTRL field specialization -/// @note rev 1.0 & 1.1 specialization +/// @note rev 1.0 specialization /// -template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::RCD_SLEW_CNTRL, R, - std::integral_constant<bool, (R <= rev::V1_1)> > +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::RCD_SLEW_CNTRL, rev::V1_0 > +{ + public: + + static constexpr size_t COMPARISON_VAL = 0; + static constexpr const char* FIELD_STR = "RCD output slew rate control"; + + template <typename T> + using COMPARISON_OP = std::equal_to<T>; +}; + +/// +/// @class readerTraits +/// @brief trait structure to hold static SPD information +/// @note RCD_SLEW_CNTRL field specialization +/// @note rev 1.1 specialization +/// +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::RCD_SLEW_CNTRL, rev::V1_1 > { public: @@ -3077,8 +2946,7 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::RCD_SLEW_CNTRL, R, /// @note valid for rev >= 1.2 /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::RCD_SLEW_CNTRL, R, - std::integral_constant<bool, (R >= rev::V1_2)> > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::RCD_SLEW_CNTRL, R > { public: @@ -3094,11 +2962,10 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::RCD_SLEW_CNTRL, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DATA_BUFFER_REV field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_REV, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_REV, R > { public: @@ -3106,18 +2973,17 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_REV, R, static constexpr const char* FIELD_STR = "Data buffer revision"; template <typename T> - using COMPARISON_OP = std::less_equal<T>; + using COMPARISON_OP = std::less<T>; }; /// /// @class readerTraits /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note VREF_DQ_RANK0 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK0, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK0, R > { public: @@ -3133,11 +2999,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK0, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note VREF_DQ_RANK1 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK1, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK1, R > { public: @@ -3153,11 +3018,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK1, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note VREF_DQ_RANK2 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK2, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK2, R > { public: @@ -3173,11 +3037,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK2, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note VREF_DQ_RANK3 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK3, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK3, R > { public: @@ -3194,12 +3057,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::VREF_DQ_RANK3, R, /// @tparam R the revision of the SPD field /// @note DATA_BUFFER_VREF_DQ field specialization /// @note rev 1.0 specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ, R, - - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ, R > { public: @@ -3215,11 +3076,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DB_MDQ_LTE_1866 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_1866, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_1866, R > { public: @@ -3235,11 +3095,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_1866, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DB_MDQ_LTE_2400 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_2400, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_2400, R > { public: @@ -3255,11 +3114,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_2400, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DB_MDQ_LTE_3200 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_3200, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_3200, R > { public: @@ -3275,11 +3133,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_LTE_3200, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DB_MDQ_RTT_LTE_1866 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_1866, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_1866, R > { public: @@ -3295,11 +3152,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_1866, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DB_MDQ_RTT_LTE_2400 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_2400, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_2400, R > { public: @@ -3315,11 +3171,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_2400, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DB_MDQ_RTT_LTE_3200 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_3200, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_3200, R > { public: @@ -3335,11 +3190,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DB_MDQ_RTT_LTE_3200, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_DRIVE_STRENGTH_LTE_1866 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_1866, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_1866, R > { public: @@ -3355,11 +3209,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_1866, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_DRIVE_STRENGTH_LTE_2400 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_2400, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_2400, R > { public: @@ -3375,11 +3228,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_2400, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_DRIVE_STRENGTH_LTE_3200 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_3200, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_3200, R > { public: @@ -3395,11 +3247,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_DRIVE_STRENGTH_LTE_3200, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_NOM_LTE_1866 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_1866, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_1866, R > { public: @@ -3415,11 +3266,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_1866, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_NOM_LTE_2400 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_2400, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_2400, R > { public: @@ -3435,11 +3285,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_2400, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_NOM_LTE_3200 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_3200, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_3200, R > { public: @@ -3455,11 +3304,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_NOM_LTE_3200, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_WR_LTE_1866 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_1866, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_1866, R > { public: @@ -3475,11 +3323,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_1866, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_WR_LTE_2400 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_2400, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_2400, R > { public: @@ -3495,11 +3342,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_2400, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_WR_LTE_3200 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_3200, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_3200, R > { public: @@ -3515,11 +3361,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_WR_LTE_3200, R, /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_PARK_R01_LTE_1866 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_1866, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_1866, R > { public: @@ -3535,11 +3380,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_1866 /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_PARK_R01_LTE_2400 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_2400, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_2400, R > { public: @@ -3555,11 +3399,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_2400 /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_PARK_R01_LTE_3200 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_3200, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_3200, R > { public: @@ -3575,11 +3418,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R01_LTE_3200 /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_PARK_R23_LTE_1866 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_1866, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_1866, R > { public: @@ -3595,11 +3437,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_1866 /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_PARK_R23_LTE_2400 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_2400, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_2400, R > { public: @@ -3615,11 +3456,10 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_2400 /// @brief trait structure to hold static SPD information /// @tparam R the revision of the SPD field /// @note DRAM_ODT_RTT_PARK_R23_LTE_3200 field specialization -/// @note valid for revisions up to rev::LRDIMM_MAX (largest decoded rev) +/// @note valid for all revisions /// template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_3200, R, - std::integral_constant<bool, (R <= rev::LRDIMM_MAX)> > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_3200, R > { public: @@ -3634,11 +3474,28 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_ODT_RTT_PARK_R23_LTE_3200 /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note DRAM_VREF_DQ_RANGE field specialization -/// @note rev 1.0 & 1.1 specialization +/// @note rev 1.0 specialization /// -template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_VREF_DQ_RANGE, R, - std::integral_constant<bool, (R <= rev::V1_1)> > +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_VREF_DQ_RANGE, rev::V1_0 > +{ + public: + + static constexpr size_t COMPARISON_VAL = 0b1111; + static constexpr const char* FIELD_STR = "VrefDQ range for DRAM interface range"; + + template <typename T> + using COMPARISON_OP = std::less_equal<T>; +}; + +/// +/// @class readerTraits +/// @brief trait structure to hold static SPD information +/// @note DRAM_VREF_DQ_RANGE field specialization +/// @note rev 1.1 specialization +/// +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_VREF_DQ_RANGE, rev::V1_1 > { public: @@ -3656,8 +3513,7 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DRAM_VREF_DQ_RANGE, R, /// @note rev 1.2+ specialization /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::DRAM_VREF_DQ_RANGE, R, - std::integral_constant<bool, (R >= rev::V1_2)> > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::DRAM_VREF_DQ_RANGE, R > { public: @@ -3672,11 +3528,28 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::DRAM_VREF_DQ_RANGE, R, /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note DATA_BUFFER_VREF_DQ field specialization -/// @note rev 1.0 & 1.1 specialization +/// @note rev 1.0 specialization /// -template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ_RANGE, R, - std::integral_constant<bool, (R <= rev::V1_1)> > +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ_RANGE, rev::V1_0 > +{ + public: + + static constexpr size_t COMPARISON_VAL = 0; + static constexpr const char* FIELD_STR = "Data Buffer VrefDQ range for DRAM interface range"; + + template <typename T> + using COMPARISON_OP = std::equal_to<T>; +}; + +/// +/// @class readerTraits +/// @brief trait structure to hold static SPD information +/// @note DATA_BUFFER_VREF_DQ field specialization +/// @note rev 1.1 specialization +/// +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ_RANGE, rev::V1_1 > { public: @@ -3694,8 +3567,7 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ_RANGE, R, /// @note rev 1.2+ specialization /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ_RANGE, R, - std::integral_constant<bool, (R >= rev::V1_2)> > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ_RANGE, R > { public: @@ -3712,9 +3584,26 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_VREF_DQ_RANGE, R, /// @note DATA_BUFFER_DFE field specialization /// @note rev 1.0 & 1.1 specialization /// -template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_DFE, R, - std::integral_constant<bool, (R <= rev::V1_1)> > +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_DFE, rev::V1_0 > +{ + public: + + static constexpr size_t COMPARISON_VAL = 0; + static constexpr const char* FIELD_STR = "Data Buffer DFE"; + + template <typename T> + using COMPARISON_OP = std::equal_to<T>; +}; + +/// +/// @class readerTraits +/// @brief trait structure to hold static SPD information +/// @note DATA_BUFFER_DFE field specialization +/// @note rev 1.1 specialization +/// +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_DFE, rev::V1_1 > { public: @@ -3732,8 +3621,7 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_DFE, R, /// @note rev 1.2+ specialization /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_DFE, R, - std::integral_constant<bool, (R >= rev::V1_2)> > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_DFE, R > { public: @@ -3748,11 +3636,28 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_DFE, R, /// @class readerTraits /// @brief trait structure to hold static SPD information /// @note DATA_BUFFER_GAIN_ADJUST field specialization -/// @note rev 1.0 & 1.1 specialization +/// @note rev 1.0 specialization /// -template< rev R > -class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_GAIN_ADJUST, R, - std::integral_constant<bool, (R <= rev::V1_1)> > +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_GAIN_ADJUST, rev::V1_0 > +{ + public: + + static constexpr size_t COMPARISON_VAL = 1; + static constexpr const char* FIELD_STR = "Data Buffer Gain Adjust"; + + template <typename T> + using COMPARISON_OP = std::less_equal<T>; +}; + +/// +/// @class readerTraits +/// @brief trait structure to hold static SPD information +/// @note DATA_BUFFER_GAIN_ADJUST field specialization +/// @note rev 1.1 specialization +/// +template< > +class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_GAIN_ADJUST, rev::V1_1 > { public: @@ -3770,8 +3675,7 @@ class readerTraits < fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_GAIN_ADJUST, R, /// @note rev 1.2+ specialization /// template< rev R > -class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_GAIN_ADJUST, R, - std::integral_constant<bool, (R >= rev::V1_2)> > +class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_GAIN_ADJUST, R > { public: diff --git a/src/import/generic/memory/lib/spd/spd_utils.C b/src/import/generic/memory/lib/spd/spd_utils.C index 3a977ccf6..bfe380dc5 100644 --- a/src/import/generic/memory/lib/spd/spd_utils.C +++ b/src/import/generic/memory/lib/spd/spd_utils.C @@ -22,3 +22,204 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file spd_utls.C +/// @brief SPD utility function implimentations +/// +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: HB:FSP + + +#include <generic/memory/lib/spd/spd_utils.H> +#include <generic/memory/lib/utils/find.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> + +namespace mss +{ +namespace spd +{ + +/// +/// @brief Helper function to retrieves medium and fine timebase values +/// @param[in] i_spd_decoder the SPD decoder +/// @param[out] o_mtb the medium timebase (MTB) from SPD +/// @param[out] o_ftb the fine timebase (FTB) from SPD +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode get_timebases( const mss::spd::facade& i_spd_decoder, + int64_t& o_mtb, + int64_t& o_ftb ) +{ + // ========================================================= + // Byte 17 maps + // Item JC-45-2220.01x + // Page 29 + // DDR4 SPD Document Release 3 + // Byte 17 (0x011): Timebases + // ========================================================= + // Created a maps of a single value in case mapping expands to more values + static const std::vector<std::pair<int64_t, int64_t> > FINE_TIMEBASE_MAP = + { + // {key byte, fine timebase (in picoseconds) + {0, 1} + // All others reserved + }; + + // ========================================================= + // Byte 17 maps + // Item JC-45-2220.01x + // Page 29 + // DDR4 SPD Document Release 3 + // Byte 17 (0x011): Timebases + // ========================================================= + // Created a maps of a single value in case mapping expands to more values + static const std::vector<std::pair<int64_t, int64_t> > MEDIUM_TIMEBASE_MAP = + { + // {key byte, medium timebase (in picoseconds) + {0, 125} + // All others reserved + }; + + // Retrieve timing parameters + const auto l_target = i_spd_decoder.get_dimm_target(); + + int64_t l_spd_ftb = 0; + int64_t l_spd_mtb = 0; + + FAPI_TRY( i_spd_decoder.medium_timebase(l_spd_mtb), + "%s. Failed medium_timebase()", spd::c_str(l_target) ); + + FAPI_ASSERT( mss::find_value_from_key(MEDIUM_TIMEBASE_MAP, l_spd_mtb, o_mtb), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_mtb) + .set_DATA(o_mtb) + .set_FUNCTION(GET_TIMEBASES_MTB) + .set_TARGET(l_target), + "Could not find a mapped value that matched the key (%d) for %s", + l_spd_mtb, spd::c_str(l_target) ); + FAPI_TRY( i_spd_decoder.fine_timebase(l_spd_ftb), + "%s. Failed fine_timebase()", spd::c_str(l_target) ); + + FAPI_ASSERT( mss::find_value_from_key(FINE_TIMEBASE_MAP, l_spd_ftb, o_ftb), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_ftb) + .set_DATA(o_ftb) + .set_FUNCTION(GET_TIMEBASES_FTB) + .set_TARGET(l_target), + "Could not find a mapped value that matched the key (%d) for %s", + l_spd_ftb, spd::c_str(l_target) ); + + FAPI_INF("MTB: %d, FTB: %d for %s", o_mtb, o_ftb, spd::c_str(l_target)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Retrieves SDRAM Minimum Cycle Time (tCKmin) from SPD +/// @param[in] i_spd_decoder the SPD decoder +/// @param[out] o_value tCKmin value in ps +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode get_tckmin( const mss::spd::facade& i_spd_decoder, + uint64_t& o_value ) +{ + int64_t l_timing_ftb = 0; + int64_t l_timing_mtb = 0; + int64_t l_medium_timebase = 0; + int64_t l_fine_timebase = 0; + int64_t l_temp = 0; + + // Retrieve timing parameters + const auto l_target = i_spd_decoder.get_dimm_target(); + + FAPI_TRY( get_timebases(i_spd_decoder, l_medium_timebase, l_fine_timebase), + "%s. Failed get_timebases", spd::c_str(l_target) ); + FAPI_TRY( i_spd_decoder.min_tck(l_timing_mtb), + "%s. Failed min_tck()", spd::c_str(l_target) ); + FAPI_TRY( i_spd_decoder.fine_offset_min_tck(l_timing_ftb), + "%s. Failed fine_offset_min_tck()", spd::c_str(l_target) ); + + // Calculate timing value + l_temp = spd::calc_timing_from_timebase(l_timing_mtb, + l_medium_timebase, + l_timing_ftb, + l_fine_timebase); + + // Sanity check + FAPI_ASSERT(l_temp > 0, + fapi2::MSS_INVALID_TIMING_VALUE(). + set_VALUE(l_temp). + set_FUNCTION(GET_TCKMIN). + set_DIMM_TARGET(l_target), + "%s. tCKmin invalid (<= 0) : %d", + spd::c_str(l_target), + l_temp); + + o_value = l_temp; + + FAPI_INF("%s. tCKmin (ps): %d", + spd::c_str(l_target), + o_value ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD +/// @param[in] i_spd_decoder SPD decoder +/// @param[out] o_value tCKmax value in ps +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode get_tckmax( const mss::spd::facade& i_spd_decoder, + uint64_t& o_value ) +{ + int64_t l_timing_ftb = 0; + int64_t l_timing_mtb = 0; + int64_t l_medium_timebase = 0; + int64_t l_fine_timebase = 0; + int64_t l_temp = 0; + + // Retrieve timing parameters + const auto l_target = i_spd_decoder.get_dimm_target(); + + FAPI_TRY( get_timebases(i_spd_decoder, l_medium_timebase, l_fine_timebase), + "%s. Failed get_timebases", spd::c_str(l_target) ); + FAPI_TRY( i_spd_decoder.max_tck(l_timing_mtb), + "%s. Failed max_tck()", spd::c_str(l_target) ); + FAPI_TRY( i_spd_decoder.fine_offset_max_tck(l_timing_ftb), + "%s. Failed fine_offset_max_tck()", spd::c_str(l_target) ); + + // Calculate timing value + l_temp = spd::calc_timing_from_timebase(l_timing_mtb, + l_medium_timebase, + l_timing_ftb, + l_fine_timebase); + + // Sanity check + FAPI_ASSERT(l_temp > 0, + fapi2::MSS_INVALID_TIMING_VALUE(). + set_VALUE(l_temp). + set_FUNCTION(GET_TCKMAX). + set_DIMM_TARGET(l_target), + "%s. tCKmax invalid (<= 0) : %d", + spd::c_str(l_target), + l_temp); + + o_value = l_temp; + + FAPI_INF( "%s. tCKmax (ps): %d", + spd::c_str(l_target), + o_value); + +fapi_try_exit: + return fapi2::current_err; +} + +}// spd +}// mss diff --git a/src/import/generic/memory/lib/spd/spd_utils.H b/src/import/generic/memory/lib/spd/spd_utils.H index 4674e71aa..916c41d39 100644 --- a/src/import/generic/memory/lib/spd/spd_utils.H +++ b/src/import/generic/memory/lib/spd/spd_utils.H @@ -22,3 +22,150 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file spd_utls.H +/// @brief SPD utility functions definitions +/// +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_SPD_UTILS_H_ +#define _MSS_SPD_UTILS_H_ + +#include <fapi2.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> +#include <generic/memory/lib/spd/spd_facade.H> + +namespace mss +{ +namespace spd +{ + +/// +/// @brief Calculates timing value +/// @param[in] i_timing_mtb timing value in MTB units +/// @param[in] i_mtb_multiplier SPD medium timebase +/// @param[in] i_timing_ftb fine offset of timing value +/// @param[in] i_ftb_multiplier SPD fine timebase +/// @return the timing value in picoseconds +/// +inline int64_t calc_timing_from_timebase(const int64_t i_timing_mtb, + const int64_t i_mtb_multiplier, + const int64_t i_timing_ftb, + const int64_t i_ftb_multiplier) +{ + // JEDEC algorithm + const int64_t l_timing_val = i_timing_mtb * i_mtb_multiplier; + const int64_t l_fine_offset = i_timing_ftb * i_ftb_multiplier; + + return l_timing_val + l_fine_offset; +} + +/// +/// @brief Helper to compute JEDEC's SPD rounding algorithm +/// to convert ps to nCK +/// @tparam T input type +/// @tparam OT output type +/// @param[in] i_timing_in_ps timing parameter in ps +/// @param[in] i_tck_in_ps clock period in ps +/// @param[in] i_inverse_corr_factor inverse correction factor (defined by JEDEC) +/// @param[out] o_value_nck the end calculation in nck +/// @return true if overflow didn't occur, false otherwise +/// @note DDR4 SPD Contents Rounding Algorithm +/// @note Item 2220.46 +/// +template<typename T, typename OT> +static inline bool jedec_spd_rounding_alg(const T& i_timing_in_ps, + const T& i_tck_in_ps, + const guard_band i_inverse_corr_factor, + OT& o_val_nck) +{ + // Preliminary nCK calculation, scaled by 1000 per JDEC algorithm + T l_temp_nck = (i_timing_in_ps * mss::CONVERT_PS_IN_A_NS) / (i_tck_in_ps == 0 ? 1 : i_tck_in_ps); + l_temp_nck += i_inverse_corr_factor; + l_temp_nck = l_temp_nck / mss::CONVERT_PS_IN_A_NS; + + // Check for overflow + // static_cast needed for HB compiler that complains about + // comparision of two different integral types + o_val_nck = l_temp_nck; + + FAPI_DBG("Input timing (ps) %d, tCK (ps) %d, temp output %d, output (nCK) %d", + i_timing_in_ps, i_tck_in_ps, l_temp_nck, o_val_nck); + + return (static_cast<T>(o_val_nck) == l_temp_nck); +} + +/// +/// @brief Returns clock cycles based on input application period +/// @tparam T input type +/// @tparam OT output type +/// @param[in] i_timing_in_ps timing parameter in ps +/// @param[in] i_tck_in_ps clock period in ps +/// @param[in] i_inverse_corr_factor inverse correction factor (defined by JEDEC) +/// @param[out] o_value_nck the end calculation in nck +/// @return FAPI2_RC_SUCCESS iff okay +/// @note DDR4 SPD Contents Rounding Algorithm +/// @note Item 2220.46 +/// +template<typename T, typename OT> +inline fapi2::ReturnCode calc_nck(const T& i_timing_in_ps, + const T& i_tck_in_ps, + const guard_band i_inverse_corr_factor, + OT& o_val_nck) +{ + FAPI_ASSERT( jedec_spd_rounding_alg(i_timing_in_ps, + i_tck_in_ps, + i_inverse_corr_factor, + o_val_nck), + fapi2::MSS_INVALID_CAST_CALC_NCK(). + set_TIMING_PS(i_timing_in_ps). + set_NCK_NS(i_tck_in_ps). + set_CORRECTION_FACTOR(i_inverse_corr_factor), + "Overflow occured. Returned data is %d", o_val_nck); + + // If we don't assert, we don't know what's in current_err ... + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function to retrieves medium and fine timebase values +/// @param[in] i_spd_decoder the SPD decoder +/// @param[out] o_mtb the medium timebase (MTB) from SPD +/// @param[out] o_ftb the fine timebase (FTB) from SPD +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode get_timebases( const mss::spd::facade& i_spd_decoder, + int64_t& o_mtb, + int64_t& o_ftb ); + +/// +/// @brief Retrieves SDRAM Minimum Cycle Time (tCKmin) from SPD +/// @param[in] i_spd_decoder the SPD decoder +/// @param[out] o_value tCKmin value in ps +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode get_tckmin( const mss::spd::facade& i_spd_decoder, + uint64_t& o_value ); + +/// +/// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD +/// @param[in] i_spd_decoder SPD decoder +/// @param[out] o_value tCKmax value in ps +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode get_tckmax( const mss::spd::facade& i_spd_decoder, + uint64_t& o_value ); + +}// spd + +}// mss + +#endif // _MSS_SPD_UTILS_H_ diff --git a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H index 4bdaf09b7..736827295 100644 --- a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H +++ b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H @@ -43,6 +43,20 @@ namespace mss { /// +/// @brief Common conversions +/// +enum conversions +{ + CONVERT_PS_IN_A_NS = 1000, ///< 1000 pico in an nano + CONVERT_PS_IN_A_US = 1000000, ///< 1000000 picos in a micro + MHZ_TO_KHZ = 1000, + SEC_IN_HOUR = 60 * 60, ///< seconds in an hour, used for scrub times + NIBBLES_PER_BYTE = 2, + BITS_PER_NIBBLE = 4, + BITS_PER_BYTE = 8, +}; + +/// /// @brief FFDC generic codes /// enum generic_ffdc_codes @@ -58,22 +72,58 @@ enum generic_ffdc_codes PRE_DATA_ENGINE_CTOR = 0x1005, EXTRACT_SPD_FLD = 0x1006, SPD_READER = 0x1007, - BASE_CNFG_MAKE_OBJ = 0x1008, - DIMM_MODULE_MAKE_OBJ = 0x1009, - CREATE_BASE_CNFG_FACTORY = 0x100A, - CREATE_MODULE_FACTORY = 0x100B, + BASE_CFG_PARAM_SELECT = 0x1008, + DIMM_MODULE_PARAM_SELECT = 0x1009, + BASE_CFG_FACTORY = 0x100A, + DIMM_MODULE_FACTORY = 0x100B, + GET_TAAMIN = 0x100C, + GET_TCKMIN = 0x100D, + GET_TCKMAX = 0x100E, GET_TIMEBASES_FTB = 0x100F, GET_TIMEBASES_MTB = 0x1010, + GET_SUPPORTED_REV = 0x1011, + TRASMIN = 0x1012, + TRCMIN = 0x1013, + TRFC1MIN = 0x1014, + TRFC2MIN = 0x1015, + TRFC4MIN = 0x1016, + TFAWMIN = 0x1017, + TWTR_S_MIN = 0x1018, + TWRMIN = 0x1019, + TWTR_L_MIN = 0x101A, + DEVICE_TYPE = 0x101B, + BASE_MODULE_TYPE = 0x101C, }; /// -/// @brief DRAM generation selector +/// @brief Supported proc types /// -enum device_type +enum proc_type { - DDR4 = 0x0c, + NIMBUS, + AXONE, }; +/// +/// @brief JEDEC supported DDR4 speeds +/// +enum ddr4_dimm_speeds +{ + DIMM_SPEED_1600 = 1600, + DIMM_SPEED_1866 = 1866, + DIMM_SPEED_2133 = 2133, + DIMM_SPEED_2400 = 2400, + DIMM_SPEED_2666 = 2666, + DIMM_SPEED_2933 = 2933, + DIMM_SPEED_3200 = 3200, +}; + +namespace spd +{ + +/// +/// @brief SPD revisions - not tied any particular module +/// enum rev : uint8_t { V1_0 = 0x10, ///< represents Rev 1.0 @@ -93,11 +143,43 @@ enum rev : uint8_t /// enum parameters { + UNINITIALIZED, BASE_CNFG, RDIMM_MODULE, LRDIMM_MODULE, + NVDIMM_MODULE, +}; + +/// +/// @brief DRAM generation selector +/// @note values set to SPD settings +/// +enum device_type +{ + DDR4 = 0x0c, +}; + +/// +/// @brief DIMM type selector +/// @note values set to SPD settings +/// +enum dimm_type +{ + RDIMM = 0b0001, + LRDIMM = 0b0100, +}; + +enum guard_band : uint16_t +{ + // Used for caclulating spd timing values - from JEDEC rounding algorithm + // Correction factor is 1% (for DDR3) or 2.5% (for DDR4) + // when doing integer math, we add-in the inverse correction factor + // Formula used for derivation: + // Guardband = 1000 * (1000* correction_factor) - 1 + INVERSE_DDR4_CORRECTION_FACTOR = 974, ///< DDR4 correction factor }; +}// spd }// mss #endif |