Added DDR5 DDIMM capacity calculation
Added the calculation for the capacity of a ddr5 ddimm
Change-Id: Ia20c2828db8ee695747ca90f62b2a2458ccd5394
Signed-off-by: jinuthomas <jinu.joy.thomas@in.ibm.com>
diff --git a/vpd-parser/memory_vpd_parser.cpp b/vpd-parser/memory_vpd_parser.cpp
index b68b629..f6c97b4 100644
--- a/vpd-parser/memory_vpd_parser.cpp
+++ b/vpd-parser/memory_vpd_parser.cpp
@@ -1,5 +1,7 @@
#include "memory_vpd_parser.hpp"
+#include <cmath>
+#include <cstdint>
#include <iostream>
#include <numeric>
#include <string>
@@ -17,10 +19,6 @@
using namespace std;
using namespace openpower::vpd::parser;
-static constexpr auto MEM_BYTE_4 = 4;
-static constexpr auto MEM_BYTE_6 = 6;
-static constexpr auto MEM_BYTE_12 = 12;
-static constexpr auto MEM_BYTE_13 = 13;
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;
@@ -36,7 +34,186 @@
static constexpr auto JEDEC_RESERVED_BITS = 3;
static constexpr auto JEDEC_DIE_COUNT_RIGHT_SHIFT = 4;
-auto memoryVpdParser::getDimmSize(Binary::const_iterator iterator)
+static constexpr auto SDRAM_DENSITY_PER_DIE_24GB = 24;
+static constexpr auto SDRAM_DENSITY_PER_DIE_32GB = 32;
+static constexpr auto SDRAM_DENSITY_PER_DIE_48GB = 48;
+static constexpr auto SDRAM_DENSITY_PER_DIE_64GB = 64;
+static constexpr auto SDRAM_DENSITY_PER_DIE_UNDEFINED = 0;
+
+static constexpr auto PRIMARY_BUS_WIDTH_32_BITS = 32;
+static constexpr auto PRIMARY_BUS_WIDTH_UNUSED = 0;
+
+bool memoryVpdParser::checkValidValue(uint8_t l_ByteValue, uint8_t shift,
+ uint8_t minValue, uint8_t maxValue)
+{
+ l_ByteValue = l_ByteValue >> shift;
+ if ((l_ByteValue > maxValue) || (l_ByteValue < minValue))
+ {
+ cout << "Non valid Value encountered value[" << l_ByteValue
+ << "] range [" << minValue << ".." << maxValue << "] found "
+ << " " << endl;
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+uint8_t memoryVpdParser::getDDR5DensityPerDie(uint8_t l_ByteValue)
+{
+ uint8_t l_densityPerDie = SDRAM_DENSITY_PER_DIE_UNDEFINED;
+ if (l_ByteValue < constants::VALUE_5)
+ {
+ l_densityPerDie = l_ByteValue * constants::VALUE_4;
+ }
+ else
+ {
+ switch (l_ByteValue)
+ {
+ case VALUE_5:
+ l_densityPerDie = SDRAM_DENSITY_PER_DIE_24GB;
+ break;
+
+ case VALUE_6:
+ l_densityPerDie = SDRAM_DENSITY_PER_DIE_32GB;
+ break;
+
+ case VALUE_7:
+ l_densityPerDie = SDRAM_DENSITY_PER_DIE_48GB;
+ break;
+
+ case VALUE_8:
+ l_densityPerDie = SDRAM_DENSITY_PER_DIE_64GB;
+ break;
+
+ default:
+ cout << "default value encountered for density per die" << endl;
+ l_densityPerDie = SDRAM_DENSITY_PER_DIE_UNDEFINED;
+ break;
+ }
+ }
+ return l_densityPerDie;
+}
+
+uint8_t memoryVpdParser::getDDR5DiePerPackage(uint8_t l_ByteValue)
+{
+ uint8_t l_DiePerPackage = constants::VALUE_0;
+ if (l_ByteValue < constants::VALUE_2)
+ {
+ l_DiePerPackage = l_ByteValue + constants::VALUE_1;
+ }
+ else
+ {
+ l_DiePerPackage = pow(constants::VALUE_2,
+ (l_ByteValue - constants::VALUE_1));
+ }
+ return l_DiePerPackage;
+}
+
+auto memoryVpdParser::getDdr5BasedDDimmSize(Binary::const_iterator iterator)
+{
+ size_t dimmSize = 0;
+
+ do
+ {
+ if (!checkValidValue(iterator[constants::SPD_BYTE_235] &
+ constants::MASK_BYTE_BITS_01,
+ constants::SHIFT_BITS_0, constants::VALUE_1,
+ constants::VALUE_3) ||
+ !checkValidValue(iterator[constants::SPD_BYTE_235] &
+ constants::MASK_BYTE_BITS_345,
+ constants::SHIFT_BITS_3, constants::VALUE_1,
+ constants::VALUE_3))
+ {
+ std::cerr
+ << "Capacity calculation failed for channels per DIMM. DDIMM Byte 235 value ["
+ << iterator[constants::SPD_BYTE_235] << "]";
+ break;
+ }
+ uint8_t l_channelsPerDDimm =
+ (((iterator[constants::SPD_BYTE_235] & constants::MASK_BYTE_BITS_01)
+ ? constants::VALUE_1
+ : constants::VALUE_0) +
+ ((iterator[constants::SPD_BYTE_235] &
+ constants::MASK_BYTE_BITS_345)
+ ? constants::VALUE_1
+ : constants::VALUE_0));
+
+ if (!checkValidValue(iterator[constants::SPD_BYTE_235] &
+ constants::MASK_BYTE_BITS_012,
+ constants::SHIFT_BITS_0, constants::VALUE_1,
+ constants::VALUE_3))
+ {
+ std::cerr
+ << "Capacity calculation failed for bus width per channel. DDIMM Byte 235 value ["
+ << iterator[constants::SPD_BYTE_235] << "]";
+ break;
+ }
+ uint8_t l_busWidthPerChannel =
+ (iterator[constants::SPD_BYTE_235] & constants::MASK_BYTE_BITS_012)
+ ? PRIMARY_BUS_WIDTH_32_BITS
+ : PRIMARY_BUS_WIDTH_UNUSED;
+
+ if (!checkValidValue(iterator[constants::SPD_BYTE_4] &
+ constants::MASK_BYTE_BITS_567,
+ constants::SHIFT_BITS_5, constants::VALUE_0,
+ constants::VALUE_5))
+ {
+ std::cerr
+ << "Capacity calculation failed for die per package. DDIMM Byte 4 value ["
+ << iterator[constants::SPD_BYTE_4] << "]";
+ break;
+ }
+ uint8_t l_diePerPackage = getDDR5DiePerPackage(
+ (iterator[constants::SPD_BYTE_4] & constants::MASK_BYTE_BITS_567) >>
+ constants::VALUE_5);
+
+ if (!checkValidValue(iterator[constants::SPD_BYTE_4] &
+ constants::MASK_BYTE_BITS_01234,
+ constants::SHIFT_BITS_0, constants::VALUE_1,
+ constants::VALUE_8))
+ {
+ std::cerr
+ << "Capacity calculation failed for SDRAM Density per Die. DDIMM Byte 4 value ["
+ << iterator[constants::SPD_BYTE_4] << "]";
+ break;
+ }
+ uint8_t l_densityPerDie = getDDR5DensityPerDie(
+ iterator[constants::SPD_BYTE_4] & constants::MASK_BYTE_BITS_01234);
+
+ uint8_t l_ranksPerChannel = ((iterator[constants::SPD_BYTE_234] &
+ constants::MASK_BYTE_BITS_345) >>
+ constants::VALUE_3) +
+ (iterator[constants::SPD_BYTE_234] &
+ constants::MASK_BYTE_BITS_012) +
+ constants::VALUE_2;
+
+ if (!checkValidValue(iterator[constants::SPD_BYTE_6] &
+ constants::MASK_BYTE_BITS_567,
+ constants::SHIFT_BITS_5, constants::VALUE_0,
+ constants::VALUE_3))
+ {
+ std::cout
+ << "Capacity calculation failed for dram width DDIMM Byte 6 value ["
+ << iterator[constants::SPD_BYTE_6] << "]";
+ break;
+ }
+ uint8_t l_dramWidth = VALUE_4 *
+ (VALUE_1 << ((iterator[constants::SPD_BYTE_6] &
+ constants::MASK_BYTE_BITS_567) >>
+ constants::VALUE_5));
+
+ dimmSize = (l_channelsPerDDimm * l_busWidthPerChannel *
+ l_diePerPackage * l_densityPerDie * l_ranksPerChannel) /
+ (8 * l_dramWidth);
+
+ } while (1);
+
+ return constants::CONVERT_MB_TO_KB * dimmSize;
+}
+
+auto memoryVpdParser::getDdr4BasedDDimmSize(Binary::const_iterator iterator)
{
size_t tmp = 0, dimmSize = 0;
@@ -46,7 +223,7 @@
// NOTE: This calculation is Only for DDR4
// Calculate SDRAM capacity
- tmp = iterator[MEM_BYTE_4] & JEDEC_SDRAM_CAP_MASK;
+ tmp = iterator[SPD_BYTE_4] & JEDEC_SDRAM_CAP_MASK;
/* Make sure the bits are not Reserved */
if (tmp > JEDEC_SDRAMCAP_RESERVED)
{
@@ -58,7 +235,7 @@
sdramCap = (sdramCap << tmp) * JEDEC_SDRAMCAP_MULTIPLIER;
/* Calculate Primary bus width */
- tmp = iterator[MEM_BYTE_13] & JEDEC_PRI_BUS_WIDTH_MASK;
+ tmp = iterator[SPD_BYTE_13] & JEDEC_PRI_BUS_WIDTH_MASK;
if (tmp > JEDEC_RESERVED_BITS)
{
cerr << "Bad data in vpd byte 13. Can't calculate primary bus width "
@@ -68,7 +245,7 @@
priBusWid = (priBusWid << tmp) * JEDEC_PRI_BUS_WIDTH_MULTIPLIER;
/* Calculate SDRAM width */
- tmp = iterator[MEM_BYTE_12] & JEDEC_SDRAM_WIDTH_MASK;
+ tmp = iterator[SPD_BYTE_12] & JEDEC_SDRAM_WIDTH_MASK;
if (tmp > JEDEC_RESERVED_BITS)
{
cerr << "Bad data in vpd byte 12. Can't calculate SDRAM width and so "
@@ -77,18 +254,18 @@
}
sdramWid = (sdramWid << tmp) * JEDEC_SDRAM_WIDTH_MULTIPLIER;
- tmp = iterator[MEM_BYTE_6] & JEDEC_SIGNAL_LOADING_MASK;
+ tmp = iterator[SPD_BYTE_6] & JEDEC_SIGNAL_LOADING_MASK;
if (tmp == JEDEC_SINGLE_LOAD_STACK)
{
// Fetch die count
- tmp = iterator[MEM_BYTE_6] & JEDEC_DIE_COUNT_MASK;
+ tmp = iterator[SPD_BYTE_6] & JEDEC_DIE_COUNT_MASK;
tmp >>= JEDEC_DIE_COUNT_RIGHT_SHIFT;
dieCount = tmp + 1;
}
/* Calculate Number of ranks */
- tmp = iterator[MEM_BYTE_12] & JEDEC_NUM_RANKS_MASK;
+ tmp = iterator[SPD_BYTE_12] & JEDEC_NUM_RANKS_MASK;
tmp >>= JEDEC_RESERVED_BITS;
if (tmp > JEDEC_RESERVED_BITS)
@@ -104,12 +281,33 @@
return constants::CONVERT_MB_TO_KB * dimmSize;
}
+size_t memoryVpdParser::getDDimmSize(Binary::const_iterator iterator)
+{
+ size_t dimmSize = 0;
+ if ((iterator[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
+ constants::SPD_DRAM_TYPE_DDR4)
+ {
+ dimmSize = getDdr4BasedDDimmSize(iterator);
+ }
+ else if ((iterator[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
+ constants::SPD_DRAM_TYPE_DDR5)
+ {
+ dimmSize = getDdr5BasedDDimmSize(iterator);
+ }
+ else
+ {
+ cerr << "Error: DDIMM is neither DDR4 nor DDR5. DDIMM Byte 2 value ["
+ << iterator[constants::SPD_BYTE_2] << "]";
+ }
+ return dimmSize;
+}
+
kwdVpdMap memoryVpdParser::readKeywords(Binary::const_iterator iterator)
{
KeywordVpdMap map{};
// collect Dimm size value
- auto dimmSize = getDimmSize(iterator);
+ auto dimmSize = getDDimmSize(iterator);
if (!dimmSize)
{
cerr << "Error: Calculated dimm size is 0.";