Skip to content

Commit

Permalink
Support DDR4 DDIMM parse
Browse files Browse the repository at this point in the history
This commit adds the code to support parsing of DDR4 DDIMM type VPD.

ParserFactory is updated to handle the DDR4 type to get the DDIMM VPD
parsing instance for DDR4 DDIMM and DdimmVpdParser class updated to
handle DDR4 DDIMM VPD parsing with new API to calculate the
DDR4 DDIMM size.

Tested the changes by running vpd-manager application, observed DDIMM
parser is selected for DDR4 DDIMM EEPROM files and parsing is
successful. And also observed, DDIMM size is calculated correctly
for DDR4 DDIMMs.

Signed-off-by: Anupama B R <[email protected]>
  • Loading branch information
branupama committed Oct 16, 2024
1 parent effda2b commit 4b9b8df
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 3 deletions.
15 changes: 15 additions & 0 deletions include/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ static constexpr auto SPD_MODULE_TYPE_DDIMM = 0x0A;
static constexpr auto SPD_DRAM_TYPE_DDR5 = 0x12;
static constexpr auto SPD_DRAM_TYPE_DDR4 = 0x0C;

static constexpr auto JEDEC_SDRAM_CAP_MASK = 0x0F;
static constexpr auto JEDEC_PRI_BUS_WIDTH_MASK = 0x07;
static constexpr auto JEDEC_SDRAM_WIDTH_MASK = 0x07;
static constexpr auto JEDEC_NUM_RANKS_MASK = 0x38;
static constexpr auto JEDEC_DIE_COUNT_MASK = 0x70;
static constexpr auto JEDEC_SINGLE_LOAD_STACK = 0x02;
static constexpr auto JEDEC_SIGNAL_LOADING_MASK = 0x03;

static constexpr auto JEDEC_SDRAMCAP_MULTIPLIER = 256;
static constexpr auto JEDEC_PRI_BUS_WIDTH_MULTIPLIER = 8;
static constexpr auto JEDEC_SDRAM_WIDTH_MULTIPLIER = 4;
static constexpr auto JEDEC_SDRAMCAP_RESERVED = 6;
static constexpr auto JEDEC_RESERVED_BITS = 3;
static constexpr auto JEDEC_DIE_COUNT_RIGHT_SHIFT = 4;

static constexpr auto LAST_KW = "PF";
static constexpr auto POUND_KW = '#';
static constexpr auto POUND_KW_PREFIX = "PD_";
Expand Down
9 changes: 9 additions & 0 deletions include/ddimm_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ class DdimmVpdParser : public ParserInterface
size_t
getDdr5BasedDdimmSize(types::BinaryVector::const_iterator i_iterator);

/**
* @brief This function calculates DDR4 based DDIMM's capacity
*
* @param[in] i_iterator - iterator to buffer containing VPD
* @return calculated size or 0 in case of any error.
*/
size_t
getDdr4BasedDdimmSize(types::BinaryVector::const_iterator i_iterator);

/**
* @brief This function calculates DDR5 based die per package
*
Expand Down
99 changes: 96 additions & 3 deletions src/ddimm_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,94 @@ size_t DdimmVpdParser::getDdr5BasedDdimmSize(
return constants::CONVERT_GB_TO_KB * l_dimmSize;
}

size_t DdimmVpdParser::getDdr4BasedDdimmSize(
types::BinaryVector::const_iterator i_iterator)
{
size_t l_tmpValue = 0, l_dimmSize = 0;

// Calculate SDRAM capacity
l_tmpValue = i_iterator[constants::SPD_BYTE_4] &
constants::JEDEC_SDRAM_CAP_MASK;

/* Make sure the bits are not Reserved */
if (l_tmpValue > constants::JEDEC_SDRAMCAP_RESERVED)
{
logging::logMessage(
"Bad data in vpd byte 4. Can't calculate SDRAM capacity and so "
"dimm size.\n ");
return l_dimmSize;
}

size_t l_sdramCapacity = 1;
l_sdramCapacity = (l_sdramCapacity << l_tmpValue) *
constants::JEDEC_SDRAMCAP_MULTIPLIER;

