From bc2f2095a281a21ab45b829e67c9f1788d5f9984 Mon Sep 17 00:00:00 2001 From: Brian Silver Date: Wed, 15 Jun 2016 10:18:27 -0500 Subject: Change memdiags/mcbist stop conditions to incorporate end, thresholds Change-Id: I74659dc9efd3a348abaa12c65e9aed6eae0fba15 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/25993 Tested-by: Hostboot CI Tested-by: Jenkins Server Reviewed-by: Brian R. Silver Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/25998 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell --- .../p9/procedures/hwp/memory/lib/mcbist/mcbist.H | 135 +++--- .../p9/procedures/hwp/memory/lib/mcbist/memdiags.C | 112 ++--- .../p9/procedures/hwp/memory/lib/mcbist/memdiags.H | 50 +-- .../p9/procedures/hwp/memory/lib/mcbist/settings.H | 467 ++++++++++++++++----- .../p9/procedures/hwp/memory/p9_mss_memdiag.C | 5 +- .../p9/procedures/hwp/memory/p9_mss_memdiag.H | 2 +- .../chips/p9/procedures/hwp/memory/p9_mss_scrub.C | 2 +- .../procedures/hwp/memory/tests/mss_memdiags_ut.C | 166 ++++++-- 8 files changed, 626 insertions(+), 313 deletions(-) diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H index 067b1362b..0e678fb79 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H @@ -616,11 +616,12 @@ class program iv_addr_gen.insertFromRight(0b0000); // By default if there's an error, we stop after the errored address - iv_config.insertFromRight( - stop_conditions::STOP_AFTER_ADDRESS); + iv_config.insertFromRight(end_boundary::STOP_AFTER_ADDRESS); // All mcbist attentions are host attentions, special attention bit is already clear iv_config.setBit(); + } /// @@ -636,15 +637,66 @@ class program /// /// @brief Change the mcbist thresholds - /// @param[in] i_thresholds the new thresholds + /// @param[in] i_thresholds the new thresholds/stop conditions /// @return void /// - inline void change_thresholds( const thresholds& i_thresholds ) + inline void change_thresholds( const stop_conditions& i_thresholds ) { iv_thresholds = i_thresholds; return; } + /// + /// @brief Change the forced pause state + /// @param[in] i_end the end_boundary to pause at + /// @return void + /// + inline void change_forced_pause( const end_boundary& i_end ) + { + if (i_end == end_boundary::DONT_CHANGE) + { + return; + } + + // Clear all the forced pause bits so we don't stack pauses + iv_config.clearBit(); + iv_config.clearBit(); + iv_config.clearBit(); + iv_addr_gen.clearBit(); + + switch (i_end) + { + case end_boundary::STOP_AFTER_ADDRESS: + iv_config.setBit(); + break; + + case end_boundary::STOP_AFTER_SLAVE_RANK: + iv_config.setBit(); + iv_addr_gen.setBit(); + break; + + case end_boundary::STOP_AFTER_MASTER_RANK: + iv_config.setBit(); + iv_addr_gen.clearBit(); + break; + + case end_boundary::STOP_AFTER_SUBTEST: + iv_config.setBit(); + break; + + // None is all set, we cleared the bits above + case end_boundary::NONE: + break; + + // Default is a no forced pause (as we cleared all the bits) + default: + FAPI_INF("no forced pause state - end state %d unknown", i_end); + break; + }; + + return; + } + /// /// @brief Change MCBIST Speed /// @param[in] i_target the target behind which the memory sits @@ -706,70 +758,33 @@ class program } /// - /// @brief Change MCBIST Stop conditions - /// @param[in] i_stops the stop conditions - /// @param[in] i_only_if_error forces the stop conditions to only be in effect if there is an error - /// if there is not an error the subtest continues. Defaults to mss::NO, meaning these are forced conditions - /// @return FAPI2_RC_SUCCSS iff ok + /// @brief Change MCBIST Stop-on-error conditions (end boundaries) + /// @param[in] i_end the end boundary /// @note By default the MCBIST is programmed to always stop after an errored address. This API /// allows the caller to force a stop at a boundary or to force no stopping on errors /// - inline void change_stops( const stop_conditions i_stops, const bool i_only_if_error = mss::NO ) + inline void change_end_boundary( const end_boundary i_end ) { - // If there's no change, just get outta here - if (i_stops == DONT_CHANGE) - { - goto fapi_try_exit; - } + // Which bit in the end boundary which siginifies this is a slave rank detect situation + constexpr uint64_t SLAVE_RANK_INDICATED_BIT = 61; - // If these conditions only take effect when there's an error, set that up in the ERROR_MODE field - // NO_STOP_ON_ERROR is specific to the ERROR MODE field, so set that up here too - if ((i_only_if_error == mss::YES) || (i_stops == NO_STOP_ON_ERROR)) + // If there's no change, just get outta here + if (i_end == DONT_CHANGE) { - iv_config.insertFromRight(i_stops); - goto fapi_try_exit; + return; } - // Otherwise, these are forced conditions and they need to be put in their specific fields - switch(i_stops) - { - case STOP_AFTER_ADDRESS: - iv_config.setBit(); - break; - - case STOP_AFTER_RANK: - iv_config.setBit(); - break; - - case STOP_AFTER_SUBTEST: - iv_config.setBit(); - break; + // The values of the enum were crafted so that we can simply insertFromRight into the register. + // We take note of whether to set the slave or master rank indicator and set that as well. + // The hardware has to have a 1 or a 0 - so there is no choice for the rank detection. So it + // doesn't matter that we're processing other end boundaries here - they'll just look like we + // asked for a master rank detect. + iv_config.insertFromRight(i_end); - // Same as don't-change - default: - break; - }; - - fapi_try_exit: - FAPI_INF("load MCBIST stops: 0x%016lx (0x%016lx)", i_stops, iv_config); - - return; - } - - /// - /// @brief Change MCBIST End boundaries - /// @param[in] i_end the end boundary - /// @return FAPI2_RC_SUCCSS iff ok - /// @note this really is just deciding if the stop conditions are master or slave rank boundaries - /// - inline void change_end_boundary( const end_boundary i_end ) - { - // This is a little funny ... the hardware has one bit representing 'master' and 'slave' - // So, NONE really represents a stop condition. We probably should combine the two, but the - // API doc from PRD asks for them separate. - uint64_t l_detect_slave = i_end == end_boundary::SLAVE_RANK ? 1 : 0; + FAPI_INF("i_end 0x%016lx", i_end); + uint64_t l_detect_slave = fapi2::buffer(i_end).getBit(); + iv_addr_gen.writeBit( l_detect_slave ); FAPI_INF("load MCBIST end boundaries: detect slave? %s", (l_detect_slave == 1 ? "yes" : "no") ); - iv_addr_gen.writeBit(l_detect_slave); } /// @@ -1139,8 +1154,8 @@ class program // The pattern for the pattern generator uint64_t iv_pattern; - // The error thresholds for the program - thresholds iv_thresholds; + // The error stop conditions, thresholds for the program + stop_conditions iv_thresholds; }; /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C index 004f36720..c9e8c77b3 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C @@ -117,14 +117,11 @@ fapi2::ReturnCode operation::base_init() // Load pattern FAPI_TRY( iv_program.change_pattern(iv_const.iv_pattern) ); - // Load stop conditions - iv_program.change_stops(iv_const.iv_stop); - // Load end boundaries iv_program.change_end_boundary(iv_const.iv_end_boundary); // Load thresholds - iv_program.change_thresholds(iv_const.iv_thresholds); + iv_program.change_thresholds(iv_const.iv_stop); // Setup the requested speed FAPI_TRY( iv_program.change_speed(iv_target, iv_const.iv_speed) ); @@ -428,19 +425,19 @@ fapi_try_exit: /// @note Uses broadcast mode if possible /// @param[in] i_target the target behind which all memory should be read /// @param[in] i_stop stop conditions -/// @param[in] i_thresholds thresholds +/// @param[in] i_end whether to end, and where - defaults to immediate (stop after failed address) /// @return FAPI2_RC_SUCCESS iff everything ok /// @note The function is asynchronous, and the caller should be looking for a done attention /// template<> fapi2::ReturnCode sf_read( const fapi2::Target& i_target, - const stop_conditions i_stop, - const thresholds& i_thresholds ) + const stop_conditions& i_stop, + const end_boundary i_end ) { FAPI_INF("superfast read start"); fapi2::ReturnCode l_rc; - constraints l_const(i_stop, i_thresholds); + constraints l_const(i_stop, speed::LUDICROUS, i_end, mss::mcbist::address()); sf_read_operation l_read_op(i_target, l_const, l_rc); FAPI_ASSERT( l_rc == FAPI2_RC_SUCCESS, @@ -457,21 +454,21 @@ fapi_try_exit: /// @brief Super Fast Read to End of Port - used to run superfast read on all memory behind the target /// @param[in] i_target the target behind which all memory should be read /// @param[in] i_stop stop conditions -/// @param[in] i_thresholds thresholds /// @param[in] i_address mcbist::address representing the port, dimm, rank +/// @param[in] i_end whether to end, and where - defaults to immediate (stop after failed address) /// @return FAPI2_RC_SUCCESS iff everything ok /// @note The function is asynchronous, and the caller should be looking for a done attention /// template<> fapi2::ReturnCode sf_read( const fapi2::Target& i_target, - const stop_conditions i_stop, - const thresholds& i_thresholds, - const mss::mcbist::address& i_address ) + const stop_conditions& i_stop, + const mss::mcbist::address& i_address, + const end_boundary i_end ) { FAPI_INF("superfast read - end of port"); fapi2::ReturnCode l_rc; - constraints l_const(i_stop, i_thresholds, i_address); + constraints l_const(i_stop, speed::LUDICROUS, i_end, i_address); sf_read_eop_operation l_read_op(i_target, l_const, l_rc); FAPI_ASSERT( l_rc == FAPI2_RC_SUCCESS, @@ -488,7 +485,6 @@ fapi_try_exit: /// @brief Scrub - continuous scrub all memory behind the target /// @param[in] i_target the target behind which all memory should be scrubbed /// @param[in] i_stop stop conditions -/// @param[in] i_thresholds thresholds /// @param[in] i_speed the speed to scrub /// @param[in] i_address mcbist::address representing the port, dimm, rank /// @return FAPI2_RC_SUCCESS iff everything ok @@ -496,15 +492,14 @@ fapi_try_exit: /// template<> fapi2::ReturnCode background_scrub( const fapi2::Target& i_target, - const stop_conditions i_stop, - const thresholds& i_thresholds, + const stop_conditions& i_stop, const speed i_speed, const mss::mcbist::address& i_address ) { FAPI_INF("continuous (background) scrub"); fapi2::ReturnCode l_rc; - constraints l_const(i_stop, i_thresholds, i_speed, end_boundary::NONE, i_address); + constraints l_const(i_stop, i_speed, end_boundary::NONE, i_address); continuous_scrub_operation l_op(i_target, l_const, l_rc); FAPI_ASSERT( l_rc == FAPI2_RC_SUCCESS, @@ -521,7 +516,6 @@ fapi_try_exit: /// @brief Scrub - targeted scrub all memory behind the target /// @param[in] i_target the target behind which all memory should be scrubbed /// @param[in] i_stop stop conditions -/// @param[in] i_thresholds thresholds /// @param[in] i_speed the speed to scrub /// @param[in] i_address mcbist::address representing the port, dimm, rank /// @param[in] i_end whether to end, and where @@ -530,22 +524,21 @@ fapi_try_exit: /// template<> fapi2::ReturnCode targeted_scrub( const fapi2::Target& i_target, - const stop_conditions i_stop, - const thresholds& i_thresholds, + const stop_conditions& i_stop, const speed i_speed, const mss::mcbist::address& i_address, const end_boundary i_end ) { FAPI_INF("targeted scrub"); - if (i_stop == memdiags::stop_conditions::DONT_STOP) + if (i_end == end_boundary::NONE) { - FAPI_ERR("targeted scrub must have stop conditions"); + FAPI_ERR("targeted scrub must have end boundaries"); return FAPI2_RC_INVALID_PARAMETER; } fapi2::ReturnCode l_rc; - constraints l_const(i_stop, i_thresholds, i_speed, i_end, i_address); + constraints l_const(i_stop, i_speed, i_end, i_address); targeted_scrub_operation l_op(i_target, l_const, l_rc); FAPI_ASSERT( l_rc == FAPI2_RC_SUCCESS, @@ -559,11 +552,10 @@ fapi_try_exit: } /// -/// @brief Continue current command on next address - change thresholds +/// @brief Continue current command on next address /// The current commaand has paused on an error, so we can record the address of the error /// and finish the current master or slave rank. /// @param[in] i_target the target -/// @param[in] i_thresholds new thresholds /// @param[in] i_end whether to end, and where (default = don't stop at end of rank) /// @param[in] i_stop stop conditions (default - 0 meaning 'don't change conditions') /// @param[in] i_speed the speed to scrub (default - NO_CHANGE meaning leave speed untouched) @@ -572,9 +564,8 @@ fapi_try_exit: /// template<> fapi2::ReturnCode continue_cmd( const fapi2::Target& i_target, - const thresholds& i_thresholds, const end_boundary i_end, - const stop_conditions i_stop, + const stop_conditions& i_stop, const speed i_speed ) { // Too long, make shorter @@ -589,37 +580,44 @@ fapi2::ReturnCode continue_cmd( const fapi2::Target& i_targe // TODO RTC:155518 Check for stop or in progress before allowing continue. Not critical // as the caller should know and can check the in-progress bit in the event they don't - // This is OK as because the i_end is optional, for the caller to specify a - // stop condition other than DONT_CHANGE, they'd have to specify the end too - // It doean't make any sense to have a 'don't stop' in the end boundaries as - // you need to tell the stop conditions that. - if (i_stop != stop_conditions::DONT_CHANGE) + if (i_end != end_boundary::DONT_CHANGE) { // Before we go too far, check to see if we're already stopped at the boundary we are asking to stop at bool l_stopped_at_boundary = false; uint64_t l_error_mode = 0; + bool l_detect_slave = false; - FAPI_TRY( mss::getScom(i_target, MCBIST_MCBCFGQ, l_program.iv_config) ); + FAPI_TRY( mss::getScom(i_target, TT::CFGQ_REG, l_program.iv_config) ); + FAPI_TRY( mss::getScom(i_target, TT::MCBAGRAQ_REG, l_program.iv_addr_gen) ); l_program.iv_config.extractToRight(l_error_mode); + l_detect_slave = l_program.iv_addr_gen.getBit(); - switch (i_stop) + switch (i_end) { - case stop_conditions::STOP_AFTER_ADDRESS: + case end_boundary::STOP_AFTER_ADDRESS: l_stopped_at_boundary = l_program.iv_config.getBit() || - l_error_mode == stop_conditions::STOP_AFTER_ADDRESS; + l_error_mode == end_boundary::STOP_AFTER_ADDRESS; + break; + + case end_boundary::STOP_AFTER_SLAVE_RANK: + // Note: we really want STOP_AFTER_MASTER_RANK here even though we're in the slave + // case because MASTER_RANK has the a 0 so that l_error_mode will check correctly + l_stopped_at_boundary = + l_program.iv_config.getBit() || + ((l_error_mode == end_boundary::STOP_AFTER_MASTER_RANK) && (l_detect_slave == false)); break; - case stop_conditions::STOP_AFTER_RANK: + case end_boundary::STOP_AFTER_MASTER_RANK: l_stopped_at_boundary = l_program.iv_config.getBit() || - l_error_mode == stop_conditions::STOP_AFTER_RANK; + ((l_error_mode == end_boundary::STOP_AFTER_MASTER_RANK) && (l_detect_slave == true)); break; - case stop_conditions::STOP_AFTER_SUBTEST: + case end_boundary::STOP_AFTER_SUBTEST: l_stopped_at_boundary = l_program.iv_config.getBit() || - l_error_mode == stop_conditions::STOP_AFTER_SUBTEST; + l_error_mode == end_boundary::STOP_AFTER_SUBTEST; break; // By default we're not stopped at a boundary we're going to continue from @@ -635,8 +633,6 @@ fapi2::ReturnCode continue_cmd( const fapi2::Target& i_targe // Read-modify-write the fields in the program. FAPI_TRY( mss::getScom(i_target, TT::MCBAGRAQ_REG, l_program.iv_addr_gen) ); - l_program.change_stops(i_stop); - l_program.change_end_boundary(i_end); FAPI_TRY( mss::mcbist::load_addr_gen(i_target, l_program) ); @@ -645,7 +641,7 @@ fapi2::ReturnCode continue_cmd( const fapi2::Target& i_targe } // Thresholds - FAPI_TRY( mss::mcbist::load_thresholds(i_target, i_thresholds) ); + FAPI_TRY( mss::mcbist::load_thresholds(i_target, i_stop) ); // Setup speed FAPI_TRY( l_program.change_speed(i_target, i_speed) ); @@ -661,34 +657,4 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief Continue current command on next address -/// The current commaand has paused on an error, so we can record the address of the error -/// and finish the current master or slave rank. -/// @param[in] i_target the target -/// @param[in] i_end where to end, if stop conditions change (defaults to Master Rank) -/// @param[in] i_stop stop conditions (default - DONT_CHANGE meaning 'don't change conditions') -/// @param[in] i_speed the speed to scrub (default - SAM_SPEED meaning leave speed untouched) -/// @return FAPI2_RC_SUCCESS iff ok -/// -template<> -fapi2::ReturnCode continue_cmd( const fapi2::Target& i_target, - const end_boundary i_end, - const stop_conditions i_stop, - const speed i_speed ) -{ - FAPI_INF("continue_cmd - no change thresholds"); - - // Read current thresholds and pass them as if they're changed. - fapi2::buffer i_thresholds; - FAPI_TRY( mss::getScom(i_target, mss::mcbist::mcbistTraits::THRESHOLD_REG, i_thresholds) ); - - return continue_cmd( i_target, thresholds(i_thresholds), i_end, i_stop, i_speed ); - -fapi_try_exit: - return fapi2::current_err; -} - - - } diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.H b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.H index 961fc5f73..796126171 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.H @@ -43,7 +43,6 @@ namespace memdiags // Map some of the mcbist namespace here to make it easier for users of memdiags // This is an intentional using statement in a header which is typically // disallowed - I am intentionally pulling these into this namespace for all callers. -using mss::mcbist::thresholds; using mss::mcbist::constraints; using mss::mcbist::speed; using mss::mcbist::end_boundary; @@ -291,6 +290,9 @@ struct targeted_scrub_operation : public operation // We're a single-port operation o_rc = this->single_port_init(); + + // Targeted scrub needs to force a pause and the end boundary. So we make sure that happens here. + this->iv_program.change_forced_pause( i_const.iv_end_boundary ); } targeted_scrub_operation() = delete; @@ -314,37 +316,36 @@ fapi2::ReturnCode sf_init( const fapi2::Target& i_target, /// @note Uses broadcast mode if possible /// @param[in] i_target the target behind which all memory should be read /// @param[in] i_stop stop conditions -/// @param[in] i_thresholds thresholds +/// @param[in] i_end whether to end, and where - defaults to immediate (stop after failed address) /// @return FAPI2_RC_SUCCESS iff everything ok /// @note The function is asynchronous, and the caller should be looking for a done attention /// template< fapi2::TargetType T > fapi2::ReturnCode sf_read( const fapi2::Target& i_target, - const stop_conditions i_stop, - const thresholds& i_thresholds ); + const stop_conditions& i_stop, + const end_boundary i_end = end_boundary::STOP_AFTER_ADDRESS ); /// /// @brief Super Fast Read to End of Port - used to run superfast read on all memory behind the target /// @tparam T the fapi2::TargetType of the target /// @param[in] i_target the target behind which all memory should be read /// @param[in] i_stop stop conditions -/// @param[in] i_thresholds thresholds /// @param[in] i_address mcbist::address representing the address from which to start. +/// @param[in] i_end whether to end, and where - defaults to immediate (stop after failed address) /// @return FAPI2_RC_SUCCESS iff everything ok /// @note The function is asynchronous, and the caller should be looking for a done attention /// @note The address is often the port, dimm, rank but this is not enforced in the API. /// template< fapi2::TargetType T > fapi2::ReturnCode sf_read( const fapi2::Target& i_target, - const stop_conditions i_stop, - const thresholds& i_thresholds, - const mss::mcbist::address& i_address ); + const stop_conditions& i_stop, + const mss::mcbist::address& i_address, + const end_boundary i_end = end_boundary::STOP_AFTER_ADDRESS ); /// /// @brief Scrub - continuous scrub all memory behind the target /// @param[in] i_target the target behind which all memory should be scrubbed /// @param[in] i_stop stop conditions -/// @param[in] i_thresholds thresholds /// @param[in] i_speed the speed to scrub /// @param[in] i_address mcbist::address representing the address from which to start. /// @return FAPI2_RC_SUCCESS iff everything ok @@ -353,8 +354,7 @@ fapi2::ReturnCode sf_read( const fapi2::Target& i_target, /// template< fapi2::TargetType T > fapi2::ReturnCode background_scrub( const fapi2::Target& i_target, - const stop_conditions i_stop, - const thresholds& i_thresholds, + const stop_conditions& i_stop, const speed i_speed, const mss::mcbist::address& i_address ); @@ -362,7 +362,6 @@ fapi2::ReturnCode background_scrub( const fapi2::Target& i_target, /// @brief Scrub - targeted scrub all memory described by the input address (rank, slave, etc.) /// @param[in] i_target the target behind which all memory should be scrubbed /// @param[in] i_stop stop conditions -/// @param[in] i_thresholds thresholds /// @param[in] i_speed the speed to scrub /// @param[in] i_address mcbist::address representing the address from which to start. /// @param[in] i_end whether to end, and where @@ -372,8 +371,7 @@ fapi2::ReturnCode background_scrub( const fapi2::Target& i_target, /// template< fapi2::TargetType T > fapi2::ReturnCode targeted_scrub( const fapi2::Target& i_target, - const stop_conditions i_stop, - const thresholds& i_thresholds, + const stop_conditions& i_stop, const speed i_speed, const mss::mcbist::address& i_address, const end_boundary i_end ); @@ -384,37 +382,17 @@ fapi2::ReturnCode targeted_scrub( const fapi2::Target& i_target, /// and finish the current master or slave rank. /// @tparam T the fapi2::TargetType of the target /// @param[in] i_target the target -/// @param[in] i_end whether to end, and where (default = don't stop at end of rank) -/// @param[in] i_stop stop conditions (default - 0 meaning 'don't change conditions') -/// @param[in] i_speed the speed to scrub (default - NO_CHANGE meaning leave speed untouched) -/// @return FAPI2_RC_SUCCESS iff ok -/// -template< fapi2::TargetType T > -fapi2::ReturnCode continue_cmd( const fapi2::Target& i_target, - const end_boundary i_end = end_boundary::NONE, - const stop_conditions i_stop = stop_conditions::DONT_CHANGE, - const speed i_speed = speed::SAME_SPEED ); - -/// -/// @brief Continue current command on next address - change thresholds -/// The current commaand has paused on an error, so we can record the address of the error -/// and finish the current master or slave rank. -/// @tparam T the fapi2::TargetType of the target -/// @param[in] i_target the target -/// @param[in] i_thresholds new thresholds -/// @param[in] i_end whether to end, and where (default = don't stop at end of rank) +/// @param[in] i_end whether to end, and where (default - don't stop at end of rank) /// @param[in] i_stop stop conditions (default - 0 meaning 'don't change conditions') /// @param[in] i_speed the speed to scrub (default - NO_CHANGE meaning leave speed untouched) /// @return FAPI2_RC_SUCCESS iff ok /// template< fapi2::TargetType T > fapi2::ReturnCode continue_cmd( const fapi2::Target& i_target, - const thresholds& i_thresholds, const end_boundary i_end = end_boundary::NONE, - const stop_conditions i_stop = stop_conditions::DONT_CHANGE, + const stop_conditions& i_stop = stop_conditions(), const speed i_speed = speed::SAME_SPEED ); - } // namespace #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/settings.H b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/settings.H index 4ab89090c..5f76ca774 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/settings.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/settings.H @@ -36,6 +36,7 @@ #include #include +#include namespace mss { @@ -43,29 +44,20 @@ namespace mss namespace mcbist { -/// Stop conditions for MCBIST programs -enum stop_conditions +/// End boundaries for MCBIST programs - where to stop when stopping or pausing +enum end_boundary : uint64_t { - NO_STOP_ON_ERROR = 0b00, - DONT_STOP = NO_STOP_ON_ERROR, - STOP_AFTER_ADDRESS = 0b01, - STOP_AFTER_RANK = 0b10, - STOP_AFTER_SUBTEST = 0b11, - - /// Don't change the stop conditions when continuing - DONT_CHANGE = 0xFF, -}; - -/// Boundary conditions for operations - when to stopmc -enum end_boundary -{ - NONE = 0, - CONTINUOUS = NONE, - NEVER = NONE, - MASTER_RANK = 1, - MRANK = MASTER_RANK, - SLAVE_RANK = 2, - SRANK = SLAVE_RANK, + // We're gonna get a little hacky here. The pause on error mode field + // is two bits, with another bit representing slave/master. So we craft + // the enum so that we can insertFromRight and get the proper vaules, and + // leave on bit out of that two-bit range to represent master or slave + NONE = 0b000, + STOP_AFTER_ADDRESS = 0b001, + STOP_AFTER_MASTER_RANK = 0b010, + STOP_AFTER_SLAVE_RANK = 0b110, + STOP_AFTER_SUBTEST = 0b011, + + DONT_CHANGE = 0xFF, }; /// Speeds for performing MCBIST operations @@ -82,35 +74,108 @@ enum speed }; /// -/// @class Memory diagnostic subsystem error thresholds +/// @class Memory diagnostic subsystem stop-on-error settings and thresholds /// @note Matches Nimbus MBSTRQ, but might be changed later for Centaur, or mapped. /// -class thresholds +class stop_conditions { public: + // Many of the config fields share a disable bit pattern, so we define it here - static constexpr uint64_t DISABLE = 0b1111; + static constexpr uint64_t DISABLE = 0b1111; + static constexpr uint64_t MAX_THRESHOLD = 0b1110; + + private: /// - /// @brief Thresholds class ctor + /// @brief Little helper to convert threshold inputs to exponents + /// @param[in] i_value, the value of the threshold (presumably) + /// @return a value n such that 2^n <= i_value && n < 15 /// - thresholds(): - iv_value(0) - { } + uint64_t make_threshold_setting( const uint64_t i_value ) + { + // If the user passes in DISABLE, let it past. This prevents callers from having to + // do the conditional. Zero is none which is disable + if ((i_value == DISABLE) || (i_value == 0)) + { + return DISABLE; + } + + // Find the first bit set. This represents the largest power of 2 this input can represent + // The subtraction from 63 switches from a left-count to a right-count (e.g., 0 (left most + // bit) is really bit 63 if you start on the right.) + uint64_t l_largest = 63 - first_bit_set(i_value); + + // If the first bit set is off in space and greater than 2^14, we just return 0b1110 + // Otherwise, l_largest is the droid we're looking for + return l_largest >= MAX_THRESHOLD ? MAX_THRESHOLD : l_largest; + } + + /// + /// @brief Generic pause on threshold + /// @tparam F, the bit field to manipulate + /// @tparam L, the length of F + /// @param[in] the state of the error - mss::ON or mss::OFF + /// @return fapi2::buffer& this->iv_value useful for method chaining + /// @note If the input is mss::ON, this method enables the error, it's corresponding + /// threshold defines the threshold at which the engine will stop. If no threshold is + /// defined (the error is disabled) this method will set the threshold to 1. A previously + /// defined threshold (i.e., not disabled) will be left intact. If the input + /// is mss::OFF, this method will disable the error by setting the threshold to disabled. + /// + template< uint64_t F, uint64_t L > + inline stop_conditions& set_pause_on_threshold( const states i_on_or_off ) + { + if (i_on_or_off == mss::OFF) + { + iv_value.insertFromRight(DISABLE); + return *this; + } + + uint64_t l_thresh = 0; + iv_value.extractToRight(l_thresh); + + if (l_thresh != DISABLE) + { + // Note the threshold field is an exponent, so this is 2^0, or 1 count + iv_value.insertFromRight(0); + } + return *this; + } + + public: + /// + /// @brief Stop/Thresholds class ctor + /// + stop_conditions(): + iv_value(0) + { + // By default we want to start everything in 'don't stop' mode. This means disabling + // the errors which contain thresholds + set_thresh_nce_int(DISABLE) + .set_thresh_nce_soft(DISABLE) + .set_thresh_nce_hard(DISABLE) + .set_thresh_rce(DISABLE) + .set_thresh_ice(DISABLE) + .set_thresh_mce_int(DISABLE) + .set_thresh_mce_soft(DISABLE) + .set_thresh_mce_hard(DISABLE); + } /// - /// @brief Thresholds class ctor + /// @brief Stop/Thresholds class ctor /// @param[in] uint64_t representing the threshold register contents /// - thresholds(const uint64_t i_value): + stop_conditions(const uint64_t i_value): iv_value(i_value) - { } + { + } /// - /// @brief Thresholds class dtor + /// @brief Stop/Thresholds class dtor /// - ~thresholds() = default; + ~stop_conditions() = default; /// /// @brief uint64_t conversion @@ -120,181 +185,378 @@ class thresholds return uint64_t(iv_value); } - /// @brief set_thresh_mag_nce_int + /// + /// @brief set_thresh_nce_int /// @param[in] i_value the value of the field /// NCE intermittent error threshold magnitude to trigger for triggering pause. If /// 1111, then pause will never be triggered (disabled). Else, then MCBIST will /// pause if it takes sees 2^[this value] number of errors of this type. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_thresh_mag_nce_int( const uint64_t i_value ) + /// @note The register field is actually an exponent. The hardware will count 2^n for the + /// threshold. However, the input represents a count - how many. Thus we need to convert + /// the input to a power of 2 to get a proper exponent. Your input will be rounded down + /// to the nearest power of 2 which is less than 2^15 before being set in the register. + /// + inline stop_conditions& set_thresh_nce_int( const uint64_t i_value ) { - iv_value.insertFromRight(i_value); + iv_value.insertFromRight(make_threshold_setting(i_value)); return *this; } - /// @brief set_thresh_mag_nce_soft + /// + /// @brief set_pause_on_nce_int - enable NCE intermittent error + /// @param[in] i_on_or_off - the desired state. + /// @return fapi2::buffer& this->iv_value useful for method chaining + /// @note If the input is mss::ON, this method enables the error, it's corresponding + /// threshold defines the threshold at which the engine will stop. If no threshold is + /// defined (the error is disabled) this method will set the threshold to 1. A previously + /// defined threshold (i.e., not disabled) will be left intact. If the input + /// is mss::OFF, this method will disable the error by setting the threshold to disabled. + /// + inline stop_conditions& set_pause_on_nce_int( const states i_on_or_off ) + { + return set_pause_on_threshold(i_on_or_off); + } + + /// + /// @brief set_thresh_nce_soft /// @param[in] i_value the value of the field /// NCE soft error threshold magnitude to trigger for triggering pause. If 1111, /// then pause will never be triggered (disabled). Else, then MCBIST will pause if it /// takes sees 2^[this value] number of errors of this type. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_thresh_mag_nce_soft( const uint64_t i_value ) + /// @note The register field is actually an exponent. The hardware will count 2^n for the + /// threshold. However, the input represents a count - how many. Thus we need to convert + /// the input to a power of 2 to get a proper exponent. Your input will be rounded down + /// to the nearest power of 2 which is less than 2^15 before being set in the register. + /// + inline stop_conditions& set_thresh_nce_soft( const uint64_t i_value ) { - iv_value.insertFromRight(i_value); + iv_value.insertFromRight(make_threshold_setting(i_value)); return *this; } - /// @brief set_thresh_mag_nce_hard + /// + /// @brief set_pause_on_nce_int - enable NCE soft error + /// @param[in] i_on_or_off - the desired state. + /// @return fapi2::buffer& this->iv_value useful for method chaining + /// @note If the input is mss::ON, this method enables the error, it's corresponding + /// threshold defines the threshold at which the engine will stop. If no threshold is + /// defined (the error is disabled) this method will set the threshold to 1. A previously + /// defined threshold (i.e., not disabled) will be left intact. If the input + /// is mss::OFF, this method will disable the error by setting the threshold to disabled. + /// + inline stop_conditions& set_pause_on_nce_soft( const states i_on_or_off ) + { + return set_pause_on_threshold(i_on_or_off); + } + + /// + /// @brief set_thresh_nce_hard /// @param[in] i_value the value of the field /// NCE hard error threshold magnitude to trigger for triggering pause. If 1111, /// then pause will never be triggered (disabled). Else, then MCBIST will pause if it /// takes sees 2^[this value] number of errors of this type. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_thresh_mag_nce_hard( const uint64_t i_value ) + /// @note The register field is actually an exponent. The hardware will count 2^n for the + /// threshold. However, the input represents a count - how many. Thus we need to convert + /// the input to a power of 2 to get a proper exponent. Your input will be rounded down + /// to the nearest power of 2 which is less than 2^15 before being set in the register. + /// + inline stop_conditions& set_thresh_nce_hard( const uint64_t i_value ) { - iv_value.insertFromRight(i_value); + iv_value.insertFromRight(make_threshold_setting(i_value)); return *this; } - /// @brief set_thresh_mag_rce + /// + /// @brief set_pause_on_nce_hard - enable NCE hard error + /// @param[in] i_on_or_off - the desired state. + /// @return fapi2::buffer& this->iv_value useful for method chaining + /// @note If the input is mss::ON, this method enables the error, it's corresponding + /// threshold defines the threshold at which the engine will stop. If no threshold is + /// defined (the error is disabled) this method will set the threshold to 1. A previously + /// defined threshold (i.e., not disabled) will be left intact. If the input + /// is mss::OFF, this method will disable the error by setting the threshold to disabled. + /// + inline stop_conditions& set_pause_on_nce_hard( const states i_on_or_off ) + { + return set_pause_on_threshold(i_on_or_off); + } + + /// + /// @brief set_thresh_rce /// @param[in] i_value the value of the field /// RCE error threshold magnitude to trigger for triggering pause. If 1111, then /// pause will never be triggered (disabled). Else, then MCBIST will pause if it takes /// sees 2^[this value] number of errors of this type. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_thresh_mag_rce( const uint64_t i_value ) + /// @note The register field is actually an exponent. The hardware will count 2^n for the + /// threshold. However, the input represents a count - how many. Thus we need to convert + /// the input to a power of 2 to get a proper exponent. Your input will be rounded down + /// to the nearest power of 2 which is less than 2^15 before being set in the register. + /// + inline stop_conditions& set_thresh_rce( const uint64_t i_value ) { - iv_value.insertFromRight(i_value); + iv_value.insertFromRight(make_threshold_setting(i_value)); return *this; } - /// @brief set_thresh_mag_ice + /// + /// @brief set_pause_on_rce - enable RCE error + /// @param[in] i_on_or_off - the desired state. + /// @return fapi2::buffer& this->iv_value useful for method chaining + /// @note If the input is mss::ON, this method enables the error, it's corresponding + /// threshold defines the threshold at which the engine will stop. If no threshold is + /// defined (the error is disabled) this method will set the threshold to 1. A previously + /// defined threshold (i.e., not disabled) will be left intact. If the input + /// is mss::OFF, this method will disable the error by setting the threshold to disabled. + /// + inline stop_conditions& set_pause_on_rce( const states i_on_or_off ) + { + return set_pause_on_threshold(i_on_or_off); + } + + /// + /// @brief set_thresh_ice /// @param[in] i_value the value of the field /// ICE (IMPE) error threshold magnitude to trigger for triggering pause. If 1111, /// then pause will never be triggered (disabled). Else, then MCBIST will pause if /// it takes sees 2^[this value] number of errors of this type. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_thresh_mag_ice( const uint64_t i_value ) + /// @note The register field is actually an exponent. The hardware will count 2^n for the + /// threshold. However, the input represents a count - how many. Thus we need to convert + /// the input to a power of 2 to get a proper exponent. Your input will be rounded down + /// to the nearest power of 2 which is less than 2^15 before being set in the register. + /// + inline stop_conditions& set_thresh_ice( const uint64_t i_value ) { - iv_value.insertFromRight(i_value); + iv_value.insertFromRight(make_threshold_setting(i_value)); return *this; } - /// @brief set_thresh_mag_mce_int + /// + /// @brief set_pause_on_ice - enable ICE (IMPE) error + /// @param[in] i_on_or_off - the desired state. + /// @return fapi2::buffer& this->iv_value useful for method chaining + /// @note If the input is mss::ON, this method enables the error, it's corresponding + /// threshold defines the threshold at which the engine will stop. If no threshold is + /// defined (the error is disabled) this method will set the threshold to 1. A previously + /// defined threshold (i.e., not disabled) will be left intact. If the input + /// is mss::OFF, this method will disable the error by setting the threshold to disabled. + /// + inline stop_conditions& set_pause_on_ice( const states i_on_or_off ) + { + return set_pause_on_threshold(i_on_or_off); + } + + /// + /// @brief set_thresh_mce_int /// @param[in] i_value the value of the field /// MCE intermittent error threshold magnitude to trigger for triggering pause. If /// 1111, then pause will never be triggered (disabled). Else, then MCBIST will /// pause if it takes sees 2^[this value] number of errors of this type. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_thresh_mag_mce_int( const uint64_t i_value ) + /// @note The register field is actually an exponent. The hardware will count 2^n for the + /// threshold. However, the input represents a count - how many. Thus we need to convert + /// the input to a power of 2 to get a proper exponent. Your input will be rounded down + /// to the nearest power of 2 which is less than 2^15 before being set in the register. + /// + inline stop_conditions& set_thresh_mce_int( const uint64_t i_value ) { - iv_value.insertFromRight(i_value); + iv_value.insertFromRight(make_threshold_setting(i_value)); return *this; } - /// @brief set_thresh_mag_mce_soft + /// + /// @brief set_pause_on_mce_int - enable MCE intermittent error + /// @param[in] i_on_or_off - the desired state. + /// @return fapi2::buffer& this->iv_value useful for method chaining + /// @note If the input is mss::ON, this method enables the error, it's corresponding + /// threshold defines the threshold at which the engine will stop. If no threshold is + /// defined (the error is disabled) this method will set the threshold to 1. A previously + /// defined threshold (i.e., not disabled) will be left intact. If the input + /// is mss::OFF, this method will disable the error by setting the threshold to disabled. + /// + inline stop_conditions& set_pause_on_mce_int( const states i_on_or_off ) + { + return set_pause_on_threshold(i_on_or_off); + } + + /// + /// @brief set_thresh_mce_soft /// @param[in] i_value the value of the field /// MCE soft error threshold magnitude to trigger for triggering pause. If 1111, /// then pause will never be triggered (disabled). Else, then MCBIST will pause if it /// takes sees 2^[this value] number of errors of this type. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_thresh_mag_mce_soft( const uint64_t i_value ) + /// @note The register field is actually an exponent. The hardware will count 2^n for the + /// threshold. However, the input represents a count - how many. Thus we need to convert + /// the input to a power of 2 to get a proper exponent. Your input will be rounded down + /// to the nearest power of 2 which is less than 2^15 before being set in the register. + /// + inline stop_conditions& set_thresh_mce_soft( const uint64_t i_value ) { - iv_value.insertFromRight(i_value); + iv_value.insertFromRight(make_threshold_setting(i_value)); return *this; } - /// @brief set_thresh_mag_mce_hard + /// + /// @brief set_pause_on_mce_soft - enable MCE soft error + /// @param[in] i_on_or_off - the desired state. + /// @return fapi2::buffer& this->iv_value useful for method chaining + /// @note If the input is mss::ON, this method enables the error, it's corresponding + /// threshold defines the threshold at which the engine will stop. If no threshold is + /// defined (the error is disabled) this method will set the threshold to 1. A previously + /// defined threshold (i.e., not disabled) will be left intact. If the input + /// is mss::OFF, this method will disable the error by setting the threshold to disabled. + /// + inline stop_conditions& set_pause_on_mce_soft( const states i_on_or_off ) + { + return set_pause_on_threshold(i_on_or_off); + } + + /// + /// @brief set_thresh_mce_hard /// @param[in] i_value the value of the field /// MCE hard error threshold magnitude to trigger for triggering pause. If 1111, /// then pause will never be triggered (disabled). Else, then MCBIST will pause if it /// takes sees 2^[this value] number of errors of this type. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_thresh_mag_mce_hard( const uint64_t i_value ) + /// @note The register field is actually an exponent. The hardware will count 2^n for the + /// threshold. However, the input represents a count - how many. Thus we need to convert + /// the input to a power of 2 to get a proper exponent. Your input will be rounded down + /// to the nearest power of 2 which is less than 2^15 before being set in the register. + /// + inline stop_conditions& set_thresh_mce_hard( const uint64_t i_value ) { - iv_value.insertFromRight(i_value); + iv_value.insertFromRight(make_threshold_setting(i_value)); return *this; } + /// + /// @brief set_pause_on_mce_hard - enable MCE hard error + /// @param[in] i_on_or_off - the desired state. + /// @return fapi2::buffer& this->iv_value useful for method chaining + /// @note If the input is mss::ON, this method enables the error, it's corresponding + /// threshold defines the threshold at which the engine will stop. If no threshold is + /// defined (the error is disabled) this method will set the threshold to 1. A previously + /// defined threshold (i.e., not disabled) will be left intact. If the input + /// is mss::OFF, this method will disable the error by setting the threshold to disabled. + /// + inline stop_conditions& set_pause_on_mce_hard( const states i_on_or_off ) + { + return set_pause_on_threshold(i_on_or_off); + } + + /// /// @brief set_pause_on_sce /// @param[in] i_value the value of the field /// Enable pause on SCE error. When enabled, MCBIST will pause at the boundary /// configured if this error is seen. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_pause_on_sce( const uint64_t i_value ) + /// + inline stop_conditions& set_pause_on_sce( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_pause_on_mce /// @param[in] i_value the value of the field /// Enable pause on MCE error. When enabled, MCBIST will pause at the boundary /// configured if this error is seen. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_pause_on_mce( const uint64_t i_value ) + /// + inline stop_conditions& set_pause_on_mce( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_pause_on_mpe /// @param[in] i_value the value of the field /// Enable pause on MPE error. When enabled, MCBIST will pause at the boundary /// configured if this error is seen. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_pause_on_mpe( const uint64_t i_value ) + /// + inline stop_conditions& set_pause_on_mpe( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_pause_on_ue /// @param[in] i_value the value of the field /// Enable pause on UE error. When enabled, MCBIST will pause at the boundary /// configured if this error is seen. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_pause_on_ue( const uint64_t i_value ) + /// + inline stop_conditions& set_pause_on_ue( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_pause_on_sue /// @param[in] i_value the value of the field /// Enable pause on SUE error. When enabled, MCBIST will pause at the boundary /// configured if this error is seen. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_pause_on_sue( const uint64_t i_value ) + /// + inline stop_conditions& set_pause_on_sue( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_pause_on_aue /// @param[in] i_value the value of the field /// Enable pause on AUE error. When enabled, MCBIST will pause at the boundary /// configured if this error is seen. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_pause_on_aue( const uint64_t i_value ) + /// + inline stop_conditions& set_pause_on_aue( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_pause_on_rcd /// @param[in] i_value the value of the field /// Enable pause on RCD error. When enabled, MCBIST will pause at the boundary /// configured if this error is seen. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_pause_on_rcd( const uint64_t i_value ) + /// + inline stop_conditions& set_pause_on_rcd( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } - // Reserved. 39:52 - + /// /// @brief set_symbol_counter_mode /// @param[in] i_value the value of the field /// Selects which mode to use symbol counter latches: Mode 0) MAINT 8-bit error @@ -302,111 +564,132 @@ class thresholds /// ranks (port agnostic) Mode 2) MCBIST 4-bit error counters for 18 nibbles x 4 /// ports (rank agnostic) and 1-bit error rank map for 18 nibbles x 4 ports /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_symbol_counter_mode( const uint64_t i_value ) + /// + inline stop_conditions& set_symbol_counter_mode( const uint64_t i_value ) { - iv_value.insertFromRight(i_value); + iv_value.insertFromRight(i_value); return *this; } + /// /// @brief set_nce_soft_symbol_count_enable /// @param[in] i_value the value of the field /// Enables soft NCEs to trigger per symbol NCE error counting Only applies to /// scrub where we have different types of NCE. Non scrub counts all NCE. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_nce_soft_symbol_count_enable( const uint64_t i_value ) + /// + inline stop_conditions& set_nce_soft_symbol_count_enable( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_nce_inter_symbol_count_enable /// @param[in] i_value the value of the field /// Enables intermittent NCEs to trigger per symbol NCE error counting Only applies /// to scrub where we have different types of NCE. Non scrub counts all NCE. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_nce_inter_symbol_count_enable( const uint64_t i_value ) + /// + inline stop_conditions& set_nce_inter_symbol_count_enable( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_nce_hard_symbol_count_enable /// @param[in] i_value the value of the field /// Enables hard NCEs to trigger per symbol NCE error counting Only applies to /// scrub where we have different types of NCE. Non scrub counts all NCE. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_nce_hard_symbol_count_enable( const uint64_t i_value ) + /// + inline stop_conditions& set_nce_hard_symbol_count_enable( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_pause_mcb_error /// @param[in] i_value the value of the field /// Enable pause when MCBIST error is logged. When enabled, MCBIST will pause at /// the boundary configured if this error is seen. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_pause_mcb_error( const uint64_t i_value ) + /// + inline stop_conditions& set_pause_mcb_error( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_pause_mcb_log_full /// @param[in] i_value the value of the field /// Enable pause when MCBIST log is full. When enabled, MCBIST will pause at the /// boundary configured if this error is seen. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_pause_mcb_log_full( const uint64_t i_value ) + /// + inline stop_conditions& set_pause_mcb_log_full( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_maint_rce_with_ce /// @param[in] i_value the value of the field /// cfg_maint_rce_with_ce - not implemented. Need to investigate if needed for nimbus. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_maint_rce_with_ce( const uint64_t i_value ) + /// + inline stop_conditions& set_maint_rce_with_ce( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_mce_soft_symbol_count_enable /// @param[in] i_value the value of the field /// Enables soft MCEs to trigger per symbol MCE error counting Only applies to /// scrub where we have different types of MCE. Non scrub counts all MCE. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_mce_soft_symbol_count_enable( const uint64_t i_value ) + /// + inline stop_conditions& set_mce_soft_symbol_count_enable( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_mce_inter_symbol_count_enable /// @param[in] i_value the value of the field /// Enables intermittent MCEs to trigger per symbol MCE error counting Only applies /// to scrub where we have different types of MCE. Non scrub counts all MCE. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_mce_inter_symbol_count_enable( const uint64_t i_value ) + /// + inline stop_conditions& set_mce_inter_symbol_count_enable( const uint64_t i_value ) { iv_value.writeBit(i_value); return *this; } + /// /// @brief set_mce_hard_symbol_count_enable /// @param[in] i_value the value of the field /// Enables hard MCEs to trigger per symbol MCE error counting Only applies to /// scrub where we have different types of MCE. Non scrub counts all MCE. /// @return fapi2::buffer& this->iv_value useful for method chaining - inline thresholds& set_mce_hard_symbol_count_enable( const uint64_t i_value ) + /// + inline stop_conditions& set_mce_hard_symbol_count_enable( const uint64_t i_value ) { iv_value.writeBit(iv_value); return *this; } private: + fapi2::buffer iv_value; }; @@ -419,8 +702,7 @@ struct constraints /// @brief constraints constructor /// constraints(): - iv_stop(NO_STOP_ON_ERROR), - iv_thresholds(), + iv_stop(), iv_pattern(NO_PATTERN), iv_end_boundary(NONE), iv_speed(LUDICROUS), @@ -433,7 +715,7 @@ struct constraints /// @brief constraints constructor /// @param[in] i_pattern a pattern to set /// - constraints( const uint64_t i_pattern): + constraints( const uint64_t i_pattern ): constraints() { iv_pattern = i_pattern; @@ -443,45 +725,37 @@ struct constraints /// /// @brief constraints constructor /// @param[in] i_stop stop conditions - /// @param[in] i_thresholds thresholds /// - constraints( const stop_conditions i_stop, - const thresholds& i_thresholds ): + constraints( const stop_conditions& i_stop ): constraints() { iv_stop = i_stop; - iv_thresholds = i_thresholds; - FAPI_INF("setting up constraints with stop %d and thresholds 0x%x", i_stop, uint64_t(i_thresholds)); + FAPI_INF("setting up constraints with stop 0x%016lx", uint64_t(i_stop)); } /// /// @brief constraints constructor /// @param[in] i_stop stop conditions - /// @param[in] i_thresholds thresholds /// @param[in] i_start_address address to start from /// - constraints( const stop_conditions i_stop, - const thresholds& i_thresholds, + constraints( const stop_conditions& i_stop, const address& i_start_address ): - constraints(i_stop, i_thresholds) + constraints(i_stop) { iv_start_address = i_start_address; - FAPI_INF("setting up constraints with stop %d and thresholds 0x%x start address", - i_stop, uint64_t(i_thresholds), uint64_t(i_start_address)); + FAPI_INF("setting up constraints with start address 0x%016lx", uint64_t(i_start_address)); } /// /// @brief constraints constructor /// @param[in] i_stop stop conditions - /// @param[in] i_thresholds thresholds /// @param[in] i_start_address address to start from /// - constraints( const stop_conditions i_stop, - const thresholds& i_thresholds, + constraints( const stop_conditions& i_stop, const speed i_speed, const end_boundary i_end_boundary, const address& i_start_address ): - constraints(i_stop, i_thresholds, i_start_address) + constraints(i_stop, i_start_address) { iv_end_boundary = i_end_boundary; iv_speed = i_speed; @@ -489,7 +763,6 @@ struct constraints } stop_conditions iv_stop; - thresholds iv_thresholds; uint64_t iv_pattern; end_boundary iv_end_boundary; speed iv_speed; diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C index 55b48cfaa..0b35ed2bf 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C @@ -24,7 +24,7 @@ // *HWP HWP Owner: Brian Silver // *HWP HWP Backup: Andre Marin // *HWP Team: Memory -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HB #include @@ -69,7 +69,8 @@ extern "C" mss::poll_parameters l_poll_parameters; bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters, - [&l_status](const size_t poll_remaining, const fapi2::buffer& stat_reg) -> bool + [&l_status](const size_t poll_remaining, + const fapi2::buffer& stat_reg) -> bool { FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining); l_status = stat_reg; diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.H b/src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.H index 6ffef09ba..546972e03 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.H +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.H @@ -23,7 +23,7 @@ // *HWP HWP Owner: Brian Silver // *HWP HWP Backup: Andre Marin // *HWP Team: Memory -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HB #ifndef __P9_MSS_MEMDIAG__ diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_scrub.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_scrub.C index 20fed5c89..5b131da65 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_scrub.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_scrub.C @@ -65,7 +65,7 @@ fapi2::ReturnCode p9_mss_scrub( const fapi2::Target& i_targe } // TK do we want these to be arguments to the wrapper? - return memdiags::background_scrub(i_target, mss::mcbist::stop_conditions::NO_STOP_ON_ERROR, mss::mcbist::thresholds(), + return memdiags::background_scrub(i_target, mss::mcbist::stop_conditions(), mss::mcbist::speed::LUDICROUS, mss::mcbist::address()); fapi_try_exit: diff --git a/src/import/chips/p9/procedures/hwp/memory/tests/mss_memdiags_ut.C b/src/import/chips/p9/procedures/hwp/memory/tests/mss_memdiags_ut.C index 1e20269fb..afd81a6bd 100644 --- a/src/import/chips/p9/procedures/hwp/memory/tests/mss_memdiags_ut.C +++ b/src/import/chips/p9/procedures/hwp/memory/tests/mss_memdiags_ut.C @@ -71,45 +71,122 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" REQUIRE_FALSE( FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target(), is_sim) ); - SECTION("Test thresholds structure") + SECTION("Test stop_condition structure") { - mss::mcbist::thresholds l_t; - REQUIRE( 0 == l_t ); + // Stops default to all conditions off and all thresholded conditions disabled + mss::mcbist::stop_conditions l_t; + REQUIRE( 0xffffffff00000000 == l_t ); { - l_t.set_thresh_mag_nce_int( mss::mcbist::thresholds::DISABLE ); - REQUIRE( 0xf000000000000000 == l_t ); + l_t.set_thresh_nce_int( 0 ); + REQUIRE( 0xffffffff00000000 == l_t ); + + l_t.set_thresh_nce_int( 1 ); + REQUIRE( 0x0fffffff00000000 == l_t ); + + l_t.set_thresh_nce_int( 2 ); + REQUIRE( 0x1fffffff00000000 == l_t ); + + // Because 2^3 is 8 which is the exponent of the nearest rounded down power of 2 (12 - 4 == 8) + l_t.set_thresh_nce_int( 12 ); + REQUIRE( 0x3fffffff00000000 == l_t ); + + l_t.set_thresh_nce_int( mss::mcbist::stop_conditions::DISABLE ); + REQUIRE( 0xffffffff00000000 == l_t ); } { - l_t.set_thresh_mag_nce_soft( mss::mcbist::thresholds::DISABLE ); - REQUIRE( 0xff00000000000000 == l_t ); + l_t.set_thresh_nce_soft( 0 ); + REQUIRE( 0xffffffff00000000 == l_t ); + + l_t.set_thresh_nce_soft( 1 ); + REQUIRE( 0xf0ffffff00000000 == l_t ); + + l_t.set_thresh_nce_soft( 2 ); + REQUIRE( 0xf1ffffff00000000 == l_t ); + + // Because 2^3 is 8 which is the exponent of the nearest rounded down power of 2 (12 - 4 == 8) + l_t.set_thresh_nce_soft( 12 ); + REQUIRE( 0xf3ffffff00000000 == l_t ); + + l_t.set_thresh_nce_soft( mss::mcbist::stop_conditions::DISABLE ); + REQUIRE( 0xffffffff00000000 == l_t ); } { - l_t.set_thresh_mag_nce_hard( mss::mcbist::thresholds::DISABLE ); - REQUIRE( 0xfff0000000000000 == l_t ); + l_t.set_thresh_nce_hard( 0 ); + REQUIRE( 0xffffffff00000000 == l_t ); + + l_t.set_thresh_nce_hard( 1 ); + REQUIRE( 0xff0fffff00000000 == l_t ); + + l_t.set_thresh_nce_hard( 2 ); + REQUIRE( 0xff1fffff00000000 == l_t ); + + l_t.set_thresh_nce_hard( 10 ); + REQUIRE( 0xff3fffff00000000 == l_t ); + + l_t.set_thresh_nce_hard( mss::mcbist::stop_conditions::DISABLE ); + REQUIRE( 0xffffffff00000000 == l_t ); } { - l_t.set_thresh_mag_rce( mss::mcbist::thresholds::DISABLE ); - REQUIRE( 0xffff000000000000 == l_t ); + l_t.set_thresh_rce( 0 ); + REQUIRE( 0xffffffff00000000 == l_t ); + + l_t.set_thresh_rce( 1 ); + REQUIRE( 0xfff0ffff00000000 == l_t ); + + l_t.set_thresh_rce( 2 ); + REQUIRE( 0xfff1ffff00000000 == l_t ); + + l_t.set_thresh_rce( 5 ); + REQUIRE( 0xfff2ffff00000000 == l_t ); + + l_t.set_thresh_rce( mss::mcbist::stop_conditions::DISABLE ); + REQUIRE( 0xffffffff00000000 == l_t ); } // Little method chaining check { - l_t.set_thresh_mag_ice( mss::mcbist::thresholds::DISABLE ) - .set_thresh_mag_mce_int( mss::mcbist::thresholds::DISABLE ); - REQUIRE( 0xffffff0000000000 == l_t ); + memdiags::stop_conditions l_t(0); + l_t.set_thresh_ice( mss::mcbist::stop_conditions::DISABLE ) + .set_thresh_mce_int( mss::mcbist::stop_conditions::DISABLE ); + REQUIRE( 0x0000ff0000000000 == l_t ); } { - l_t.set_thresh_mag_mce_soft( mss::mcbist::thresholds::DISABLE ); - REQUIRE( 0xfffffff000000000 == l_t ); + l_t.set_thresh_mce_soft( 0 ); + REQUIRE( 0xffffffff00000000 == l_t ); + + l_t.set_thresh_mce_soft( 1 ); + REQUIRE( 0xffffff0f00000000 == l_t ); + + l_t.set_thresh_mce_soft( 2 ); + REQUIRE( 0xffffff1f00000000 == l_t ); + + l_t.set_thresh_mce_soft( 10 ); + REQUIRE( 0xffffff3f00000000 == l_t ); + + l_t.set_thresh_mce_soft( mss::mcbist::stop_conditions::DISABLE ); + REQUIRE( 0xffffffff00000000 == l_t ); + } { - l_t.set_thresh_mag_mce_hard( mss::mcbist::thresholds::DISABLE ); + l_t.set_thresh_mce_hard( 0 ); + REQUIRE( 0xffffffff00000000 == l_t ); + + l_t.set_thresh_mce_hard( 1 ); + REQUIRE( 0xfffffff000000000 == l_t ); + + l_t.set_thresh_mce_hard( 2 ); + REQUIRE( 0xfffffff100000000 == l_t ); + + l_t.set_thresh_mce_hard( 7 ); + REQUIRE( 0xfffffff200000000 == l_t ); + + l_t.set_thresh_mce_hard( mss::mcbist::stop_conditions::DISABLE ); REQUIRE( 0xffffffff00000000 == l_t ); } @@ -149,7 +226,7 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" } { - l_t.set_symbol_counter_mode( mss::mcbist::thresholds::DISABLE ); + l_t.set_symbol_counter_mode( mss::mcbist::stop_conditions::DISABLE ); REQUIRE( 0xfffffffffe000600 == l_t ); } @@ -222,11 +299,11 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" REQUIRE( 0x0000000000000081 == l_read ); } - // Load thresholds - default state (expecting 0's) + // Load thresholds - default state (expecting default threshold register state) { fapi2::buffer l_read; REQUIRE_FALSE( mss::getScom(i_target, MCBIST_MBSTRQ, l_read) ); - REQUIRE( 0x0 == l_read ); + REQUIRE( 0xffffffff00000000 == l_read ); } // Enable maint addressing mode - enabled by default in the mcbist::program ctor @@ -290,13 +367,15 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" { // Loading of patterns is tested in the mcbist unit test. - mss::mcbist::constraints l_const(memdiags::stop_conditions::NO_STOP_ON_ERROR, memdiags::thresholds()); + memdiags::stop_conditions l_stops; + mss::mcbist::constraints l_const(l_stops); // The addresses here are calculated so that we get a few iterations // of polling on an AWAN, but not so much that we run the risk of timing out mss::mcbist::address().get_range(l_const.iv_end_address); l_const.iv_end_address.set_column(0b111111); - memdiags::operation l_bob(i_target, mss::mcbist::read_subtest(), l_const); + memdiags::operation l_bob(i_target, mss::mcbist::read_subtest(), + l_const); REQUIRE_FALSE( l_bob.multi_port_init() ); REQUIRE_FALSE( l_bob.execute() ); @@ -315,11 +394,11 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" REQUIRE( 0x0000000000000081 == l_read ); } - // Load thresholds - default state (expecting 0's) + // Load thresholds - default state (expecting default threshold register state) { fapi2::buffer l_read; REQUIRE_FALSE( mss::getScom(i_target, MCBIST_MBSTRQ, l_read) ); - REQUIRE( 0x0 == l_read ); + REQUIRE( 0xffffffff00000000 == l_read ); } // Enable maint addressing mode - enabled by default in the mcbist::program ctor @@ -390,8 +469,7 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" l_start.set_bank_group(0); l_start.set_column(0); - REQUIRE_FALSE( memdiags::sf_read(i_target, mss::mcbist::stop_conditions::STOP_AFTER_ADDRESS, - mss::mcbist::thresholds(), l_start) ); + REQUIRE_FALSE( memdiags::sf_read(i_target, mss::mcbist::stop_conditions(), l_start) ); // Check the things we default to so that we have a canary in case the defaults change // Zero out cmd timebase - mcbist::program constructor does that for us. @@ -405,14 +483,14 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" { fapi2::buffer l_read; REQUIRE_FALSE( mss::getScom(i_target, MCBIST_MCBCFGQ, l_read) ); - REQUIRE( 0x00000000000000a9 == l_read ); + REQUIRE( 0x00000000000000a1 == l_read ); } - // Load thresholds - default state (expecting 0's) + // Load thresholds - default state (expecting default threshold register state) { fapi2::buffer l_read; REQUIRE_FALSE( mss::getScom(i_target, MCBIST_MBSTRQ, l_read) ); - REQUIRE( 0x0 == l_read ); + REQUIRE( 0xffffffff00000000 == l_read ); } // Enable maint addressing mode - enabled by default in the mcbist::program ctor @@ -447,7 +525,8 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" poll_parameters l_poll_parameters; bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters, - [&l_status](const size_t poll_remaining, const fapi2::buffer& stat_reg) -> bool + [&l_status](const size_t poll_remaining, + const fapi2::buffer& stat_reg) -> bool { FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining); l_status = stat_reg; @@ -488,7 +567,7 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" l_start.set_bank_group(0); l_start.set_column(0); - REQUIRE_FALSE( memdiags::background_scrub(i_target, memdiags::stop_conditions::NO_STOP_ON_ERROR, memdiags::thresholds(), + REQUIRE_FALSE( memdiags::background_scrub(i_target, memdiags::stop_conditions(), memdiags::speed::BG_SCRUB, l_start) ); // check the state of the mcbist engine @@ -581,13 +660,13 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" SECTION("Test targeted scrub") { // Test that passing in no-stop is a bug - REQUIRE( memdiags::targeted_scrub(i_target, memdiags::stop_conditions::DONT_STOP, memdiags::thresholds(), + REQUIRE( memdiags::targeted_scrub(i_target, memdiags::stop_conditions(), memdiags::speed::LUDICROUS, mss::mcbist::address(), - memdiags::end_boundary::MASTER_RANK) ); + memdiags::end_boundary::NONE) ); - REQUIRE_FALSE( memdiags::targeted_scrub(i_target, memdiags::stop_conditions::STOP_AFTER_RANK, memdiags::thresholds(), + REQUIRE_FALSE( memdiags::targeted_scrub(i_target, memdiags::stop_conditions(), memdiags::speed::LUDICROUS, mss::mcbist::address(), - memdiags::end_boundary::MASTER_RANK) ); + memdiags::end_boundary::STOP_AFTER_MASTER_RANK) ); // Make sure targeted scrub sets the FIR bit. More for verifying our actions than // anything else @@ -623,7 +702,7 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" { fapi2::buffer l_read; REQUIRE_FALSE( mss::getScom(i_target, MCBIST_MCBCFGQ, l_read) ); - REQUIRE( 0x0000000020000021 == l_read ); + REQUIRE( 0x0000000020000041 == l_read ); } } @@ -639,8 +718,8 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" l_start_address.get_range(l_end_address); l_start_address = l_end_address - 10; - memdiags::constraints l_const(memdiags::stop_conditions::STOP_AFTER_RANK, memdiags::thresholds(), - memdiags::speed::LUDICROUS, memdiags::end_boundary::MASTER_RANK, + memdiags::constraints l_const(memdiags::stop_conditions(), memdiags::speed::LUDICROUS, + memdiags::end_boundary::STOP_AFTER_MASTER_RANK, l_start_address); l_const.iv_end_address = l_end_address; @@ -666,7 +745,8 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" fapi2::buffer l_last_address; bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters, - [&l_status](const size_t poll_remaining, const fapi2::buffer& stat_reg) -> bool + [&l_status](const size_t poll_remaining, + const fapi2::buffer& stat_reg) -> bool { FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining); l_status = stat_reg; @@ -692,14 +772,14 @@ TEST_CASE_METHOD(mss::test::mcbist_target_test_fixture, "memdiags", "[memdiags]" } // We asked to stop at the end of a rank, so we should not be able to continue to the end of the rank - REQUIRE( memdiags::continue_cmd(i_target, memdiags::end_boundary::MRANK, memdiags::stop_conditions::STOP_AFTER_RANK) ); + REQUIRE( memdiags::continue_cmd(i_target, memdiags::end_boundary::STOP_AFTER_MASTER_RANK) ); // Continue but ask to stop at the end of the subtest - REQUIRE_FALSE( memdiags::continue_cmd(i_target, memdiags::end_boundary::NONE, - memdiags::stop_conditions::STOP_AFTER_SUBTEST) ); + REQUIRE_FALSE( memdiags::continue_cmd(i_target, memdiags::end_boundary::STOP_AFTER_SUBTEST) ); l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters, - [&l_status](const size_t poll_remaining, const fapi2::buffer& stat_reg) -> bool + [&l_status](const size_t poll_remaining, + const fapi2::buffer& stat_reg) -> bool { FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining); l_status = stat_reg; -- cgit v1.2.1