From 4921bf245e22bccc84c60a2030801ec6ee48dcd6 Mon Sep 17 00:00:00 2001 From: Mark Pizzutillo Date: Mon, 29 Jul 2019 17:41:16 -0500 Subject: Update exp_draminit results display for new response structs Change-Id: I65df040404585fd5cb3b9b79258e697333079dd8 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/81318 Tested-by: FSP CI Jenkins Tested-by: Jenkins Server Tested-by: PPE CI Reviewed-by: Louis Stermole Reviewed-by: STEPHEN GLANCY Tested-by: Hostboot CI Reviewed-by: Jennifer A Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/82252 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Christian R Geddes --- .../explorer/common/include/exp_data_structs.H | 137 ++++++++- .../explorer/procedures/hwp/memory/exp_draminit.C | 64 ++--- .../procedures/hwp/memory/lib/exp_draminit_utils.C | 271 +++++++++++++++++- .../procedures/hwp/memory/lib/exp_draminit_utils.H | 123 +++++++- .../hwp/memory/lib/phy/exp_train_display.C | 272 ++++++------------ .../hwp/memory/lib/phy/exp_train_display.H | 311 +++++++++++++++++++-- .../hwp/memory/lib/phy/exp_train_handler.C | 86 ++---- .../hwp/memory/lib/phy/exp_train_handler.H | 245 +++++++++++++++- .../xml/attribute_info/exp_attributes.xml | 16 ++ .../procedures/xml/error_info/mss_exp_errors.xml | 13 + src/import/generic/memory/lib/utils/mss_bad_bits.H | 28 ++ 11 files changed, 1231 insertions(+), 335 deletions(-) (limited to 'src/import') diff --git a/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H b/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H index dbd1c8d75..2e5fcf906 100644 --- a/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H +++ b/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H @@ -68,6 +68,10 @@ enum exp_struct_sizes TRAINING_RESPONSE_NUM_RC = 27, TRAINING_RESPONSE_MR6_SIZE = TRAINING_RESPONSE_NUM_RANKS * TRAINING_RESPONSE_NUM_DRAM, RCW_8BIT_CUTOFF = 16, + EYE_MIN_MAX_SIZE = 31, + DBYTE_N_SIZE = 10, + NIBBLE_N_SIZE = 20, + BIT_N_SIZE = 8, }; /// @@ -78,19 +82,20 @@ enum exp_struct_sizes typedef struct __attribute__((packed)) { // Command Header - uint8_t cmd_id; // Command type - uint8_t cmd_flags; // Various flags associated with the command - uint16_t request_identifier; // The request identifier of this transport request - uint32_t cmd_length; // Number of bytes following the UI header - uint32_t cmd_crc; // CRC of command data buffer, if used - uint32_t host_work_area; // Scratchpad area for Host, FW returns this value as a reponse - uint32_t cmd_work_area; // Scratchpad area for Firmware, can be used for tracking command progress etc. - uint32_t padding[CMD_PADDING_SIZE]; // Fill up to the size of one cache line - uint8_t command_argument[ARGUMENT_SIZE]; // Additional parameters associated with the command - uint32_t cmd_header_crc; // CRC of 64 bytes of command header + uint8_t cmd_id; // Command type + uint8_t cmd_flags; // Various flags associated with the command + uint16_t request_identifier; // The request identifier of this transport request + uint32_t cmd_length; // Number of bytes following the UI header + uint32_t cmd_crc; // CRC of command data buffer, if used + uint32_t host_work_area; // Scratchpad area for Host, FW returns this value as a reponse + uint32_t cmd_work_area; // Scratchpad area for Firmware, can be used for tracking command progress etc. + uint32_t padding[CMD_PADDING_SIZE]; // Fill up to the size of one cache line + uint8_t command_argument[ARGUMENT_SIZE]; // Additional parameters associated with the command + uint32_t cmd_header_crc; // CRC of 64 bytes of command header } host_fw_command_struct; + /// /// @class host_fw_response_struct /// @brief The firmware response structure @@ -744,6 +749,88 @@ typedef struct __attribute__((packed)) user_response_rc_msdg_t // F1RC_D0[26:16] BIT [7:0]: 8-bit value of F1RC1x~F1RCBx } user_response_rc_msdg_t; +/// +/// @class train_2d_eye_min_max_msdg_t +/// @brief Microchip response structure +/// +typedef struct __attribute__((packed)) train_2d_eye_min_max_msdg +{ + //2D training has to run with 1D training results in the delay registers. Horizontally it takes 1D + //centered value as starting position and only sweep half of a UI to left and right (1 UI in total). + //Vertically it takes preset vref value as starting position and sweep until bit error is detected. + //The assumption is that data eye will be enclosed in that range. + //eye_max/min contain the max/min VrefDAC0/VrefDQ value which passes test with the Nth step shift + //within the 1UI range. The 1D centered RxClkDly/TxDqDly is always normalized to index 15 of the + //array. + //In train_2d_read_eye_msdg, eye_max/min value represents VrefDAC0 (PHY DQ receiver Vref setting) + //Vref = (0.510 + VrefDAC0[6:0] * 0.00385) * VDDQ + //In train_2d_write_eye_msdg, eye_max/min value represents VrefDQ (Dram DQ receiver Vref setting) + //Vref = (0.450 + VrefDQ[6:0] * 0.0065) * VDDQ + uint16_t eye_min[EYE_MIN_MAX_SIZE]; + uint16_t eye_max[EYE_MIN_MAX_SIZE]; +} train_2d_eye_min_max_msdg_t; + +/// +/// @class train_2d_read_eye_msdg_t +/// @brief Microchip response structure +/// +typedef struct __attribute__((packed)) train_2d_read_eye_msdg +{ + //train_2d_read_eye_msdg_t returns the read eye diagram from point of view of 2D training firmware. + //1D training center RxClkDly (per nibble) horizontally (left and right search), 2D training does + //sweep on horizontal (RxClkDly) and vertical (VrefDAC0) directions, then decide the center. + //2D training has to run with 1D training results in the delay registers. Horizontally it takes 1D + //centered value as starting position and only sweep half of a UI to left and right (1 UI in total). + //Vertically it takes preset vref value as starting position and sweep until bit error is detected. + //The assumption is that data eye will be enclosed in that range. + //VrefDAC0[*][*][*] contains the max/min VrefDAC0 value which passes test with the Nth step shift + //within the 1UI range. The 1D centered RxClkDly is always normalized to index 15 of the + //array. + //With both arrays, 2D read eye diagram can be plotted on debug host. + + // VrefDAC0[RANKi][DBYTEn][BITn] Maximum + // and minimum passing VrefDAC0 in 2D read training + train_2d_eye_min_max_msdg_t VrefDAC0[TRAINING_RESPONSE_NUM_RANKS][DBYTE_N_SIZE][BIT_N_SIZE]; + + // VrefDAC0_Center[DBYTEn][BITn] Centered + // VrefDAC0 value after 2D read training + uint16_t VrefDAC0_Center[DBYTE_N_SIZE][BIT_N_SIZE]; + + // RxClkDly_Center[RANKi][NIBBLEn] Centered + // RxClkDly location (w.r.t. eye diagram) after 2D + // read training + uint16_t RxClkDly_Center[TRAINING_RESPONSE_NUM_RANKS][NIBBLE_N_SIZE]; +} train_2d_read_eye_msdg_t; + +typedef struct __attribute__((packed)) train_2d_write_eye_msdg +{ + //train_2d_write_eye_msdg_t returns the write eye diagram from point of view of 2D training + //firmware. + //1D training center TxDqDly (per DQ) horizontally (left and right search), 2D training does sweep + //on horizontal (TxDqDly) and vertical (VrefDQ) directions, then decide the center. + //2D training has to run with 1D training results in the delay registers. Horizontally it takes 1D + //centered value as starting position and only sweep half of a UI to left and right (1 UI in total). + //Vertically it takes preset vref value as starting position and sweep until bit error is detected. + //The assumption is that data eye will be enclosed in that range. + //VrefDQ[*][*][*] contains the max/min VrefDQ value which passes test with the Nth step shift within + //the 1UI range. The 1D centered TxDqDly is always normalized to index 15 of the array. + //With both arrays, 2D read eye diagram can be plotted on debug host. + + // VrefDQ[RANKi][DBYTEn][BITn] Maximum and + // minimum passing VrefDQ in 2D write training + train_2d_eye_min_max_msdg_t VrefDQ[TRAINING_RESPONSE_NUM_RANKS][DBYTE_N_SIZE][BIT_N_SIZE]; + + // VrefDQ_Center[RANKi][NIBBLEn] Centered VrefDQ + // value after 2D write training + uint16_t VrefDQ_Center[TRAINING_RESPONSE_NUM_RANKS][NIBBLE_N_SIZE]; + + // TxDqDly_Center[RANKi][DBYTEn][BITn] Centered + // TxDqDly location (w.r.t. eye diagram) after 2D + // write training + uint16_t TxDqDly_Center[TRAINING_RESPONSE_NUM_RANKS][DBYTE_N_SIZE][BIT_N_SIZE]; + +} train_2d_write_eye_msdg_t; + /// /// @class user_response_msdg_t /// @brief Microchip response structure @@ -758,4 +845,34 @@ typedef struct __attribute__((packed)) user_response_msdg } user_response_msdg_t; +/// +/// @class user_2d_eye_response_1_msdg_t +/// @brief Microchip response structure +/// +typedef struct __attribute__((packed)) user_2d_eye_response_1_msdg +{ + uint32_t version_number; + train_2d_read_eye_msdg_t read_2d_eye_resp; + user_response_timing_msdg_t tm_resp; + user_response_error_msdg_t err_resp; + user_response_mrs_msdg_t mrs_resp; + user_response_rc_msdg_t rc_resp; + +} user_2d_eye_response_1_msdg_t; + +/// +/// @class user_2d_eye_response_2_msdg_t +/// @brief Microchip response structure +/// +typedef struct __attribute__((packed)) user_2d_eye_response_2_msdg +{ + uint32_t version_number; + train_2d_write_eye_msdg_t write_2d_eye_resp; + user_response_timing_msdg_t tm_resp; + user_response_error_msdg_t err_resp; + user_response_mrs_msdg_t mrs_resp; + user_response_rc_msdg_t rc_resp; + +} user_2d_eye_response_2_msdg_t; + #endif diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C index ce9137db9..67ddf14d5 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C @@ -55,7 +55,7 @@ extern "C" mss::display_git_commit_info("exp_draminit"); uint32_t l_crc = 0; - host_fw_command_struct l_cmd; + uint8_t l_phy_init_mode = 0; user_input_msdg l_phy_params; FAPI_TRY(mss::exp::setup_phy_params(i_target, l_phy_params), @@ -65,54 +65,28 @@ extern "C" FAPI_TRY( mss::exp::ib::putUserInputMsdg(i_target, l_phy_params, l_crc), "Failed putUserInputMsdg() for %s", mss::c_str(i_target) ); - { - // Issue full boot mode cmd though EXP-FW REQ buffer - FAPI_TRY( mss::exp::setup_cmd_params(i_target, - l_crc, - sizeof(l_phy_params), - l_cmd) ); - FAPI_TRY( mss::exp::ib::putCMD(i_target, l_cmd), - "Failed putCMD() for %s", mss::c_str(i_target) ); - } + // Get phy init mode attribute + FAPI_TRY(mss::attr::get_exp_phy_init_mode(i_target, l_phy_init_mode)); - // Wait a bit for the command (and training) to complete - // Value based on initial Explorer hardware in Cronus in i2c mode. - // Training takes ~10ms with no trace, ~450ms with Explorer UART debug - FAPI_TRY( fapi2::delay( (mss::DELAY_1MS * 8), 200) ); + // Make sure we're in range + FAPI_ASSERT((l_phy_init_mode <= fapi2::ENUM_ATTR_MSS_OCMB_PHY_INIT_MODE_WITH_EYE_CAPTURE), + fapi2::MSS_EXP_UNKNOWN_PHY_INIT_MODE() + .set_TARGET(i_target) + .set_VALUE(l_phy_init_mode), + "%s Value for phy init mode for exp_draminit is unknown: %u expected 0 (NORMAL), 1 (WITH_EYE_CAPTURE)", + mss::c_str(i_target), l_phy_init_mode); - // Read the response message from EXP-FW RESP buffer + // Call appropriate init function + if (l_phy_init_mode == fapi2::ENUM_ATTR_MSS_OCMB_PHY_INIT_MODE_NORMAL) { - host_fw_response_struct l_response; - user_response_msdg l_train_response; - - std::vector l_rsp_data; - fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); - - FAPI_TRY( mss::exp::ib::getRSP(i_target, l_response, l_rsp_data), - "Failed getRSP() for %s", mss::c_str(i_target) ); - - // Proccesses the response data - FAPI_TRY( mss::exp::read_training_response(i_target, l_rsp_data, l_train_response), - "Failed read_training_response for %s", mss::c_str(i_target)); - - // Displays the training response - FAPI_TRY( mss::exp::train::display_info(i_target, l_train_response)); - - // Check if cmd was successful - l_rc = mss::exp::check::response(i_target, l_response, l_cmd); - - // If not, then we need to process the bad bitmap - if(l_rc != fapi2::FAPI2_RC_SUCCESS) - { - mss::exp::bad_bit_interface l_interface(l_train_response); - - // Record bad bits should only fail if we have an attributes issue - that's a major issue - FAPI_TRY(mss::record_bad_bits(i_target, l_interface)); - - // Now, go to our true error handling procedure - FAPI_TRY(l_rc, "mss::exp::check::response failed for %s", mss::c_str(i_target)); - } + FAPI_TRY(mss::exp::host_fw_phy_normal_init(i_target, l_crc)); } + else + { + FAPI_TRY(mss::exp::host_fw_phy_init_with_eye_capture(i_target, l_crc, l_phy_params)); + } + + return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: FAPI_INF("Draminit training - %s %s", diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.C index 843675d6e..de8d0cfad 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.C @@ -34,6 +34,9 @@ #include #include +#include +#include +#include namespace mss { @@ -41,34 +44,285 @@ namespace exp { /// -/// @brief host_fw_command_struct structure setup -/// @param[in] i_target the OCMB being acted upon +/// @brief Perform normal host FW phy init +/// +/// @param[in] i_target OCMB target +/// @param[in] i_crc CRC value +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode host_fw_phy_normal_init(const fapi2::Target& i_target, + const uint32_t i_crc) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + host_fw_command_struct l_cmd; + std::vector l_rsp_data; + + // Issue full boot mode cmd though EXP-FW REQ buffer + FAPI_TRY(send_host_phy_init_cmd(i_target, i_crc, phy_init_mode::NORMAL, l_cmd)); + FAPI_TRY(mss::exp::check_host_fw_response(i_target, l_cmd, l_rsp_data, l_rc)); + FAPI_TRY(mss::exp::read_and_display_normal_training_repsonse(i_target, l_rsp_data, l_rc)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Perform host FW phy init with eye capture +/// +/// @param[in] i_target OCMB target +/// @param[in] i_crc CRC value +/// @param[in] i_phy_params PHY params struct +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// @note the goal here is to attempt to send both phy_inits even in the event of a bad return code from the read & display +/// +fapi2::ReturnCode host_fw_phy_init_with_eye_capture(const fapi2::Target& i_target, + const uint32_t i_crc, + const user_input_msdg& i_phy_params) +{ + fapi2::ReturnCode l_check_response_1_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::ReturnCode l_read_display_response_1_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::ReturnCode l_check_response_2_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::ReturnCode l_read_display_response_2_rc = fapi2::FAPI2_RC_SUCCESS; + + user_2d_eye_response_1_msdg l_response_1; + user_2d_eye_response_2_msdg l_response_2; + + std::vector l_rsp_data; + + // First, step 1 + { + host_fw_command_struct l_cmd; + FAPI_TRY(send_host_phy_init_cmd(i_target, i_crc, phy_init_mode::EYE_CAPTURE_STEP_1, l_cmd)); + + // Return code output param is that of check::response + // A fail of getRSP will go to fapi_try_exit + FAPI_TRY(mss::exp::check_host_fw_response(i_target, l_cmd, l_rsp_data, l_check_response_1_rc)); + l_read_display_response_1_rc = mss::exp::read_and_display_user_2d_eye_response(i_target, l_rsp_data, l_response_1); + } + l_rsp_data.clear(); + + // Next, step 2 + { + host_fw_command_struct l_cmd; + uint32_t l_crc = 0; + + // Put user_input_msdg again for step 2 (overwritten by data buffer from step 1) + FAPI_TRY( mss::exp::ib::putUserInputMsdg(i_target, i_phy_params, l_crc), + "Failed putUserInputMsdg() for %s", mss::c_str(i_target) ); + + // Send cmd + FAPI_TRY(send_host_phy_init_cmd(i_target, l_crc, phy_init_mode::EYE_CAPTURE_STEP_2, l_cmd)); + + // Return code output param is that of check::response + // A fail of getRSP will go to fapi_try_exit + FAPI_TRY(mss::exp::check_host_fw_response(i_target, l_cmd, l_rsp_data, l_check_response_2_rc)); + + l_read_display_response_2_rc = mss::exp::read_and_display_user_2d_eye_response(i_target, l_rsp_data, l_response_2); + } + + // Check the return codes + FAPI_TRY(process_eye_capture_return_codes(i_target, + l_response_1, + l_response_2, + l_check_response_1_rc, + l_check_response_2_rc)); + + // Finally, check the display response return codes + FAPI_TRY(l_read_display_response_1_rc, "Error ocurred reading/displaying eye capture response 1 of %s", + mss::c_str(i_target)); + FAPI_TRY(l_read_display_response_2_rc, "Error ocurred reading/displaying eye capture response 2 of %s", + mss::c_str(i_target)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Process return codes from PHY init with eye capture operations +/// +/// @param[in] i_target OCMB target +/// @param[in] i_response_1 response struct for EYE_CAPTURE_STEP_1 +/// @param[in] i_response_2 response struct for EYE_CAPTURE_STEP_2 +/// @param[in] i_response_1_rc response from check_host_fw_response from EYE_CAPTURE_STEP_1 +/// @param[in] i_response_2_rc response from check_host_fw_response from EYE_CAPTURE_STEP_2 +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else an error from above as defined in the function algorithm +/// @note return codes are passed by value, caller should not expect these to change +/// +fapi2::ReturnCode process_eye_capture_return_codes(const fapi2::Target& i_target, + const user_2d_eye_response_1_msdg& i_response_1, + const user_2d_eye_response_2_msdg& i_response_2, + fapi2::ReturnCode i_response_1_rc, + fapi2::ReturnCode i_response_2_rc) +{ + const bool l_response_1_failed = i_response_1_rc != fapi2::FAPI2_RC_SUCCESS; + const bool l_response_2_failed = i_response_2_rc != fapi2::FAPI2_RC_SUCCESS; + + if (l_response_2_failed) + { + FAPI_ERR("%s check_fw_host_response() for %s returned error code 0x%016llu", + mss::c_str(i_target), "EYE_CAPTURE_STEP_2", uint64_t(i_response_2_rc)); + + mss::exp::bad_bit_interface l_interface_2(i_response_2); + FAPI_TRY(mss::record_bad_bits(i_target, l_interface_2)); + + if (l_response_1_failed) + { + // Log response 2's error, and let's return response 1 + fapi2::logError(i_response_2_rc, fapi2::FAPI2_ERRL_SEV_RECOVERED); + + // logError sets the return code& to NULL. Set to FAPI2_RC_SUCCESS in case of use + i_response_2_rc = fapi2::FAPI2_RC_SUCCESS; + } + + FAPI_TRY(i_response_2_rc); + } + + if (l_response_1_failed) + { + FAPI_ERR("%s check_fw_host_response() for %s returned error code 0x%016llu", + mss::c_str(i_target), "EYE_CAPTURE_STEP_1", uint64_t(i_response_1_rc)); + + mss::exp::bad_bit_interface l_interface_1(i_response_1); + FAPI_TRY(mss::record_bad_bits(i_target, l_interface_1)); + + return i_response_1_rc; + } + + // Else, we did not see errors! + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Send PHY init command given the provided phy mode and CRC +/// +/// @param[in] i_target OCMB target +/// @param[in] i_crc CRC field +/// @param[in] i_phy_init_mode normal / eye capture step 1 or 2 +/// @param[out] host_fw_command_struct used for initialization +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode send_host_phy_init_cmd(const fapi2::Target& i_target, + const uint32_t i_crc, + const uint8_t i_phy_init_mode, + host_fw_command_struct& o_cmd) +{ + host_fw_command_struct l_cmd; + + // Issue full boot mode cmd though EXP-FW REQ buffer + FAPI_TRY(setup_cmd_params(i_target, i_crc, sizeof(user_input_msdg), i_phy_init_mode, l_cmd)); + FAPI_TRY(mss::exp::ib::putCMD(i_target, l_cmd), + "Failed putCMD() for %s", mss::c_str(i_target)); + + // Wait a bit for the command (and training) to complete + // Value based on initial Explorer hardware in Cronus in i2c mode. + // Training takes ~10ms with no trace, ~450ms with Explorer UART debug + FAPI_TRY(fapi2::delay((mss::DELAY_1MS * 8), 200)); + + o_cmd = l_cmd; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Get and check the host fw response from the explorer +/// +/// @param[in] i_target OCMB chip +/// @param[in] i_cmd host_fw_command_struct used to generate the response +/// @param[out] o_rsp_data response data +/// @param[out] o_rc return code from mss::exp::check::response() +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code +/// +fapi2::ReturnCode check_host_fw_response(const fapi2::Target& i_target, + host_fw_command_struct& i_cmd, + std::vector& o_rsp_data, + fapi2::ReturnCode& o_rc) +{ + host_fw_response_struct l_response; + + FAPI_TRY(mss::exp::ib::getRSP(i_target, l_response, o_rsp_data), + "Failed getRSP() for %s", mss::c_str(i_target)); + + o_rc = mss::exp::check::response(i_target, l_response, i_cmd); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Reads and displays the normal draminit training response +/// +/// @param[in] i_target OCMB target +/// @param[in] i_resp_data RESP data +/// @param[in] i_rc return code from checking response +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode read_and_display_normal_training_repsonse( + const fapi2::Target& i_target, + const std::vector i_resp_data, + const fapi2::ReturnCode i_rc) +{ + user_response_msdg l_train_response; + + // Proccesses the response data + FAPI_TRY( mss::exp::read_normal_training_response(i_target, i_resp_data, l_train_response), + "Failed read_training_response for %s", mss::c_str(i_target)); + + // Displays the training response + FAPI_INF("%s displaying user response data version %u", mss::c_str(i_target), l_train_response.version_number) + FAPI_TRY( mss::exp::train::display_normal_info(i_target, l_train_response)); + + if(i_rc != fapi2::FAPI2_RC_SUCCESS) + { + mss::exp::bad_bit_interface l_interface(l_train_response); + FAPI_TRY(mss::record_bad_bits(i_target, l_interface)); + FAPI_TRY(i_rc, "mss::exp::check::response failed for %s", mss::c_str(i_target)); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief host_fw_phy_init_command_struct structure setup +/// +/// @param[in] i_target OCMB target /// @param[in] i_cmd_data_crc the command data CRC /// @param[in] i_cmd_length the length of the command present in the data buffer (if any) +/// @param[in] i_phy_init_mode PHY init mode /// @param[out] o_cmd the command parameters to set /// fapi2::ReturnCode setup_cmd_params( const fapi2::Target& i_target, const uint32_t i_cmd_data_crc, - const uint8_t i_cmd_length, + const uint32_t i_cmd_length, + const uint8_t i_phy_init_mode, host_fw_command_struct& o_cmd) { + static constexpr uint8_t EYE_CAPTURE_STEP_1 = 1; memset(&o_cmd, 0, sizeof(host_fw_command_struct)); // Issue full boot mode cmd though EXP-FW REQ buffer // Explicit with all of these (including 0 values) to avoid ambiguity o_cmd.cmd_id = mss::exp::omi::EXP_FW_DDR_PHY_INIT; - o_cmd.cmd_flags = 0; // Retrieve a unique sequence id for this transaction uint32_t l_counter = 0; FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_OCMB_COUNTER, i_target, l_counter)); - o_cmd.request_identifier = l_counter; + + // STEP_1 = 1, STEP_2 = 0 as defined in MCHP spec section 5.4.3 Eye Capture + o_cmd.cmd_flags = i_phy_init_mode == EYE_CAPTURE_STEP_1 ? 1 : 0; + o_cmd.cmd_length = i_cmd_length; o_cmd.cmd_crc = i_cmd_data_crc; o_cmd.host_work_area = 0; o_cmd.cmd_work_area = 0; - memset(o_cmd.padding, 0, sizeof(o_cmd.padding)); + + // According to the spec Table 5-2, phy_init_mode takes the place of command_argument[0] + o_cmd.command_argument[0] = i_phy_init_mode; fapi_try_exit: return fapi2::current_err; @@ -184,8 +438,9 @@ fapi2::ReturnCode response(const fapi2::Target& i_ set_ERROR_CODE(i_rsp.response_argument[1]). set_EXPECTED_REQID(i_cmd.request_identifier). set_ACTUAL_REQID(i_rsp.request_identifier), - "Failed to initialize the PHY for %s, response=0x%X", - mss::c_str(i_target), i_rsp.response_argument[0]); + "Failed to initialize the PHY for %s, response=0x%X " + "RSP RQ ID: %u CMD RQ ID: %u", + mss::c_str(i_target), i_rsp.response_argument[0], i_rsp.request_identifier, i_cmd.request_identifier); return fapi2::FAPI2_RC_SUCCESS; diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.H index 88d814ede..39598303d 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.H @@ -46,6 +46,9 @@ #include #include #include +#include +#include +#include #include namespace mss @@ -53,6 +56,16 @@ namespace mss namespace exp { +/// +/// @brief Phy init mode for host_fw_command struct +/// +enum phy_init_mode +{ + NORMAL = 0, + EYE_CAPTURE_STEP_1 = 1, + EYE_CAPTURE_STEP_2 = 2, +}; + /// /// @brief defines the supported DIMM types in Explorer /// @@ -148,18 +161,126 @@ enum odt_fields RANK0 = 0, }; +/// +/// @brief Perform normal host FW phy init +/// +/// @param[in] i_target OCMB target +/// @param[in] i_crc CRC value +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode host_fw_phy_normal_init(const fapi2::Target& i_target, + const uint32_t i_crc); + +/// +/// @brief Perform host FW phy init with eye capture +/// +/// @param[in] i_target OCMB target +/// @param[in] i_crc CRC value +/// @param[in] i_phy_params PHY params struct +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// @note the goal here is to attempt to send both phy_inits even in the event of a bad return code from the read & display +/// +fapi2::ReturnCode host_fw_phy_init_with_eye_capture(const fapi2::Target& i_target, + const uint32_t i_crc, + const user_input_msdg& i_phy_params); + +/// +/// @brief Process return codes from PHY init with eye capture operations +/// +/// @param[in] i_target OCMB target +/// @param[in] i_response_1 response struct for EYE_CAPTURE_STEP_1 +/// @param[in] i_response_2 response struct for EYE_CAPTURE_STEP_2 +/// @param[in] i_response_1_rc response from check_host_fw_response from EYE_CAPTURE_STEP_1 +/// @param[in] i_response_2_rc response from check_host_fw_response from EYE_CAPTURE_STEP_2 +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else an error from above as defined in the function algorithm +/// @note return codes are passed by value, caller should not expect these to change +/// +fapi2::ReturnCode process_eye_capture_return_codes(const fapi2::Target& i_target, + const user_2d_eye_response_1_msdg& i_response_1, + const user_2d_eye_response_2_msdg& i_response_2, + fapi2::ReturnCode i_response_1_rc, + fapi2::ReturnCode i_response_2_rc); + +/// +/// @brief Send PHY init command given the provided phy mode and CRC +/// +/// @param[in] i_target OCMB target +/// @param[in] i_crc CRC field +/// @param[in] i_phy_init_mode normal / eye capture step 1 or 2 +/// @param[out] host_fw_command_struct used for initialization +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode send_host_phy_init_cmd(const fapi2::Target& i_target, + const uint32_t i_crc, + const uint8_t i_phy_init_mode, + host_fw_command_struct& o_cmd); + +/// +/// @brief Get and check the host fw response from the explorer +/// @param[in] i_target OCMB chip +/// @param[in] i_cmd host_fw_command_struct used to generate the response +/// @param[out] o_rsp_data response data +/// @param[out] o_rc return code from mss::exp::check::response() +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code +/// +fapi2::ReturnCode check_host_fw_response(const fapi2::Target& i_target, + host_fw_command_struct& i_cmd, + std::vector& o_rsp_data, + fapi2::ReturnCode& o_rc); + +/// +/// @brief Reads and displays the normal draminit training response +/// +/// @param[in] i_target OCMB target +/// @param[in] i_resp_data RESP data +/// @param[in] i_rc return code from checking response +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode read_and_display_normal_training_repsonse( + const fapi2::Target& i_target, + const std::vector i_resp_data, + const fapi2::ReturnCode i_rc); + +/// +/// @brief Reads and displays the user 2d eye response 1 +/// +/// @tparam T response struct +/// @param[in] i_target OCMB target +/// @param[in] i_resp_data RESP data +/// @param[out] o_rc return code from checking response +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success +/// +template +inline fapi2::ReturnCode read_and_display_user_2d_eye_response( + const fapi2::Target& i_target, + const std::vector i_resp_data, + T& o_train_response) +{ + // Proccesses the response data + FAPI_TRY(mss::exp::read_user_2d_eye_response(i_target, i_resp_data, o_train_response), + "Failed read_training_response for %s", mss::c_str(i_target)); + + // Displays the training response + FAPI_TRY(mss::exp::train::display_user_2d_eye_info(i_target, o_train_response)); + +fapi_try_exit: + return fapi2::current_err; +} + /// /// @brief host_fw_command_struct structure setup /// @param[in] i_target the OCMB being acted upon /// @param[in] i_cmd_data_crc the command data CRC /// @param[in] i_cmd_length the length of the command present in the data buffer (if any) +/// @param[in] i_phy_init_mode PHY init mode /// @param[out] o_cmd the command parameters to set /// @return FAPI2_RC_SUCCESS iff okay /// fapi2::ReturnCode setup_cmd_params( const fapi2::Target& i_target, const uint32_t i_cmd_data_crc, - const uint8_t i_cmd_length, + const uint32_t i_cmd_length, + const uint8_t i_phy_init_mode, host_fw_command_struct& o_cmd); /// diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C index fa39f9e5c..f7fbad41a 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C @@ -35,15 +35,11 @@ #include #include -#include -#include #include #include #include -#include #include #include -#include namespace mss { @@ -75,10 +71,10 @@ void display_lane_results(const fapi2::Target& i_t constexpr uint16_t CLEAN = 0; - // If we passed, display the information as only as debug - we don't want to clutter the screen with too much information + // If we passed, display the information as only as MFG - we don't want to clutter the screen with too much information if(CLEAN == i_data) { - FAPI_DBG("%s lane: %u PASSING R0:%u R1:%u R2:%u R3:%u", + FAPI_MFG("%s lane: %u PASSING R0:%u R1:%u R2:%u R3:%u", mss::c_str(i_target), i_lane, l_rank0, l_rank1, l_rank2, l_rank3); } @@ -93,211 +89,128 @@ void display_lane_results(const fapi2::Target& i_t } /// -/// @brief Displays lane failure information after training -/// @param[in] i_target the OCMB target -/// @param[in] i_training_info the training information to display +/// @brief Display train_2d_read_eye_msdg_t response struct /// -void display_lane_info(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info) -{ - for(uint8_t l_lane = 0; l_lane < exp_struct_sizes::TRAINING_RESPONSE_NUM_LANES; ++l_lane) - { - display_lane_results( i_target, l_lane, i_training_info.err_resp.Failure_Lane[l_lane]); - } -} - -/// -/// @brief Displays MR information -/// @param[in] i_target the OCMB target -/// @param[in] i_training_info the training information to display +/// @param[in] i_target OCMB target +/// @param[in] i_training_info training info struct /// -fapi2::ReturnCode display_mrs_info(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info) +void display_train_2d_read_eye(const fapi2::Target& i_target, + const user_2d_eye_response_1_msdg_t& i_training_info) { - // Loop through all DIMM's - for (const auto& l_dimm : mss::find_targets(i_target)) - { - // Rank info object for - std::vector> l_rank_info_vect; - uint8_t l_dram_width = 0; - FAPI_TRY(mss::rank::ranks_on_dimm<>(l_dimm, l_rank_info_vect)); - FAPI_TRY(mss::attr::get_dram_width(l_dimm, l_dram_width)); + FAPI_MFG("%s %s (EYE MIN/MAX):", mss::c_str(i_target), "VrefDAC0"); - // Loops through all of the ranks - for (const auto& l_rank_info : l_rank_info_vect) + for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank) + { + for (uint8_t l_dbyte = 0; l_dbyte < DBYTE_N_SIZE; ++l_dbyte) { - const uint8_t l_phy_rank = l_rank_info.get_phy_rank(); - // MR0->5 are easy, just display the value - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 0, i_training_info.mrs_resp.MR0); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 1, i_training_info.mrs_resp.MR1[l_phy_rank]); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 2, i_training_info.mrs_resp.MR2[l_phy_rank]); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 3, i_training_info.mrs_resp.MR3); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 4, i_training_info.mrs_resp.MR4); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 5, i_training_info.mrs_resp.MR5[l_phy_rank]); - - // The number of the DRAM's and the position to access each DRAM changes based upon x4 vs x8 - const auto l_num_dram = l_dram_width == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ? - mss::exp::generic_consts::EXP_NUM_DRAM_X4 : - mss::exp::generic_consts::EXP_NUM_DRAM_X8; - // The correction factor is used to determine the correct DRAM position, as x8 DRAM's take up two entries - const auto l_correction_factor = l_dram_width == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ? - 1 : 2; - - for(uint64_t l_dram = 0; l_dram < l_num_dram; ++l_dram) + for (uint8_t l_bit = 0; l_bit < BIT_N_SIZE; ++l_bit) { - const auto l_dram_pos = l_correction_factor * l_dram; - FAPI_DBG("%s rank%u MR6 dram%u 0x%04x", mss::c_str(i_target), l_phy_rank, l_dram, - i_training_info.mrs_resp.MR6[l_phy_rank][l_dram_pos]); + for (uint8_t l_eye_index = 0; l_eye_index < EYE_MIN_MAX_SIZE; ++l_eye_index) + { + const auto l_eye_min = i_training_info.read_2d_eye_resp.VrefDAC0[l_rank][l_dbyte][l_bit].eye_min[l_eye_index]; + const auto l_eye_max = i_training_info.read_2d_eye_resp.VrefDAC0[l_rank][l_dbyte][l_bit].eye_max[l_eye_index]; + + FAPI_MFG("%s %s RANK %u, DBYTE %u BIT %u EYE INDEX %u -- MIN: %u MAX: %u", + mss::c_str(i_target), "VrefDAC0", l_rank, l_dbyte, l_bit, l_eye_index, l_eye_min, l_eye_max); + } } } } - return fapi2::FAPI2_RC_SUCCESS; -fapi_try_exit: - return fapi2::current_err; -} + FAPI_MFG("%s %s_Center:", mss::c_str(i_target), "VrefDAC0"); -/// -/// @brief Displays all RCW information -/// @param[in] i_target the OCMB target -/// @param[in] i_training_info the training information to display -/// -void display_rcw_info(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info) -{ - constexpr uint64_t FUNC_SPACE0 = 0; - constexpr uint64_t FUNC_SPACE1 = 1; - - // Only display the DIMM's that exist - const auto& l_dimms = mss::find_targets(i_target); - - // Display DIMM0 - if(l_dimms.size() >= 1) + for (uint8_t l_dbyte = 0; l_dbyte < DBYTE_N_SIZE; ++l_dbyte) { - // Display all of function space 0 - // Display all 4-bit numbers - for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw) - { - display_rcw_4bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]); - } - - // Display all 8-bit numbers - for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw) + for (uint8_t l_bit = 0; l_bit < BIT_N_SIZE; ++l_bit) { - display_rcw_8bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]); + const auto l_vref_dac0_center = i_training_info.read_2d_eye_resp.VrefDAC0_Center[l_dbyte][l_bit]; + FAPI_MFG("%s %s DBYTE %u, BIT %u: %u", mss::c_str(i_target), "VrefDAC0_Center", l_dbyte, l_bit, l_vref_dac0_center); } + } - // Display all of function space 1 - // Display all 4-bit numbers - for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw) - { - display_rcw_4bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]); - } + FAPI_MFG("%s %s_Center:", mss::c_str(i_target), "RxClkDly"); - // Display all 8-bit numbers - for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw) + for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank) + { + for (uint8_t l_nibble = 0; l_nibble < NIBBLE_N_SIZE; ++l_nibble) { - display_rcw_8bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]); + const auto l_rxclkdly_center = i_training_info.read_2d_eye_resp.RxClkDly_Center[l_rank][l_nibble]; + FAPI_MFG("%s %s RANK %u, NIBBLE %u: %u", mss::c_str(i_target), "RxClkDly_Center", l_rank, l_nibble, l_rxclkdly_center); } } +} + +/// +/// @brief Display train_2d_write_eye_msdg_t response struct +/// +/// @param[in] i_target OCMB target +/// @param[in] i_training_info training info struct +/// +void display_train_2d_write_eye(const fapi2::Target& i_target, + const user_2d_eye_response_2_msdg_t& i_training_info) +{ + FAPI_MFG("%s %s (EYE MIN/MAX):", mss::c_str(i_target), "VrefDQ"); - // Display DIMM1 - if(l_dimms.size() == 2) + for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank) { - // Display all of function space 0 - // Display all 4-bit numbers - for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw) + for (uint8_t l_dbyte = 0; l_dbyte < DBYTE_N_SIZE; ++l_dbyte) { - display_rcw_4bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]); + for (uint8_t l_bit = 0; l_bit < BIT_N_SIZE; ++l_bit) + { + for (uint8_t l_eye_index = 0; l_eye_index < EYE_MIN_MAX_SIZE; ++l_eye_index) + { + const auto l_eye_min = i_training_info.write_2d_eye_resp.VrefDQ[l_rank][l_dbyte][l_bit].eye_min[l_eye_index]; + const auto l_eye_max = i_training_info.write_2d_eye_resp.VrefDQ[l_rank][l_dbyte][l_bit].eye_max[l_eye_index]; + + FAPI_MFG("%s %s RANK %u, DBYTE %u BIT %u EYE INDEX %u -- MIN: %u MAX: %u", + mss::c_str(i_target), "VrefDQ", l_rank, l_dbyte, l_bit, l_eye_index, l_eye_min, l_eye_max); + } + } } + } - // Display all 8-bit numbers - for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw) - { - display_rcw_8bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]); - } + FAPI_MFG("%s %s_Center:", mss::c_str(i_target), "VrefDQ"); - // Display all of function space 1 - // Display all 4-bit numbers - for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw) + for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank) + { + for (uint8_t l_nibble = 0; l_nibble < NIBBLE_N_SIZE; ++l_nibble) { - display_rcw_4bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]); + const auto l_vrefdq_center = i_training_info.write_2d_eye_resp.VrefDQ_Center[l_rank][l_nibble]; + FAPI_MFG("%s %s RANK %u, NIBBLE %u: %u", mss::c_str(i_target), "VrefDQ_Center", l_rank, l_nibble, l_vrefdq_center); } + } - // Display all 8-bit numbers - for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw) + FAPI_MFG("%s %s_Center:", mss::c_str(i_target), "TxDqDly"); + + for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank) + { + for (uint8_t l_dbyte = 0; l_dbyte < DBYTE_N_SIZE; ++l_dbyte) { - display_rcw_8bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]); + for (uint8_t l_bit = 0; l_bit < BIT_N_SIZE; ++l_bit) + { + const auto l_txdqdly_center = i_training_info.write_2d_eye_resp.TxDqDly_Center[l_rank][l_dbyte][l_bit]; + FAPI_MFG("%s %s RANK %u, DBYTE %u BIT %u: %u", mss::c_str(i_target), "TxDqDly_Center", l_rank, l_dbyte, l_bit, + l_txdqdly_center); + } } } } /// -/// @brief Displays command to command response timing +/// @brief Displays all training information /// @param[in] i_target the OCMB target /// @param[in] i_training_info the training information to display -/// @return returns FAPI2_RC_SUCCESS iff the procedure executes successfully +/// @return fapi2::FAPI2_RC_SUCCESS iff success /// -fapi2::ReturnCode display_response_timing(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info) +template <> +fapi2::ReturnCode display_user_2d_eye_info( + const fapi2::Target& i_target, + const user_2d_eye_response_1_msdg_t& i_training_info) { - uint8_t l_num_rank_per_ocmb = 0; - - // Loop through all DIMM's - for(const auto& l_dimm : mss::find_targets(i_target)) - { - // Gets the number of DIMM's and x4 vs x8 DRAM - // TK update ranks to use rank API - uint8_t l_num_master_ranks = 0; - - FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(l_dimm, l_num_master_ranks)); - l_num_rank_per_ocmb += l_num_master_ranks; - } - - // DFIMRL_DDRCLK_trained training result - FAPI_INF("%s DFIMRL_DDRCLK_trained: %u", mss::c_str(i_target), i_training_info.tm_resp.DFIMRL_DDRCLK_trained); - - // RD to RD - FAPI_DBG("%s RD-to-RD : 0 1 2 3", mss::c_str(i_target)); - - for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n) - { - FAPI_DBG("%s RD-to-RD rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_rank_n, - i_training_info.tm_resp.CDD_RR[l_rank_n][0], i_training_info.tm_resp.CDD_RR[l_rank_n][1], - i_training_info.tm_resp.CDD_RR[l_rank_n][2], i_training_info.tm_resp.CDD_RR[l_rank_n][3]); - } - - // WR to WR - FAPI_DBG("%s WR-to-WR : 0 1 2 3", mss::c_str(i_target)); - - for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n) - { - FAPI_DBG("%s WR-to-WR rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_rank_n, - i_training_info.tm_resp.CDD_WW[l_rank_n][0], i_training_info.tm_resp.CDD_WW[l_rank_n][1], - i_training_info.tm_resp.CDD_WW[l_rank_n][2], i_training_info.tm_resp.CDD_WW[l_rank_n][3]); - } - - // WR to RD - FAPI_DBG("%s WR-to-RD : 0 1 2 3", mss::c_str(i_target)); - - for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n) - { - FAPI_DBG("%s WR-to-RD rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_rank_n, - i_training_info.tm_resp.CDD_WR[l_rank_n][0], i_training_info.tm_resp.CDD_WR[l_rank_n][1], - i_training_info.tm_resp.CDD_WR[l_rank_n][2], i_training_info.tm_resp.CDD_WR[l_rank_n][3]); - } - - // RD to WR - FAPI_DBG("%s RD-to-WR : 0 1 2 3", mss::c_str(i_target)); - - for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n) - { - FAPI_DBG("%s RD-to-WR rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_rank_n, - i_training_info.tm_resp.CDD_RW[l_rank_n][0], i_training_info.tm_resp.CDD_RW[l_rank_n][1], - i_training_info.tm_resp.CDD_RW[l_rank_n][2], i_training_info.tm_resp.CDD_RW[l_rank_n][3]); - } + FAPI_INF("%s displaying user 2d eye response 1 data version %u", mss::c_str(i_target), i_training_info.version_number) + display_train_2d_read_eye(i_target, i_training_info); + FAPI_TRY(display_normal_info(i_target, i_training_info)); - return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: return fapi2::current_err; } @@ -306,15 +219,16 @@ fapi_try_exit: /// @brief Displays all training information /// @param[in] i_target the OCMB target /// @param[in] i_training_info the training information to display +/// @return fapi2::FAPI2_RC_SUCCESS iff success /// -fapi2::ReturnCode display_info(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info) +template <> +fapi2::ReturnCode display_user_2d_eye_info( + const fapi2::Target& i_target, + const user_2d_eye_response_2_msdg_t& i_training_info) { - FAPI_INF("%s displaying user response data version %u", mss::c_str(i_target), i_training_info.version_number) - display_rcw_info(i_target, i_training_info); - FAPI_TRY(display_mrs_info(i_target, i_training_info)); - display_lane_info(i_target, i_training_info); - FAPI_TRY(display_response_timing(i_target, i_training_info)); + FAPI_INF("%s displaying user 2d eye response 2 data version %u", mss::c_str(i_target), i_training_info.version_number) + display_train_2d_write_eye(i_target, i_training_info); + FAPI_TRY(display_normal_info(i_target, i_training_info)); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H index a71bffce6..5905e1d4b 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H @@ -37,10 +37,16 @@ #define _EXP_TRAIN_DISPLAY_H_ #include +#include +#include +#include #include #include #include +#include #include +#include + namespace mss { @@ -58,24 +64,6 @@ void display_lane_results(const fapi2::Target& i_t const uint64_t i_lane, const uint16_t i_data); - -/// -/// @brief Displays lane failure information after training -/// @param[in] i_target the OCMB target -/// @param[in] i_training_info the training information to display -/// -void display_lane_info(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info); - -/// -/// @brief Displays MRS information -/// @param[in] i_target the OCMB target -/// @param[in] i_training_info the training information to display -/// @return returns FAPI2_RC_SUCCESS iff the procedure executes successfully -/// -fapi2::ReturnCode display_mrs_info(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info); - /// /// @brief Displays RCW information for a single 8-bit RCW /// @param[in] i_target the OCMB target @@ -91,7 +79,7 @@ inline void display_rcw_8bit(const fapi2::Target& const uint8_t i_data) { const uint64_t l_rcw_print_number = i_rcw_number - exp_struct_sizes::RCW_8BIT_CUTOFF; - FAPI_DBG("%s DIMM%u F%uRC%xX: 0x%02x", mss::c_str(i_target), i_dimm, i_func_space, l_rcw_print_number, i_data); + FAPI_MFG("%s DIMM%u F%uRC%xX: 0x%02x", mss::c_str(i_target), i_dimm, i_func_space, l_rcw_print_number, i_data); } /// @@ -108,34 +96,305 @@ inline void display_rcw_4bit(const fapi2::Target& const uint64_t i_rcw_number, const uint8_t i_data) { - FAPI_DBG("%s DIMM%u F%uRC%02x: 0x%02x", mss::c_str(i_target), i_dimm, i_func_space, i_rcw_number, i_data); + FAPI_MFG("%s DIMM%u F%uRC%02x: 0x%02x", mss::c_str(i_target), i_dimm, i_func_space, i_rcw_number, i_data); +} + + +/// +/// @brief Displays lane failure information after training +/// @tparam T response struct +/// @param[in] i_target the OCMB target +/// @param[in] i_training_info the training information to display +/// +template +void display_lane_info(const fapi2::Target& i_target, + const T& i_training_info) +{ + for(uint8_t l_lane = 0; l_lane < exp_struct_sizes::TRAINING_RESPONSE_NUM_LANES; ++l_lane) + { + display_lane_results( i_target, l_lane, i_training_info.err_resp.Failure_Lane[l_lane]); + } +} + +/// +/// @brief Displays MR information +/// @tparam T response struct +/// @param[in] i_target the OCMB target +/// @param[in] i_training_info the training information to display +/// +template +fapi2::ReturnCode display_mrs_info(const fapi2::Target& i_target, + const T& i_training_info) +{ + // Loop through all ports + for (const auto& l_port : mss::find_targets(i_target)) + { + // Rank info object for + std::vector> l_rank_info_vect; + uint8_t l_dram_width[mss::exp::sizes::MAX_DIMM_PER_PORT] = {}; + FAPI_TRY(mss::rank::ranks_on_port<>(l_port, l_rank_info_vect)); + FAPI_TRY(mss::attr::get_dram_width(l_port, l_dram_width)); + + // Loops through all of the ranks + for (const auto& l_rank_info : l_rank_info_vect) + { + const uint8_t l_phy_rank = l_rank_info.get_phy_rank(); + const uint8_t l_port_rank = l_rank_info.get_port_rank(); + const uint8_t l_dram_width_for_dimm = l_dram_width[mss::index(l_rank_info.get_dimm_target())]; + // MR0->5 are easy, just display the value + FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 0, i_training_info.mrs_resp.MR0); + FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 1, i_training_info.mrs_resp.MR1[l_phy_rank]); + FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 2, i_training_info.mrs_resp.MR2[l_phy_rank]); + FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 3, i_training_info.mrs_resp.MR3); + FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 4, i_training_info.mrs_resp.MR4); + FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 5, i_training_info.mrs_resp.MR5[l_phy_rank]); + + // The number of the DRAM's and the position to access each DRAM changes based upon x4 vs x8 + const auto l_num_dram = l_dram_width_for_dimm == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ? + mss::exp::generic_consts::EXP_NUM_DRAM_X4 : mss::exp::generic_consts::EXP_NUM_DRAM_X8; + // The correction factor is used to determine the correct DRAM position, as x8 DRAM's take up two entries + const auto l_correction_factor = l_dram_width_for_dimm == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ? 1 : 2; + + for (uint64_t l_dram = 0; l_dram < l_num_dram; ++l_dram) + { + const auto l_dram_pos = l_correction_factor * l_dram; + FAPI_MFG("%s rank%u MR6 dram%u 0x%04x", mss::c_str(i_target), l_port_rank, l_dram, + i_training_info.mrs_resp.MR6[l_phy_rank][l_dram_pos]); + } + } + } + + return fapi2::FAPI2_RC_SUCCESS; +fapi_try_exit: + return fapi2::current_err; } /// /// @brief Displays all RCW information +/// @tparam T response struct /// @param[in] i_target the OCMB target /// @param[in] i_training_info the training information to display /// +template void display_rcw_info(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info); + const T& i_training_info) +{ + constexpr uint64_t FUNC_SPACE0 = 0; + constexpr uint64_t FUNC_SPACE1 = 1; + + // Only display the DIMM's that exist + const auto& l_dimms = mss::find_targets(i_target); + + // Display DIMM0 + if(l_dimms.size() >= 1) + { + // Display all of function space 0 + // Display all 4-bit numbers + for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw) + { + display_rcw_4bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]); + } + + // Display all 8-bit numbers + for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw) + { + display_rcw_8bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]); + } + + // Display all of function space 1 + // Display all 4-bit numbers + for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw) + { + display_rcw_4bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]); + } + + // Display all 8-bit numbers + for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw) + { + display_rcw_8bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]); + } + } + + // Display DIMM1 + if(l_dimms.size() == 2) + { + // Display all of function space 0 + // Display all 4-bit numbers + for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw) + { + display_rcw_4bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]); + } + + // Display all 8-bit numbers + for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw) + { + display_rcw_8bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]); + } + + // Display all of function space 1 + // Display all 4-bit numbers + for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw) + { + display_rcw_4bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]); + } + + // Display all 8-bit numbers + for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw) + { + display_rcw_8bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]); + } + } +} /// /// @brief Displays command to command response timing +/// @tparam T response struct /// @param[in] i_target the OCMB target /// @param[in] i_training_info the training information to display /// @return returns FAPI2_RC_SUCCESS iff the procedure executes successfully /// -fapi2::ReturnCode display_response_timing(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info); +template +inline fapi2::ReturnCode display_response_timing(const fapi2::Target& i_target, + const T& i_training_info) +{ + // Loop through all ports + for (const auto& l_port : mss::find_targets(i_target)) + { + // Rank info object for + std::vector> l_rank_info_vect; + FAPI_TRY(mss::rank::ranks_on_port<>(l_port, l_rank_info_vect)); + + // DFIMRL_DDRCLK_trained training result + FAPI_INF("%s DFIMRL_DDRCLK_trained: %u", mss::c_str(i_target), i_training_info.tm_resp.DFIMRL_DDRCLK_trained); + + // RD to RD + FAPI_MFG("%s RD-to-RD : 0 1 2 3", mss::c_str(i_target)); + + for(const auto& l_rank : l_rank_info_vect) + { + const auto l_phy_rank = l_rank.get_phy_rank(); + const auto l_port_rank = l_rank.get_port_rank(); + FAPI_MFG("%s RD-to-RD rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_port_rank, + i_training_info.tm_resp.CDD_RR[l_phy_rank][0], i_training_info.tm_resp.CDD_RR[l_phy_rank][1], + i_training_info.tm_resp.CDD_RR[l_phy_rank][2], i_training_info.tm_resp.CDD_RR[l_phy_rank][3]); + } + + // WR to WR + FAPI_MFG("%s WR-to-WR : 0 1 2 3", mss::c_str(i_target)); + + for(const auto& l_rank : l_rank_info_vect) + { + const auto l_phy_rank = l_rank.get_phy_rank(); + const auto l_port_rank = l_rank.get_port_rank(); + FAPI_MFG("%s WR-to-WR rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_port_rank, + i_training_info.tm_resp.CDD_WW[l_phy_rank][0], i_training_info.tm_resp.CDD_WW[l_phy_rank][1], + i_training_info.tm_resp.CDD_WW[l_phy_rank][2], i_training_info.tm_resp.CDD_WW[l_phy_rank][3]); + } + + // WR to RD + FAPI_MFG("%s WR-to-RD : 0 1 2 3", mss::c_str(i_target)); + + for(const auto& l_rank : l_rank_info_vect) + { + const auto l_phy_rank = l_rank.get_phy_rank(); + const auto l_port_rank = l_rank.get_port_rank(); + FAPI_MFG("%s WR-to-RD rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_port_rank, + i_training_info.tm_resp.CDD_WR[l_phy_rank][0], i_training_info.tm_resp.CDD_WR[l_phy_rank][1], + i_training_info.tm_resp.CDD_WR[l_phy_rank][2], i_training_info.tm_resp.CDD_WR[l_phy_rank][3]); + } + + // RD to WR + FAPI_MFG("%s RD-to-WR : 0 1 2 3", mss::c_str(i_target)); + + for(const auto& l_rank : l_rank_info_vect) + { + const auto l_phy_rank = l_rank.get_phy_rank(); + const auto l_port_rank = l_rank.get_port_rank(); + FAPI_MFG("%s RD-to-WR rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_port_rank, + i_training_info.tm_resp.CDD_RW[l_phy_rank][0], i_training_info.tm_resp.CDD_RW[l_phy_rank][1], + i_training_info.tm_resp.CDD_RW[l_phy_rank][2], i_training_info.tm_resp.CDD_RW[l_phy_rank][3]); + } + } + + return fapi2::FAPI2_RC_SUCCESS; +fapi_try_exit: + return fapi2::current_err; +} + /// -/// @brief Displays all training information +/// @brief Display train_2d_read_eye_msdg_t response struct +/// +/// @param[in] i_target OCMB target +/// @param[in] i_training_info training info struct +/// +void display_train_2d_read_eye(const fapi2::Target& i_target, + const user_2d_eye_response_1_msdg_t& i_training_info); + +/// +/// @brief Display train_2d_write_eye_msdg_t response struct +/// +/// @param[in] i_target OCMB target +/// @param[in] i_training_info training info struct +/// +void display_train_2d_write_eye(const fapi2::Target& i_target, + const user_2d_eye_response_2_msdg_t& i_training_info); + +/// +/// @brief Displays all training information common to all response structs +/// @tparam T response struct /// @param[in] i_target the OCMB target /// @param[in] i_training_info the training information to display /// @return returns FAPI2_RC_SUCCESS iff the procedure executes successfully /// -fapi2::ReturnCode display_info(const fapi2::Target& i_target, - const user_response_msdg_t& i_training_info); +template +inline fapi2::ReturnCode display_normal_info( + const fapi2::Target& i_target, + const T& i_training_info) +{ + // Target trace & FAPI_INF moved to the caller(s) such that we can call this from the eye capture functions + display_rcw_info(i_target, i_training_info); + FAPI_TRY(display_mrs_info(i_target, i_training_info)); + display_lane_info(i_target, i_training_info); + FAPI_TRY(display_response_timing(i_target, i_training_info)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Displays all training information +/// @tparam T response struct +/// @param[in] i_target the OCMB target +/// @param[in] i_training_info the training information to display +/// @return fapi2::FAPI2_RC_SUCCESS iff success +/// +template +fapi2::ReturnCode display_user_2d_eye_info( + const fapi2::Target& i_target, + const T& i_training_info); + +/// +/// @brief Displays all training information for eye response 1 +/// @param[in] i_target the OCMB target +/// @param[in] i_training_info the training information to display +/// @return fapi2::FAPI2_RC_SUCCESS iff success +/// +template <> +fapi2::ReturnCode display_user_2d_eye_info( + const fapi2::Target& i_target, + const user_2d_eye_response_1_msdg_t& i_training_info); + +/// +/// @brief Displays all training information for eye response 2 +/// @param[in] i_target the OCMB target +/// @param[in] i_training_info the training information to display +/// @return fapi2::FAPI2_RC_SUCCESS iff success +/// +template <> +fapi2::ReturnCode display_user_2d_eye_info( + const fapi2::Target& i_target, + const user_2d_eye_response_2_msdg_t& i_training_info); } // ns train } // ns exp diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C index 14b6f5e36..8ca3b5f87 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C @@ -46,17 +46,40 @@ namespace mss { /// -/// @brief A generic bad bits setter -/// @tparam MC type memory controller type +/// @brief Bad bit getter - Explorer specialization /// @param[in] i_target the fapi2 target oon which training was conducted -/// @param[in] i_array the bad bits to set +/// @param[out] o_array the bad bits +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code +/// +template <> +fapi2::ReturnCode get_bad_dq_bitmap(const fapi2::Target& i_target, + uint8_t (&o_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]) +{ + return mss::attr::get_bad_dq_bitmap(i_target, o_array); +} + +/// +/// @brief Bad bit setter - Explorer specialization +/// @param[in] i_target the fapi2 target oon which training was conducted +/// @param[in] i_array the bad bits to append /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if bad bits can be repaired /// template <> fapi2::ReturnCode set_bad_dq_bitmap(const fapi2::Target& i_target, uint8_t (&i_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]) { - return mss::attr::set_bad_dq_bitmap(i_target, i_array); + uint8_t l_current_data[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT] = {}; + + // Get existing bad bits data + FAPI_TRY(mss::attr::get_bad_dq_bitmap(i_target, l_current_data)); + + // Now, or the new bits and any existing bits together + mss::combine_bad_bits(l_current_data, i_array); + + FAPI_TRY(mss::attr::set_bad_dq_bitmap(i_target, i_array)); + +fapi_try_exit: + return fapi2::current_err; } namespace check @@ -94,68 +117,17 @@ namespace exp /// @param[out] o_resp the processed training response class /// @return FAPI2_RC_SUCCESS if ok /// -fapi2::ReturnCode read_training_response(const fapi2::Target& i_target, +fapi2::ReturnCode read_normal_training_response(const fapi2::Target& i_target, const std::vector& i_data, user_response_msdg& o_resp) { - - // True if we pass // We assert at the end to avoid LOTS of fapi asserts uint32_t l_idx = 0; - uint32_t l_version_number = 0; bool l_pass = readLE(i_data, l_idx, l_version_number); o_resp.version_number = l_version_number; - uint16_t l_DFIMRL_DDRCLK_trained = 0; - - // Reads in the timing portion of the training response - l_pass &= readLE(i_data, l_idx, l_DFIMRL_DDRCLK_trained); - l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_RR[0][0]); - l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_WW[0][0]); - l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_RW[0][0]); - l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_WR[0][0]); - - // Write to user_response_msdg - o_resp.tm_resp.DFIMRL_DDRCLK_trained = l_DFIMRL_DDRCLK_trained; - - // Error response - l_pass &= readLEArray(i_data, 80, l_idx, o_resp.err_resp.Failure_Lane); - - uint16_t l_MR0 = 0; - uint16_t l_MR3 = 0; - uint16_t l_MR4 = 0; - - // MRS response - l_pass &= readLE(i_data, l_idx, l_MR0); - l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, o_resp.mrs_resp.MR1); - l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, o_resp.mrs_resp.MR2); - l_pass &= readLE(i_data, l_idx, l_MR3); - l_pass &= readLE(i_data, l_idx, l_MR4); - l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, o_resp.mrs_resp.MR5); - l_pass &= readLEArray(i_data, TRAINING_RESPONSE_MR6_SIZE, l_idx, &o_resp.mrs_resp.MR6[0][0]); - - o_resp.mrs_resp.MR0 = l_MR0; - o_resp.mrs_resp.MR3 = l_MR3; - o_resp.mrs_resp.MR4 = l_MR4; - - // Register Control Word (RCW) response - l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F0RC_D0); - l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F1RC_D0); - l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F0RC_D1); - l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F1RC_D1); - - // Check if we have errors - FAPI_ASSERT( l_pass, - fapi2::EXP_INBAND_LE_DATA_RANGE() - .set_TARGET(i_target) - .set_FUNCTION(mss::exp::READ_TRAINING_RESPONSE_STRUCT) - .set_DATA_SIZE(i_data.size()) - .set_MAX_INDEX(sizeof(user_response_msdg)), - "%s Failed to convert from data to host_fw_response_struct data size %u expected size %u", - mss::c_str(i_target), i_data.size(), sizeof(user_response_msdg)); - - return fapi2::FAPI2_RC_SUCCESS; + FAPI_TRY(read_tm_err_mrs_rc_response(i_target, i_data, l_idx, l_pass, o_resp)); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H index 8cd501d67..dc599616c 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -51,20 +52,204 @@ namespace exp { /// -/// @brief Reads the training response structure -/// @param[in] i_target the target associated with the response data -/// @param[in] i_data the response data to read -/// @param[out] o_resp the processed training response class -/// @return FAPI2_RC_SUCCESS if ok +/// @brief Read eye capture response data from explorer data buffer +/// +/// @tparam T Response struct type +/// @param[in] i_target OCMB target +/// @param[in] i_data Raw data bytes +/// @param[in,out] io_current_idx Current parsing index +/// @param[in,out] io_pass any errors occurred during reading/endian-swapping +/// @param[in,out] io_resp response struct +/// @note this function expects io_current_index to be set correctly to the start of eye capture data +/// +template +void read_eye_capture_response(const fapi2::Target& i_target, + const std::vector& i_data, + uint32_t& io_current_idx, + bool& io_pass, + T& io_resp); + +/// +/// @brief Read eye capture response data from explorer data buffer (eye capture step 1) +/// +/// @param[in] i_target OCMB target +/// @param[in] i_data Raw data bytes +/// @param[in,out] io_current_idx Current parsing index +/// @param[in,out] io_pass any errors occurred during reading/endian-swapping +/// @param[in,out] io_resp train_2d_read_eye_msdg +/// @note this function expects io_current_index to be set correctly to the start of eye capture data /// -fapi2::ReturnCode read_training_response(const fapi2::Target& i_target, +template<> +inline void read_eye_capture_response(const fapi2::Target& + i_target, const std::vector& i_data, - user_response_msdg& o_resp); + uint32_t& io_current_idx, + bool& io_pass, + user_2d_eye_response_1_msdg& io_resp) +{ + // Eye capture step 1 struct + uint32_t l_idx = io_current_idx; + bool l_pass = io_pass; + + // VrefDAC0: 3D array of 2 1D arrays + for (uint8_t l_num_ranks = 0; l_num_ranks < TRAINING_RESPONSE_NUM_RANKS; ++l_num_ranks) + { + for (uint8_t l_dbyte_n_size = 0; l_dbyte_n_size < DBYTE_N_SIZE; ++ l_dbyte_n_size) + { + for (uint8_t l_bit_n_sze = 0; l_bit_n_sze < BIT_N_SIZE; ++ l_bit_n_sze) + { + l_pass &= readLEArray(i_data, EYE_MIN_MAX_SIZE, l_idx, + &io_resp.read_2d_eye_resp.VrefDAC0[l_num_ranks][l_dbyte_n_size][l_bit_n_sze].eye_min[0]); + l_pass &= readLEArray(i_data, EYE_MIN_MAX_SIZE, l_idx, + &io_resp.read_2d_eye_resp.VrefDAC0[l_num_ranks][l_dbyte_n_size][l_bit_n_sze].eye_max[0]); + } + } + } + + // 2D array VrefDAC0_Center [DBYTE_N_SIZE][BIT_N_SIZE] + l_pass &= readLEArray(i_data, (DBYTE_N_SIZE * BIT_N_SIZE), l_idx, + &io_resp.read_2d_eye_resp.VrefDAC0_Center[0][0]); + + // 2D array RxClkDly_Center [TRAINING_RESPONSE_NUM_RANKS][NIBBLE_N_SIZE] + l_pass &= readLEArray(i_data, (TRAINING_RESPONSE_NUM_RANKS * NIBBLE_N_SIZE), l_idx, + &io_resp.read_2d_eye_resp.RxClkDly_Center[0][0]); + + io_pass = l_pass; + io_current_idx = l_idx; +} + +/// +/// @brief Read eye capture response data from explorer data buffer (eye capture step 2) +/// +/// @param[in] i_target OCMB target +/// @param[in] i_data Raw data bytes +/// @param[in,out] io_current_idx Current parsing index +/// @param[in,out] io_pass any errors occurred during reading/endian-swapping +/// @param[in,out] io_resp user_2d_eye_response_2_msdg +/// @note this function expects io_current_index to be set correctly to the start of eye capture data +/// +template<> +inline void read_eye_capture_response(const fapi2::Target& + i_target, + const std::vector& i_data, + uint32_t& io_current_idx, + bool& io_pass, + user_2d_eye_response_2_msdg& io_resp) +{ + + // Eye capture step 1 struct + uint32_t l_idx = io_current_idx; + bool l_pass = io_pass; + + // VrefDQ: 3D array of 2 1D arrays + for (uint8_t l_num_ranks = 0; l_num_ranks < TRAINING_RESPONSE_NUM_RANKS; ++l_num_ranks) + { + for (uint8_t l_dbyte_n_size = 0; l_dbyte_n_size < DBYTE_N_SIZE; ++ l_dbyte_n_size) + { + for (uint8_t l_bit_n_sze = 0; l_bit_n_sze < BIT_N_SIZE; ++ l_bit_n_sze) + { + l_pass &= readLEArray(i_data, EYE_MIN_MAX_SIZE, l_idx, + &io_resp.write_2d_eye_resp.VrefDQ[l_num_ranks][l_dbyte_n_size][l_bit_n_sze].eye_min[0]); + l_pass &= readLEArray(i_data, EYE_MIN_MAX_SIZE, l_idx, + &io_resp.write_2d_eye_resp.VrefDQ[l_num_ranks][l_dbyte_n_size][l_bit_n_sze].eye_max[0]); + } + } + } + + // 2D array VrefDQ_Center [TRAINING_RESPONSE_NUM_RANKS][NIBBLE_N_SIZE] + l_pass &= readLEArray(i_data, (TRAINING_RESPONSE_NUM_RANKS * NIBBLE_N_SIZE), l_idx, + &io_resp.write_2d_eye_resp.VrefDQ_Center[0][0]); + + // 3D array TxDqDly_Center [TRAINING_RESPONSE_NUM_RANKS][DBYTE_N_SIZE][DBYTE_N_SIZE] + l_pass &= readLEArray(i_data, (TRAINING_RESPONSE_NUM_RANKS * DBYTE_N_SIZE * BIT_N_SIZE), l_idx, + &io_resp.write_2d_eye_resp.TxDqDly_Center[0][0][0]); + + io_pass = l_pass; + io_current_idx = l_idx; + + return; +} + +/// +/// @brief Read the common block of fields from the training response structs +/// +/// @tparam T training repsonse struct type +/// @param[in] i_target OCMB chip +/// @param[in] i_data response data +/// @param[in] i_current_idx last index left off +/// @param[in] i_pass response parsing success thus far +/// @param[in,out] io_resp response struct +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// +template +fapi2::ReturnCode read_tm_err_mrs_rc_response(const fapi2::Target& i_target, + const std::vector& i_data, + const uint32_t i_current_idx, + const bool i_pass, + T& io_resp) +{ + uint32_t l_idx = i_current_idx; + bool l_pass = i_pass; + + uint16_t l_DFIMRL_DDRCLK_trained = 0; + + // Reads in the timing portion of the training response + l_pass &= readLE(i_data, l_idx, l_DFIMRL_DDRCLK_trained); + l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &io_resp.tm_resp.CDD_RR[0][0]); + l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &io_resp.tm_resp.CDD_WW[0][0]); + l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &io_resp.tm_resp.CDD_RW[0][0]); + l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &io_resp.tm_resp.CDD_WR[0][0]); + + // Write to user_response_msdg + io_resp.tm_resp.DFIMRL_DDRCLK_trained = l_DFIMRL_DDRCLK_trained; + + // Error response + l_pass &= readLEArray(i_data, 80, l_idx, io_resp.err_resp.Failure_Lane); + + uint16_t l_MR0 = 0; + uint16_t l_MR3 = 0; + uint16_t l_MR4 = 0; + + // MRS response + l_pass &= readLE(i_data, l_idx, l_MR0); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, io_resp.mrs_resp.MR1); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, io_resp.mrs_resp.MR2); + l_pass &= readLE(i_data, l_idx, l_MR3); + l_pass &= readLE(i_data, l_idx, l_MR4); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, io_resp.mrs_resp.MR5); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_MR6_SIZE, l_idx, &io_resp.mrs_resp.MR6[0][0]); + + io_resp.mrs_resp.MR0 = l_MR0; + io_resp.mrs_resp.MR3 = l_MR3; + io_resp.mrs_resp.MR4 = l_MR4; + + // Register Control Word (RCW) response + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, io_resp.rc_resp.F0RC_D0); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, io_resp.rc_resp.F1RC_D0); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, io_resp.rc_resp.F0RC_D1); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, io_resp.rc_resp.F1RC_D1); + + // Check if we have errors + FAPI_ASSERT( l_pass, + fapi2::EXP_INBAND_LE_DATA_RANGE() + .set_TARGET(i_target) + .set_FUNCTION(mss::exp::READ_TRAINING_RESPONSE_STRUCT) + .set_DATA_SIZE(i_data.size()) + .set_MAX_INDEX(sizeof(T)), + "%s Failed to convert from data to host_fw_response_struct data size %u expected size %u", + mss::c_str(i_target), i_data.size(), sizeof(T)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} /// /// @brief Explorer's bad bit interface class -/// @brief Explorer's bad bit interface class +/// @tparam T user response struct type /// +template class bad_bit_interface { public: @@ -85,7 +270,7 @@ class bad_bit_interface /// @brief Constructor /// @param[in] i_response response data from training /// - bad_bit_interface(const user_response_msdg_t& i_response ) + bad_bit_interface(const T& i_response ) { // First, clear everything std::fill(&iv_bad_bits[0][0], &iv_bad_bits[0][0] + sizeof(iv_bad_bits), 0); @@ -171,6 +356,48 @@ class bad_bit_interface } }; + +/// +/// @brief Reads the training response structure +/// @param[in] i_target the target associated with the response data +/// @param[in] i_data the response data to read +/// @param[out] o_resp the processed training response class +/// @return FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode read_normal_training_response(const fapi2::Target& i_target, + const std::vector& i_data, + user_response_msdg& o_resp); + +/// +/// @brief Reads user 2d eye response 1 +/// @tparam T response struct +/// @param[in] i_target the target associated with the response data +/// @param[in] i_data the response data to read +/// @param[out] o_resp the processed training response class +/// @return FAPI2_RC_SUCCESS if ok +/// +template +inline fapi2::ReturnCode read_user_2d_eye_response(const fapi2::Target& i_target, + const std::vector& i_data, + T& o_resp) +{ + // First let's erase the struct + memset(&o_resp, 0, sizeof(T)); + // We assert at the end to avoid LOTS of fapi asserts + uint32_t l_idx = 0; + uint32_t l_version_number = 0; + bool l_pass = readLE(i_data, l_idx, l_version_number); + o_resp.version_number = l_version_number; + + read_eye_capture_response(i_target, i_data, l_idx, l_pass, o_resp); + + FAPI_TRY(read_tm_err_mrs_rc_response(i_target, i_data, l_idx, l_pass, o_resp)); + +fapi_try_exit: + return fapi2::current_err; +} + + } // ns exp } // ns mss diff --git a/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_attributes.xml b/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_attributes.xml index 9e655ee15..cdd22a559 100644 --- a/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_attributes.xml +++ b/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_attributes.xml @@ -410,4 +410,20 @@ exp_atxdly_b + + ATTR_MSS_OCMB_PHY_INIT_MODE + TARGET_TYPE_OCMB_CHIP + + Mode for PHY initialization. + + uint8 + + + NORMAL = 0, + WITH_EYE_CAPTURE = 1 + + + exp_phy_init_mode + + diff --git a/src/import/chips/ocmb/explorer/procedures/xml/error_info/mss_exp_errors.xml b/src/import/chips/ocmb/explorer/procedures/xml/error_info/mss_exp_errors.xml index ae2cf7f56..9172a516f 100644 --- a/src/import/chips/ocmb/explorer/procedures/xml/error_info/mss_exp_errors.xml +++ b/src/import/chips/ocmb/explorer/procedures/xml/error_info/mss_exp_errors.xml @@ -700,4 +700,17 @@ + + RC_MSS_EXP_UNKNOWN_PHY_INIT_MODE + + The PHY init mode attribute value was unknown. Valid: 0 (NORMAL), 1 (WITH_EYE_CAPTURE) + + TARGET + VALUE + + CODE + MEDIUM + + + diff --git a/src/import/generic/memory/lib/utils/mss_bad_bits.H b/src/import/generic/memory/lib/utils/mss_bad_bits.H index e6d2cdfa5..b39d84859 100644 --- a/src/import/generic/memory/lib/utils/mss_bad_bits.H +++ b/src/import/generic/memory/lib/utils/mss_bad_bits.H @@ -45,6 +45,17 @@ namespace mss { +/// +/// @brief A generic bad bits getter +/// @tparam MC type memory controller type +/// @param[in] i_target the fapi2 target oon which training was conducted +/// @param[out] o_array the bad bits array +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code +/// +template +fapi2::ReturnCode get_bad_dq_bitmap(const fapi2::Target& i_target, + uint8_t (&o_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]); + /// /// @brief A generic bad bits setter /// @tparam MC type memory controller type @@ -56,6 +67,23 @@ template fapi2::ReturnCode set_bad_dq_bitmap(const fapi2::Target& i_target, uint8_t (&i_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]); +/// +/// @brief combine the two bad bits arrays into the io_bad_bits array +/// @param[in] i_new_bad_bits bad bits to append +/// @param[in,out] io_bad_bits will contain the bitwise or of the original io_bad_bits and i_new_bad_bits +/// +inline void combine_bad_bits(const uint8_t (&i_new_bad_bits)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT], + uint8_t (&io_bad_bits)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]) +{ + for (uint8_t l_rank = 0; l_rank < BAD_BITS_RANKS; ++ l_rank) + { + for (uint8_t l_bad_dq_byte = 0; l_bad_dq_byte < BAD_DQ_BYTE_COUNT; ++l_bad_dq_byte) + { + io_bad_bits[l_rank][l_bad_dq_byte] |= i_new_bad_bits[l_rank][l_bad_dq_byte]; + } + } +} + /// /// @brief Records bad bits into the bad bits attribute /// @tparam MC MC type on which training was run -- cgit v1.2.1