/* Calculate Primary bus width */
l_tmpValue = i_iterator[constants::SPD_BYTE_13] &
constants::JEDEC_PRI_BUS_WIDTH_MASK;

if (l_tmpValue > constants::JEDEC_RESERVED_BITS)
{
logging::logMessage(
"Bad data in vpd byte 13. Can't calculate primary bus width "
"and so dimm size.");
return l_dimmSize;
}

size_t l_primaryBusWid = 1;
l_primaryBusWid = (l_primaryBusWid << l_tmpValue) *
constants::JEDEC_PRI_BUS_WIDTH_MULTIPLIER;

/* Calculate SDRAM width */
l_tmpValue = i_iterator[constants::SPD_BYTE_12] &
constants::JEDEC_SDRAM_WIDTH_MASK;

if (l_tmpValue > constants::JEDEC_RESERVED_BITS)
{
logging::logMessage(
"Bad data in vpd byte 12. Can't calculate SDRAM width and so "
"dimm size.");
return l_dimmSize;
}

size_t l_sdramWidth = 1;
l_sdramWidth = (l_sdramWidth << l_tmpValue) *
constants::JEDEC_SDRAM_WIDTH_MULTIPLIER;

// Calculate die count
l_tmpValue = i_iterator[constants::SPD_BYTE_6] &
constants::JEDEC_SIGNAL_LOADING_MASK;
uint8_t l_dieCount = 1;

if (l_tmpValue == constants::JEDEC_SINGLE_LOAD_STACK)
{
// Fetch die count
l_tmpValue = i_iterator[constants::SPD_BYTE_6] &
constants::JEDEC_DIE_COUNT_MASK;
l_tmpValue >>= constants::JEDEC_DIE_COUNT_RIGHT_SHIFT;
l_dieCount = l_tmpValue + 1;
}

/* Calculate Number of ranks */
l_tmpValue = i_iterator[constants::SPD_BYTE_12] &
constants::JEDEC_NUM_RANKS_MASK;
l_tmpValue >>= constants::JEDEC_RESERVED_BITS;

if (l_tmpValue > constants::JEDEC_RESERVED_BITS)
{
logging::logMessage(
"Can't calculate number of ranks. Invalid data found.");
return l_dimmSize;
}

size_t l_logicalRanksPerDimm = (l_tmpValue + 1) * l_dieCount;

l_dimmSize = (l_sdramCapacity / constants::JEDEC_PRI_BUS_WIDTH_MULTIPLIER) *
(l_primaryBusWid / l_sdramWidth) * l_logicalRanksPerDimm;

return (constants::CONVERT_MB_TO_KB * l_dimmSize);
}

size_t
DdimmVpdParser::getDdimmSize(types::BinaryVector::const_iterator i_iterator)
{
Expand All @@ -209,11 +297,16 @@ size_t
{
l_dimmSize = getDdr5BasedDdimmSize(i_iterator);
}
else if ((i_iterator[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
constants::SPD_DRAM_TYPE_DDR4)
{
l_dimmSize = getDdr4BasedDdimmSize(i_iterator);
}
else
{
logging::logMessage("Error: DDIMM is not DDR5. DDIMM Byte 2 value [" +
std::to_string(i_iterator[constants::SPD_BYTE_2]) +
"]");
logging::logMessage(
"Error: DDIMM is neither DDR4 nor DDR5. DDIMM Byte 2 value [" +
std::to_string(i_iterator[constants::SPD_BYTE_2]) + "]");
}
return l_dimmSize;
}
Expand Down
1 change: 1 addition & 0 deletions src/parser_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ std::shared_ptr<ParserInterface>
}

case vpdType::DDR5_DDIMM_MEMORY_VPD:
case vpdType::DDR4_DDIMM_MEMORY_VPD:
{
logging::logMessage("DDIMM parser selected for VPD file path: " +
i_vpdFilePath);
Expand Down

0 comments on commit 4b9b8df

Please sign in to comment.