From e343aa0915640a081eba91a565fb3d2b9af2922c Mon Sep 17 00:00:00 2001 From: Brian Silver Date: Thu, 22 Sep 2016 12:46:34 -0500 Subject: [PATCH] Add 3DS DIMM support Change-Id: Ida75c3f7f21b7bee358d0815805937b22f21c40d Original-Change-Id: Iab21b0e0aae34053ea8eab70cca6d8e65b75c308 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/30354 Tested-by: Jenkins Server Tested-by: Hostboot CI Reviewed-by: STEPHEN GLANCY Reviewed-by: ANDRE A. MARIN Reviewed-by: Christian R. Geddes Reviewed-by: Matt K. Light Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/37404 Reviewed-by: Daniel M. Crowell Tested-by: Daniel M. Crowell --- .../p9/procedures/hwp/memory/lib/mc/xlate.C | 1412 +++++++++++++++-- .../p9/procedures/hwp/memory/lib/mc/xlate.H | 505 +++++- 2 files changed, 1723 insertions(+), 194 deletions(-) diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C b/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C index 432015dd9db..fdb92513d23 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C @@ -57,60 +57,318 @@ namespace mc /// A little vector of translators. We have one of these for each DIMM we support static const std::vector xlate_map = { - // 2R4Gbx4 DDR4 RDIMM + // 1R 4Gbx4 DDR4 RDIMM { - dimm::kind(2, 0, 4, 4, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 16), - xlate_dimm_2R4Gbx4 + dimm::kind(1, 1, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 8), + xlate_dimm_1R1T4Gbx4 }, + + // 1R 8Gbx4 DDR4 RDIMM + { + dimm::kind(1, 1, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 16), + xlate_dimm_1R1T8Gbx4 + }, + + // 1R 16Gbx4 DDR4 RDIMM + { + dimm::kind(1, 1, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 32), + xlate_dimm_1R1T16Gbx4 + }, + + // 2R 4Gbx4 DDR4 RDIMM + { + dimm::kind(2, 2, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 16), + xlate_dimm_2R2T4Gbx4 + }, + + // 2R 8Gbx4 DDR4 RDIMM + { + dimm::kind(2, 2, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 32), + xlate_dimm_2R2T8Gbx4 + }, + + // 2R 16Gbx4 DDR4 RDIMM + { + dimm::kind(2, 2, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 64), + xlate_dimm_2R2T16Gbx4 + }, + + // 4R 4Gbx4 DDR4 RDIMM + { + dimm::kind(4, 4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 32), + xlate_dimm_4R4T4Gbx4 + }, + + // 4R 8Gbx4 DDR4 RDIMM + { + dimm::kind(4, 4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 64), + xlate_dimm_4R4T8Gbx4 + }, + + // 4R 16Gbx4 DDR4 RDIMM + { + dimm::kind(4, 4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 128), + xlate_dimm_4R4T16Gbx4 + }, + + + + // + // 3DS + // + + // 1R 2H 3DS 4Gbx4 DDR4 RDIMM + { + dimm::kind(1, 2, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 16), + xlate_dimm_1R2T4Gbx4 + }, + + // 1R 2H 3DS 8Gbx4 DDR4 RDIMM + { + dimm::kind(1, 2, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 32), + xlate_dimm_1R2T8Gbx4 + }, + + // 1R 2H 3DS 16Gbx4 DDR4 RDIMM + { + dimm::kind(1, 2, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 64), + xlate_dimm_1R2T16Gbx4 + }, + + // 1R 4H 3DS 4Gbx4 DDR4 RDIMM + { + dimm::kind(1, 4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 32), + xlate_dimm_1R4T4Gbx4 + }, + + // 1R 4H 3DS 8Gbx4 DDR4 RDIMM + { + dimm::kind(1, 4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 64), + xlate_dimm_1R4T8Gbx4 + }, + + // 1R 4H 3DS 16Gbx4 DDR4 RDIMM + { + dimm::kind(1, 4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 128), + xlate_dimm_1R4T16Gbx4 + }, + + // 1R 8H 3DS 4Gbx4 DDR4 RDIMM + { + dimm::kind(1, 8, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 64), + xlate_dimm_1R8T4Gbx4 + }, + + // 1R 8H 3DS 8Gbx4 DDR4 RDIMM + { + dimm::kind(1, 8, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 128), + xlate_dimm_1R8T8Gbx4 + }, + + // 1R 8H 3DS 16Gbx4 DDR4 RDIMM + { + dimm::kind(1, 8, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 256), + xlate_dimm_1R8T16Gbx4 + }, + + + // 2R 2H 3DS 4Gbx4 DDR4 RDIMM + { + dimm::kind(2, 4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 32), + xlate_dimm_2R4T4Gbx4 + }, + + // 2R 2H 3DS 8Gbx4 DDR4 RDIMM + { + dimm::kind(2, 4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 64), + xlate_dimm_2R4T8Gbx4 + }, + + // 2R 2H 3DS 16Gbx4 DDR4 RDIMM { - dimm::kind(1, 0, 4, 4, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 8), - xlate_dimm_1R4Gbx4 + dimm::kind(2, 4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 128), + xlate_dimm_2R4T16Gbx4 + }, + + + // 2R 4H 3DS 4Gbx4 DDR4 RDIMM + { + dimm::kind(2, 8, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 64), + xlate_dimm_2R8T4Gbx4 + }, + + // 2R 4H 3DS 8Gbx4 DDR4 RDIMM + { + dimm::kind(2, 8, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 128), + xlate_dimm_2R8T8Gbx4 + }, + + // 2R 4H 3DS 16Gbx4 DDR4 RDIMM + { + dimm::kind(2, 8, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 256), + xlate_dimm_2R8T16Gbx4 + }, + + + // 2R 8H 3DS 4Gbx4 DDR4 RDIMM + { + dimm::kind(2, 16, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 128), + xlate_dimm_2R16T4Gbx4 + }, + + // 2R 8H 3DS 8Gbx4 DDR4 RDIMM + { + dimm::kind(2, 16, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 256), + xlate_dimm_2R16T8Gbx4 + }, + + // 2R 8H 3DS 16Gbx4 DDR4 RDIMM + { + dimm::kind(2, 16, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, + fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 16, 512), + xlate_dimm_2R16T16Gbx4 }, }; +/// +/// @brief Helper to determine if a given DIMM is the only 1R DIMM on a port +/// @param[in] i_target the DIMM in question +/// @note 1R DIMM are special. We need to handle 2 1R DIMM on a port as a special case - kind of make them look like +/// a single 2R DIMM. So we have to do a little dance here to get our partners configuration. +/// @return true iff all slots are have 1R DIMM installed +/// +static bool all_slots_1R_helper(const fapi2::Target& i_target) +{ + const auto& l_mca = mss::find_target(i_target); + const auto& l_dimms = mss::find_targets(l_mca); + + const std::vector l_dimm_kinds = dimm::kind::vector(l_dimms); + bool l_all_slots_1R = false; + + // If we only have 1 DIMM, we don't have two slots with 1R DIMM. If we need to check, iterate + // over the DIMM kinds and make sure all the DIMM have one master and one total ranks (not 3DS). + if (l_dimms.size() > 1) + { + l_all_slots_1R = true; + + for (const auto& k : l_dimm_kinds) + { + l_all_slots_1R &= (k.iv_master_ranks == 1) && (k.iv_total_ranks == 1); + } + + FAPI_INF("We have a 1R DIMM %s and more than one DIMM installed; all 1R? %s", + mss::c_str(i_target), (l_all_slots_1R == true ? "yes" : "no") ); + } + + return l_all_slots_1R; +} + /// /// @brief Helper to lay down the col and bank mappings. -/// @param[in] o_xlate1 a buffer representing the xlate register to modify -/// @param[in] o_xlate2 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify /// @note This is for 16 bank DIMM, 32 bank DIMM will be different /// -static void column_and_16bank_helper(fapi2::buffer& l_xlate1, fapi2::buffer& l_xlate2) +static void column_and_16bank_helper(fapi2::buffer& io_xlate1, fapi2::buffer& io_xlate2) { // These are compile time freebies, so there's no need to bother putting them in a pre-defined // constant and or-ing them in. Keeps things much more clear when the performance team wants to muck // around with the settings. Mappings taken directly from the Nimbus Workbook. The magic numbers // aren't; they're settings as defined in the scomdef - l_xlate1.insertFromRight(0b01101); + constexpr uint64_t COL4_MAP(0b01101); + constexpr uint64_t COL5_MAP(0b01100); + constexpr uint64_t COL6_MAP(0b01011); + constexpr uint64_t COL7_MAP(0b01010); + constexpr uint64_t COL8_MAP(0b01001); + constexpr uint64_t COL9_MAP(0b00111); + constexpr uint64_t BANK0_MAP(0b01110); + constexpr uint64_t BANK1_MAP(0b10000); + constexpr uint64_t BG0_MAP(0b10001); + constexpr uint64_t BG1_MAP(0b10010); - l_xlate1.insertFromRight(0b01100); + io_xlate1.insertFromRight(COL4_MAP); - l_xlate1.insertFromRight(0b01011); + io_xlate1.insertFromRight(COL5_MAP); - l_xlate1.insertFromRight(0b01010); + io_xlate1.insertFromRight(COL6_MAP); - l_xlate2.insertFromRight(0b01001); + io_xlate1.insertFromRight(COL7_MAP); - l_xlate2.insertFromRight(0b00111); + io_xlate2.insertFromRight(COL8_MAP); - l_xlate2.insertFromRight(0b01110); + io_xlate2.insertFromRight(COL9_MAP); - l_xlate2.insertFromRight(0b10000); + io_xlate2.insertFromRight(BANK0_MAP); - l_xlate2.insertFromRight(0b10001); + io_xlate2.insertFromRight(BANK1_MAP); - l_xlate2.insertFromRight(0b10010); + io_xlate2.insertFromRight(BG0_MAP); + + io_xlate2.insertFromRight(BG1_MAP); +} + +/// +/// @brief D Bit helper - sets the d-bit +/// The D bit is the bit in the address which tells the controller to move to the +/// other DIMM on the slot. D is short for DIMM bit. +/// @param[in] i_target, the DIMM target (for tracing only) +/// @param[in] i_largest, true if we're the largest DIMM on the port +/// @param[in] i_offset, which side of the register to setup +/// @param[in] i_map the place to map the D bit in the register +/// @param[in,out] io_xlate the translation register +/// +static void d_bit_helper( const fapi2::Target& i_target, + const bool i_largest, + const uint64_t i_offset, + const uint64_t i_map, + fapi2::buffer& io_xlate0) +{ + // Setup the D-bit. If we're the largest DIMM, it is our mapping which maters. + // Notice that we don't care if the D-value bit has been set; this mapping needs to be setup regardless + // (SJ Powell says so) + if (i_largest) + { + FAPI_INF("setting d-bit mapping (am largest) 0x%x for %s", i_map, mss::c_str(i_target)); + io_xlate0.insertFromRight(i_map, MCS_PORT02_MCP0XLT0_D_BIT_MAP + i_offset, MCS_PORT02_MCP0XLT0_D_BIT_MAP_LEN); + } } /// @@ -118,105 +376,429 @@ static void column_and_16bank_helper(fapi2::buffer& l_xlate1, fapi2::b /// @param[in] i_kind the DIMM to map /// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 /// @param[in] i_largest whether or not we're the largest DIMM on the port. -/// @param[in] o_xlate a buffer representing the xlate register to modify -/// @param[in] o_xlate1 a buffer representing the xlate register to modify -/// @param[in] o_xlate2 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify /// @note Called for 2R4Gbx4 DDR4 RDIMM /// -void xlate_dimm_2R4Gbx4( const dimm::kind& i_kind, - const uint64_t i_offset, - const bool i_largest, - fapi2::buffer& o_xlate, - fapi2::buffer& o_xlate1, - fapi2::buffer& o_xlate2 ) +void xlate_dimm_2R2T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) { + constexpr uint64_t M1_MAP(0b01111); + constexpr uint64_t R15_MAP(0b00110); + constexpr uint64_t DBIT_MAP(0b00101); + // Set the proper bit if there is a DIMM in this slot. If there wasn't, we wouldn't see // this DIMM in the vector, so this is always safe. - o_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_VALID + i_offset); + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_VALID + i_offset); // Check our master ranks, and enable the proper bits. // Note this seems a little backward. M0 is the left most bit, M1 the right most. // So, M1 changes for ranks 0,1 and M0 changes for ranks 3,4 // 2 rank DIMM, so master bit 1 (least significant) bit needs to be mapped. - o_xlate.setBit(MCS_PORT13_MCP0XLT0_SLOT0_M1_VALID + i_offset); - o_xlate.insertFromRight(0b01111); + io_xlate0.setBit(MCS_PORT13_MCP0XLT0_SLOT0_M1_VALID + i_offset); + io_xlate0.insertFromRight(M1_MAP); // Tell the MC which of the row bits are valid, and map the DIMM selector // We're a 16 row DIMM, so ROW15 is valid. - o_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + i_offset); - o_xlate.insertFromRight(0b00110); + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + i_offset); + io_xlate0.insertFromRight(R15_MAP); // Drop down the column assignments - column_and_16bank_helper(o_xlate1, o_xlate2); + column_and_16bank_helper(io_xlate1, io_xlate2); + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} - // Setup the D-bit. If we're the largest DIMM, it is our mapping which maters. - // Notice tht we don't care if the D-value bit has been set; this mapping needs to be setup regardless (SJ Powell says so) - if (i_largest) - { - FAPI_INF("setting d-bit mapping (am largest) for %s", mss::c_str(i_kind.iv_target)); - o_xlate.insertFromRight(0b00101, MCS_PORT02_MCP0XLT0_D_BIT_MAP + i_offset, MCS_PORT02_MCP0XLT0_D_BIT_MAP_LEN); - } + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R2T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R16_MAP(0b00101); + constexpr uint64_t DBIT_MAP(0b00100); + + // We're basically a 2R 4Gbx4 with an extra row. So lets setup like we're one of those, + // add row 16 and shift the D bit as needed. + xlate_dimm_2R2T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Tell the MC which of the row bits are valid, and map the DIMM selector + // We're a 17 row DIMM, so ROW16 is valid. + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + i_offset); + io_xlate0.insertFromRight(R16_MAP); + + // Column assignments happened when we called xlate_dimm_2R2T4Gbx4 + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); } +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R2T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R17_MAP(0b00100); + constexpr uint64_t DBIT_MAP(0b00011); + + // We're basically a 2R 8Gbx4 with an extra row. So lets setup like we're one of those, + // add row 16 and shift the D bit as needed. + xlate_dimm_2R2T8Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Tell the MC which of the row bits are valid, and map the DIMM selector + // We're a 18 row DIMM, so ROW17 is valid. + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + i_offset); + io_xlate0.insertFromRight(R17_MAP); + + // Column assignments happened when we called xlate_dimm_2R2T8Gbx4 + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} /// /// @brief Perform initializations of the MC translation /// @param[in] i_kind the DIMM to map /// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 /// @param[in] i_largest whether or not we're the largest DIMM on the port. -/// @param[in] o_xlate a buffer representing the xlate register to modify -/// @param[in] o_xlate1 a buffer representing the xlate register to modify -/// @param[in] o_xlate2 a buffer representing the xlate register to modify -/// @note Called for 1R4Gbx4 DDR4 RDIMM -/// -void xlate_dimm_1R4Gbx4( const dimm::kind& i_kind, - const uint64_t i_offset, - const bool i_largest, - fapi2::buffer& o_xlate, - fapi2::buffer& o_xlate1, - fapi2::buffer& o_xlate2 ) -{ - // 1R DIMM are special. We need to handle 2 1R DIMM on a port as a special case - kind of make them look like - // a single 2R DIMM. So we have to do a little dance here to get our partners configuration. - const auto& l_mca = mss::find_target(i_kind.iv_target); - const auto& l_dimms = mss::find_targets(l_mca); +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 2H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R4T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t CLEAR_MAP(0b00000); + constexpr uint64_t M1_MAP(0b00110); - const std::vector l_dimm_kinds = dimm::kind::vector(l_dimms); - bool l_all_slots_1R = false; + // We're just like a 1R 4H 4Gbx4 so lets start there and modify for the slave ranks. + xlate_dimm_1R4T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); - // If we only have 1 DIMM, we don't have two slots with 1R DIMM. If we need to check, iterate - // over the DIMM kinds and make sure all the DIMM have one master and zero slaves. - if (l_dimms.size() > 1) - { - l_all_slots_1R = true; + io_xlate0.clearBit(MCS_PORT13_MCP0XLT0_SLOT0_S1_VALID + i_offset); + io_xlate1.insertFromRight(CLEAR_MAP); - for (const auto& k : l_dimm_kinds) - { - l_all_slots_1R &= (k.iv_master_ranks == 1) && (k.iv_slave_ranks == 0); - } + io_xlate0.setBit(MCS_PORT13_MCP0XLT0_SLOT0_M1_VALID + i_offset); + io_xlate0.insertFromRight(M1_MAP); - FAPI_INF("We have a 1R DIMM and more than one DIMM installed; all 1R? %s", - (l_all_slots_1R == true ? "yes" : "no") ); - } +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 2H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R4T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R16_MAP(0b00100); + constexpr uint64_t DBIT_MAP(0b00011); + + // We're just like a 2R 2H 4Gbx4 so lets start there and modify for the slave ranks. + xlate_dimm_2R4T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 16 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + i_offset); + io_xlate0.insertFromRight(R16_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 2H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R4T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R17_MAP(0b00011); + constexpr uint64_t DBIT_MAP(0b00010); + + // We're just like a 2R 2H 8Gbx4 so lets start there and modify for the slave ranks. + xlate_dimm_2R4T8Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 17 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + i_offset); + io_xlate0.insertFromRight(R17_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 4H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R8T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t CLEAR_MAP(0b00000); + constexpr uint64_t M1_MAP(0b00101); + + // We're just like a 1R 8H 4Gbx4 so lets start there and modify for the slave ranks. + xlate_dimm_1R8T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + io_xlate0.clearBit(MCS_PORT13_MCP0XLT0_SLOT0_S0_VALID + i_offset); + io_xlate1.insertFromRight(CLEAR_MAP); + + io_xlate0.setBit(MCS_PORT13_MCP0XLT0_SLOT0_M1_VALID + i_offset); + io_xlate0.insertFromRight(M1_MAP); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 4H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R8T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R16_MAP(0b00011); + constexpr uint64_t DBIT_MAP(0b00010); + + // We're just like a 2R 4H 3DS 4Gbx4 so lets start there and modify + xlate_dimm_2R8T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 16 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + i_offset); + io_xlate0.insertFromRight(R16_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 4H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R8T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R17_MAP(0b00010); + constexpr uint64_t DBIT_MAP(0b0001); + + // We're just like a 2R 2H 3DS 8Gbx4 so lets start there and modify + xlate_dimm_2R4T8Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 17 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + i_offset); + io_xlate0.insertFromRight(R17_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 8H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R16T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t M1_MAP(0b00100); + constexpr uint64_t R15_MAP(0b00011); + constexpr uint64_t DBIT_MAP(0b00010); + + // We're just like a 1R 8H 4Gbx4 so lets start there + xlate_dimm_1R8T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // We need to setup our M1 bit + io_xlate0.setBit(MCS_PORT13_MCP0XLT0_SLOT0_M1_VALID + i_offset); + io_xlate0.insertFromRight(M1_MAP); + + // Add in Row 15 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + i_offset); + io_xlate0.insertFromRight(R15_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 8H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R16T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R16_MAP(0b00010); + constexpr uint64_t DBIT_MAP(0b00001); + + // We're just like a 2R 8H 3DS 4Gbx4 DDR4 RDIMM + xlate_dimm_2R16T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 16 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + i_offset); + io_xlate0.insertFromRight(R16_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 8H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R16T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R17_MAP(0b00001); + constexpr uint64_t DBIT_MAP(0b0000); + + // We're just like a 2R 8H 3DS 8Gbx4 DDR4 RDIMM + xlate_dimm_2R16T8Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 17 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + i_offset); + io_xlate0.insertFromRight(R17_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R1T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + bool l_all_slots_1R = all_slots_1R_helper(i_kind.iv_target); // Set the proper bit if there is a DIMM in this slot. If there wasn't, we wouldn't see // this DIMM in the vector, so this is always safe. - o_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_VALID + i_offset); + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_VALID + i_offset); - // If we have all the slots filled in with 1R/0 slave DIMM, we build a very differnt mapping. + // If we have all the slots filled in with 1R SDP DIMM, we build a very differnt mapping. if (l_all_slots_1R) { + constexpr uint64_t R15_MAP(0b00110); + constexpr uint64_t DBIT_MAP(0b01111); + // Tell the MC which of the row bits are valid, and map the DIMM selector // We're a 16 row DIMM, so ROW15 is valid. - o_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + i_offset); - o_xlate.insertFromRight(0b00110); + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + i_offset); + io_xlate0.insertFromRight(R15_MAP); // Drop down the column assignments. - column_and_16bank_helper(o_xlate1, o_xlate2); + column_and_16bank_helper(io_xlate1, io_xlate2); // Setup the D-bit. Since both DIMM are identical, we just need to setup the map FAPI_INF("setting d-bit mapping (all 1R DIMM) for %s", mss::c_str(i_kind.iv_target)); - o_xlate.insertFromRight(0b01111); + io_xlate0.insertFromRight(DBIT_MAP); return; } @@ -225,155 +807,637 @@ void xlate_dimm_1R4Gbx4( const dimm::kind& i_kind, // Tell the MC which of the row bits are valid, and map the DIMM selector // We're a 16 row DIMM, so ROW15 is valid. - o_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + i_offset); - o_xlate.insertFromRight(0b00111); + + constexpr uint64_t COL4_MAP(0b01110); + constexpr uint64_t COL5_MAP(0b01101); + constexpr uint64_t COL6_MAP(0b01100); + constexpr uint64_t COL7_MAP(0b01011); + constexpr uint64_t COL8_MAP(0b01010); + constexpr uint64_t COL9_MAP(0b01001); + constexpr uint64_t BANK0_MAP(0b01111); + constexpr uint64_t BANK1_MAP(0b10000); + constexpr uint64_t BG0_MAP(0b10001); + constexpr uint64_t BG1_MAP(0b10010); + constexpr uint64_t R15_MAP(0b00111); + + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + i_offset); + io_xlate0.insertFromRight(R15_MAP); // We don't just drop down the col and bank assignments, they're different. - o_xlate1.insertFromRight(0b01110); + io_xlate1.insertFromRight(COL4_MAP); - o_xlate1.insertFromRight(0b01101); + io_xlate1.insertFromRight(COL5_MAP); - o_xlate1.insertFromRight(0b01100); + io_xlate1.insertFromRight(COL6_MAP); - o_xlate1.insertFromRight(0b01011); + io_xlate1.insertFromRight(COL7_MAP); - o_xlate2.insertFromRight(0b01010); + io_xlate2.insertFromRight(COL8_MAP); - o_xlate2.insertFromRight(0b01001); + io_xlate2.insertFromRight(COL9_MAP); - o_xlate2.insertFromRight(0b01111); + io_xlate2.insertFromRight(BANK0_MAP); - o_xlate2.insertFromRight(0b10000); + io_xlate2.insertFromRight(BANK1_MAP); - o_xlate2.insertFromRight(0b10001); + io_xlate2.insertFromRight(BG0_MAP); - o_xlate2.insertFromRight(0b10010); + io_xlate2.insertFromRight(BG1_MAP); - // There's nothing to do for the D-bit. We're either not the largest DIMM, in which case the lrgest DIMM + // There's nothing to do for the D-bit. We're either not the largest DIMM, in which case the largest DIMM // will fix up our D-bit mapping, or we're the only DIMM in the port. If we're the only DIMM in the port, // there is no D-bit mapping for a 1 slot 1R DIMM. return; } /// -/// @brief Perform initializations of the MC translation - MCA specialization -/// @param[in] i_target, the target which has the MCA to map -/// @return FAPI2_RC_SUCCESS iff ok +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 8Gbx4 DDR4 RDIMM /// -template<> -fapi2::ReturnCode setup_xlate_map(const fapi2::Target& i_target) +void xlate_dimm_1R1T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) { - fapi2::buffer l_xlate; - fapi2::buffer l_xlate1; - fapi2::buffer l_xlate2; + constexpr uint64_t R16_MAP_ALL_1R(0b00110); + constexpr uint64_t R16_MAP_NOT_ALL_1R(0b00101); - const auto l_dimms = i_target.getChildren(); + // We're more or less a 1R 4Gbx4 with an extra row. So lets setup like that and add our row in. + xlate_dimm_1R1T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); - // We need to keep around specifications of both DIMM as we set the D bit based on the sizes of the DIMM - std::vector l_dimm_kinds = dimm::kind::vector(l_dimms); + // If we have all the slots filled in with 1R SDP DIMM, we build a differnt mapping. + // Add the 17th row + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + i_offset); + io_xlate0.insertFromRight(all_slots_1R_helper(i_kind.iv_target) ? R16_MAP_ALL_1R : R16_MAP_NOT_ALL_1R); - FAPI_INF("Setting up xlate registers for MCA%d (%d)", mss::pos(i_target), mss::index(i_target)); + // There's nothing to do for the D-bit. We're either not the largest DIMM, in which case the largest DIMM + // will fix up our D-bit mapping, or we're the only DIMM in the port. If we're the only DIMM in the port, + // there is no D-bit mapping for a 1 slot 1R DIMM. + return; +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R1T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R16_MAP_ALL_1R(0b00101); + constexpr uint64_t R16_MAP_NOT_ALL_1R(0b00100); + + // We're more or less a 1R 8Gbx4 with an extra row. So lets setup like that and add our row in. + xlate_dimm_1R1T8Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // If we have all the slots filled in with 1R SDP DIMM, we build a differnt mapping. + // Add the 18th row + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + i_offset); + io_xlate0.insertFromRight(all_slots_1R_helper(i_kind.iv_target) ? R16_MAP_ALL_1R : R16_MAP_NOT_ALL_1R); + + // There's nothing to do for the D-bit. We're either not the largest DIMM, in which case the largest DIMM + // will fix up our D-bit mapping, or we're the only DIMM in the port. If we're the only DIMM in the port, + // there is no D-bit mapping for a 1 slot 1R DIMM. + return; +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 2H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R2T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t CLEAR_MAP(0b00000); + constexpr uint64_t S2_MAP(0b01111); + + // We're just like a 2R 4Gbx4 so lets start there and modify for the slave ranks. + xlate_dimm_2R2T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + io_xlate0.clearBit(MCS_PORT13_MCP0XLT0_SLOT0_M1_VALID + i_offset); + io_xlate0.insertFromRight(CLEAR_MAP); + + io_xlate0.setBit(MCS_PORT13_MCP0XLT0_SLOT0_S2_VALID + i_offset); + io_xlate1.insertFromRight(S2_MAP); +} + + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 2H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R2T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R16_MAP(0b00101); + constexpr uint64_t DBIT_MAP(0b00100); + + // We're just like a 1R 2H 4Gbx4 so lets start there + xlate_dimm_1R2T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 16 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + i_offset); + io_xlate0.insertFromRight(R16_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); + +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 2H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R2T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R17_MAP(0b00100); + constexpr uint64_t DBIT_MAP(0b00011); + + // We're just like a 1R 2H 8Gbx4 so lets start there + xlate_dimm_1R2T8Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 17 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + i_offset); + io_xlate0.insertFromRight(R17_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); + +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 4H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R4T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t S1_MAP(0b00110); + constexpr uint64_t R15_MAP(0b00101); + constexpr uint64_t DBIT_MAP(0b00100); + + // We're just like a 1R 2H 4Gbx4 so lets start there and modify for the slave ranks. + xlate_dimm_1R2T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // What was row 15 is now a slave rank, and we have to add in row 15 and the d-bit + io_xlate0.setBit(MCS_PORT13_MCP0XLT0_SLOT0_S1_VALID + i_offset); + io_xlate1.insertFromRight(S1_MAP); + + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + i_offset); + io_xlate0.insertFromRight(R15_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 4H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R4T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R16_MAP(0b00100); + constexpr uint64_t DBIT_MAP(0b00011); + + // We're just like a 1R 4H 4Gbx4 so lets start there and modify + xlate_dimm_1R4T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 16 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + i_offset); + io_xlate0.insertFromRight(R16_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); + +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 4H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R4T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R17_MAP(0b00011); + constexpr uint64_t DBIT_MAP(0b00010); + + // We're just like a 1R 4H 8Gbx4 so lets start there and modify + xlate_dimm_1R4T8Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Add in Row 17 + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + i_offset); + io_xlate0.insertFromRight(R17_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 8H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R8T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t S0_MAP(0b00101); + constexpr uint64_t R15_MAP(0b00100); + constexpr uint64_t DBIT_MAP(0b00011); + + // We're just like a 1R 4H 4Gbx4 so lets start there and modify for the slave ranks. + xlate_dimm_1R4T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + io_xlate0.setBit(MCS_PORT13_MCP0XLT0_SLOT0_S0_VALID + i_offset); + io_xlate1.insertFromRight(S0_MAP); + + // We're a 16 row DIMM, so ROW15 is valid. + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + i_offset); + io_xlate0.insertFromRight(R15_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 8H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R8T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R16_MAP(0b00011); + constexpr uint64_t DBIT_MAP(0b00010); + + // We're just like a 1R 8H 4Gbx4 so lets start there and modify for the slave ranks. + xlate_dimm_1R8T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // We're a 17 row DIMM, so ROW16 is valid. + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + i_offset); + io_xlate0.insertFromRight(R16_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 8H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R8T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R17_MAP(0b00010); + constexpr uint64_t DBIT_MAP(0b00001); + + // We're just like a 1R 8H 8Gbx4 so lets start there and modify for the slave ranks. + xlate_dimm_1R8T8Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // We're a 18 row DIMM, so ROW17 is valid. + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + i_offset); + io_xlate0.insertFromRight(R17_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 4R 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_4R4T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R15_MAP(0b00101); + constexpr uint64_t M0_MAP(0b00110); + constexpr uint64_t DBIT_MAP(0b00100); + + // We're just like a 2R 4Gbx4 except we have a valid M0 and a different DIMM bit. + xlate_dimm_2R2T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + // Our R15 is still valid, but slide it over to make room for the M0 bit + io_xlate0.insertFromRight(R15_MAP); + + io_xlate0.setBit(MCS_PORT13_MCP0XLT0_SLOT0_M0_VALID + i_offset); + io_xlate0.insertFromRight(M0_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 4R 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_4R4T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R16_MAP(0b00100); + constexpr uint64_t DBIT_MAP(0b00011); + + // We're just like a 4R 4Gbx4 except we have an extra row + xlate_dimm_4R4T4Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + i_offset); + io_xlate0.insertFromRight(R16_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 4R 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_4R4T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + constexpr uint64_t R17_MAP(0b00011); + constexpr uint64_t DBIT_MAP(0b00010); + + // We're just like a 4R 8Gbx4 except we have an extra row + xlate_dimm_4R4T8Gbx4(i_kind, i_offset, i_largest, io_xlate0, io_xlate1, io_xlate2); + + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + i_offset); + io_xlate0.insertFromRight(R17_MAP); + + d_bit_helper(i_kind.iv_target, i_largest, i_offset, DBIT_MAP, io_xlate0); +} + +/// +/// @brief Helper to setup the translation map - useful for testing +/// @param[in] i_dimm_kinds std::vector of DIMM kind's representing the DIMM (Not const as we sort the vector) +/// @param[out] fapi2::buffer io_xlate00 - xlt register 0's value +/// @param[out] fapi2::buffer io_xlate1 - xlt register 1's value +/// @param[out] fapi2::buffer io_xlate2 - xlt register 2's value +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode setup_xlate_map_helper( std::vector& i_dimm_kinds, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ) +{ + if (i_dimm_kinds.size() < 1) + { + FAPI_ERR("seeing an empty vector in the setup_xlate_map_helper"); + fapi2::Assert(false); + } // Considering the DIMM, record who gets the D bit. We make sure the *smallest* DIMM has the highest address // range by setting it's D bit to 1. This eliminates, or reduces, holes in the memory map. // However, we need to set that DIMM's D bit in the location of the largest DIMM's D-bit map (I know that's // hard to grok - set the D bit in the smallest DIMM but in the location mapped for the largest.) So we // keep track of the largest DIMM so when we set it up, we make sure to set the D-bit in the other. - std::sort(l_dimm_kinds.begin(), l_dimm_kinds.end(), [](const dimm::kind & a, const dimm::kind & b) -> bool + std::sort(i_dimm_kinds.begin(), i_dimm_kinds.end(), [](const dimm::kind & a, const dimm::kind & b) -> bool { return a.iv_size > b.iv_size; }); - FAPI_INF("DIMM with the largest size on this port is %s %dR %dgbx%d (%dG)", - mss::c_str(l_dimm_kinds[0].iv_target), - l_dimm_kinds[0].iv_master_ranks, l_dimm_kinds[0].iv_dram_density, - l_dimm_kinds[0].iv_dram_width, l_dimm_kinds[0].iv_size); + FAPI_INF("DIMM with the largest size on this port is %s %dMR (%d total ranks) %dgbx%d (%dG)", + mss::c_str(i_dimm_kinds[0].iv_target), + i_dimm_kinds[0].iv_master_ranks, + i_dimm_kinds[0].iv_total_ranks, + i_dimm_kinds[0].iv_dram_density, + i_dimm_kinds[0].iv_dram_width, + i_dimm_kinds[0].iv_size); - const auto l_d_bit_target = l_dimm_kinds[0].iv_target; + const auto l_d_bit_target = i_dimm_kinds[0].iv_target; // Get the functional DIMM on this port. - for (const auto& d : l_dimms) + for (const auto& k : i_dimm_kinds) { // Our slot (0, 1) is the same as our general index. - const uint64_t l_slot = mss::index(d); + const uint64_t l_slot = mss::index(k.iv_target); // Our slot offset tells us which 16 bit section in the xlt register to use for this DIMM // We'll either use the left most bits (slot 0) or move 16 bits to the right for slot 1. const uint64_t l_slot_offset = l_slot * 16; - // Grab our kind out of the vector - auto l_kind = std::find_if(l_dimm_kinds.begin(), l_dimm_kinds.end(), [&l_slot](const dimm::kind & k) -> bool - { - return mss::index(k.iv_target) == l_slot; - }); - - // If we don't find the fellow, we have a programming bug as we made the kind vector from the - // vector we're iterating over. - if (l_kind == l_dimm_kinds.end()) - { - FAPI_ERR("can't find our dimm in the kind vector: l_slot %d %s", l_slot, mss::c_str(d)); - fapi2::Assert(false); - } - - FAPI_DBG("address translation for DIMM %s %dR %dgbx%d (%dG) in slot %d", - mss::c_str(d), l_kind->iv_master_ranks, l_kind->iv_dram_density, - l_kind->iv_dram_width, l_kind->iv_size, l_slot); + FAPI_INF("address translation for DIMM %s %dMR (%d total ranks) %dgbx%d (%dG) in slot %d", + mss::c_str(k.iv_target), + k.iv_master_ranks, + k.iv_total_ranks, + k.iv_dram_density, + k.iv_dram_width, + k.iv_size, + l_slot); // Set the proper bit if there is a DIMM in this slot. If there wasn't, we wouldn't see // this DIMM in the vector, so this is always safe. - l_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_VALID + l_slot_offset); + io_xlate0.setBit(MCS_PORT02_MCP0XLT0_SLOT0_VALID + l_slot_offset); // Find the proper set function based on this DIMM kind. - const auto l_setup = std::find_if( xlate_map.begin(), xlate_map.end(), [l_kind](const xlate_setup & x) -> bool + const auto l_setup = std::find_if( xlate_map.begin(), xlate_map.end(), [k](const xlate_setup & x) -> bool { - return x.iv_kind == *l_kind; + return x.iv_kind == k; } ); + // If we didn't find it, raise a stink. + FAPI_ASSERT( l_setup != xlate_map.end(), + fapi2::MSS_NO_XLATE_FOR_DIMM(). + set_DIMM_IN_ERROR(k.iv_target). + set_MASTER_RANKS(k.iv_master_ranks). + set_TOTAL_RANKS(k.iv_total_ranks). + set_DRAM_DENSITY(k.iv_dram_density). + set_DRAM_WIDTH(k.iv_dram_width). + set_DRAM_GENERATION(k.iv_dram_generation). + set_DIMM_TYPE(k.iv_dimm_type). + set_ROWS(k.iv_rows). + set_SIZE(k.iv_size), + "no address translation funtion for DIMM %s %dMR (%d total ranks) %dgbx%d (%dG) in slot %d", + mss::c_str(k.iv_target), + k.iv_master_ranks, + k.iv_total_ranks, + k.iv_dram_density, + k.iv_dram_width, + k.iv_size, + l_slot ); + + // If we did find it ... // If we're the smallest DIMM in the port and we have more than one DIMM, we set our D-bit. - if( (l_d_bit_target != d) && (l_dimms.size() > 1) ) + if( (l_d_bit_target != k.iv_target) && (i_dimm_kinds.size() > 1) ) { - FAPI_INF("noting d-bit of 1 for %s", mss::c_str(d)); - l_xlate.setBit(MCS_PORT13_MCP0XLT0_SLOT0_D_VALUE + l_slot_offset); + FAPI_INF("noting d-bit of 1 for %s", mss::c_str(k.iv_target)); + io_xlate0.setBit(MCS_PORT13_MCP0XLT0_SLOT0_D_VALUE + l_slot_offset); } - // If we didn't find it, raise a stink. - FAPI_ASSERT( l_setup != xlate_map.end(), - fapi2::MSS_NO_XLATE_FOR_DIMM(). - set_DIMM_IN_ERROR(d). - set_MASTER_RANKS(l_kind->iv_master_ranks). - set_SLAVE_RANKS(l_kind->iv_slave_ranks). - set_DRAM_DENSITY(l_kind->iv_dram_density). - set_DRAM_WIDTH(l_kind->iv_dram_width). - set_DRAM_GENERATION(l_kind->iv_dram_generation). - set_DIMM_TYPE(l_kind->iv_dimm_type). - set_ROWS(l_kind->iv_rows). - set_SIZE(l_kind->iv_size), - "no address translation funtion for DIMM %s %dR %dgbx%d (%dG) in slot %d", - mss::c_str(d), l_kind->iv_master_ranks, l_kind->iv_dram_density, - l_kind->iv_dram_width, l_kind->iv_size, l_slot ); - - // If we did find it, call the translation function to fill in the blanks. + // Call the translation function to fill in the blanks. // The conditional argument tells the setup function whether this setup sould set the D bit, as we're // the largest DIMM on the port. - l_setup->iv_func(*l_kind, l_slot_offset, (l_kind->iv_target == l_d_bit_target), l_xlate, l_xlate1, l_xlate2); + l_setup->iv_func(k, l_slot_offset, (k.iv_target == l_d_bit_target), io_xlate0, io_xlate1, io_xlate2); } + FAPI_INF("cramming 0x%016lx in for MCP0XLT0", io_xlate0); + FAPI_INF("cramming 0x%016lx in for MCP0XLT1", io_xlate1); + FAPI_INF("cramming 0x%016lx in for MCP0XLT2", io_xlate2); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Perform initializations of the MC translation - MCA specialization +/// @param[in] i_target, the target which has the MCA to map +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode setup_xlate_map(const fapi2::Target& i_target) +{ + fapi2::buffer l_xlate0; + fapi2::buffer l_xlate1; + fapi2::buffer l_xlate2; + + const auto l_dimms = i_target.getChildren(); + + // We need to keep around specifications of both DIMM as we set the D bit based on the sizes of the DIMM + std::vector l_dimm_kinds = dimm::kind::vector(l_dimms); + + FAPI_INF("Setting up xlate registers for MCA%d (%d)", mss::pos(i_target), mss::index(i_target)); - FAPI_INF("cramming 0x%016lx in for MCP0XLT0", l_xlate); - FAPI_INF("cramming 0x%016lx in for MCP0XLT1", l_xlate1); - FAPI_INF("cramming 0x%016lx in for MCP0XLT2", l_xlate2); + FAPI_TRY( setup_xlate_map_helper(l_dimm_kinds, l_xlate0, l_xlate1, l_xlate2) ); - FAPI_TRY( mss::putScom(i_target, MCA_MBA_MCP0XLT0, l_xlate) ); + FAPI_TRY( mss::putScom(i_target, MCA_MBA_MCP0XLT0, l_xlate0) ); FAPI_TRY( mss::putScom(i_target, MCA_MBA_MCP0XLT1, l_xlate1) ); FAPI_TRY( mss::putScom(i_target, MCA_MBA_MCP0XLT2, l_xlate2) ); diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.H b/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.H index 850ed9be7e6..e59d86d772e 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.H @@ -82,36 +82,501 @@ struct xlate_setup /// /// @brief Perform initializations of the MC translation /// @param[in] i_kind the DIMM to map -/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 /// @param[in] i_largest whether or not we're the largest DIMM on the port. -/// @param[in] o_xlate a buffer representing the xlate register to modify -/// @param[in] o_xlate1 a buffer representing the xlate register to modify -/// @param[in] o_xlate2 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify /// @note Called for 2R4Gbx4 DDR4 RDIMM /// -void xlate_dimm_2R4Gbx4( const dimm::kind& i_kind, - const uint64_t i_offset, - const bool i_largest, - fapi2::buffer& o_xlate, - fapi2::buffer& o_xlate1, - fapi2::buffer& o_xlate2 ); +void xlate_dimm_2R2T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); /// /// @brief Perform initializations of the MC translation /// @param[in] i_kind the DIMM to map -/// @param[in] i_offset the offset; whether the DIMM ins slot 0 or slot 1 +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 /// @param[in] i_largest whether or not we're the largest DIMM on the port. -/// @param[in] o_xlate a buffer representing the xlate register to modify -/// @param[in] o_xlate1 a buffer representing the xlate register to modify -/// @param[in] o_xlate2 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R2T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R2T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 2H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R4T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 2H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R4T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 2H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R4T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 4H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R8T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 4H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R8T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 4H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R8T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 8H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R16T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 8H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R16T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 2R 8H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_2R16T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R1T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R1T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R1T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 2H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R2T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 2H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R2T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 2H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R2T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 4H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R4T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 4H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R4T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 4H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R4T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 8H 3DS 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R8T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 8H 3DS 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R8T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 8H 3DS 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R8T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 4R 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_4R4T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 4R 8Gbx4 DDR4 RDIMM +/// +void xlate_dimm_4R4T8Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 4R 16Gbx4 DDR4 RDIMM +/// +void xlate_dimm_4R4T16Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); +/// +/// @brief Helper to setup the translation map - useful for testing +/// @param[in] i_dimm_kinds std::vector of DIMM kind's representing the DIMM (Not const as we sort the vector) +/// @param[out] fapi2::buffer o_xlate0 - xlt register 0's value +/// @param[out] fapi2::buffer o_xlate1 - xlt register 1's value +/// @param[out] fapi2::buffer o_xlate2 - xlt register 2's value +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode setup_xlate_map_helper( std::vector& i_dimm_kinds, + fapi2::buffer& o_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify /// @note Called for 1R4Gbx4 DDR4 RDIMM /// -void xlate_dimm_1R4Gbx4( const dimm::kind& i_kind, - const uint64_t i_offset, - const bool i_largest, - fapi2::buffer& o_xlate, - fapi2::buffer& o_xlate1, - fapi2::buffer& o_xlate2 ); +void xlate_dimm_1R1T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); + +/// +/// @brief Perform initializations of the MC translation +/// @param[in] i_kind the DIMM to map +/// @param[in] i_offset the offset; whether the DIMM is in slot 0 or slot 1 +/// @param[in] i_largest whether or not we're the largest DIMM on the port. +/// @param[in,out] io_xlate0 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate1 a buffer representing the xlate register to modify +/// @param[in,out] io_xlate2 a buffer representing the xlate register to modify +/// @note Called for 1R 2 total ranks 4Gbx4 DDR4 RDIMM +/// +void xlate_dimm_1R2T4Gbx4( const dimm::kind& i_kind, + const uint64_t i_offset, + const bool i_largest, + fapi2::buffer& io_xlate0, + fapi2::buffer& io_xlate1, + fapi2::buffer& io_xlate2 ); } // ns mc