<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_tod_move_tod_to_tb.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//--------------------------------------------------------------------------
//
//
/// @file p9_tod_move_tod_to_tb.C
/// @brief Procedures to check if move_tod_to_tb works
///
// *HWP HWP Owner <NAME> <EMAIL>
// *HWP FW Owner: <NAME> <EMAIL>
// *HWP Team: Nest
// *HWP Level: 2
// *HWP Consumed by: None - this is a test for VBU
//
//--------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <p9_quad_scom_addresses_fld.H>
#include <p9_quad_scom_addresses.H>
#include <p9_tod_move_tod_to_tb.H>

extern "C"
{

//------------------------------------------------------------------------------
// Function definitions
//------------------------------------------------------------------------------

    //---------------------------------------------------------------------------------
    // NOTE: description in header
    //---------------------------------------------------------------------------------
    fapi2::ReturnCode p9_tod_move_tod_to_tb(const tod_topology_node* i_tod_node, const uint8_t i_thread_num,
                                            fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>* i_failingTodProc )
    {
        fapi2::ReturnCode rc;
        fapi2::buffer<uint64_t> data;
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>* target = i_tod_node->i_target;
        uint32_t tod_init_pending_count = 0; // Timeout counter for bits that are cleared by hardware
        uint64_t tfmr_state = 0;
        uint8_t l_core_id = 0x0;
        //bool is_mdmt = true;
        bool l_fused_core = false;

        FAPI_DBG("Start");

        //Get all the cores on this proc chip
        auto l_core_targets = target->getChildren<fapi2::TARGET_TYPE_CORE>(fapi2::TARGET_STATE_FUNCTIONAL);

        //Check if we are in fused mode
        if (l_core_targets.size() > 0)
        {
            FAPI_TRY(fapi2::getScom(l_core_targets[0], C_CORE_THREAD_STATE, data), "Error getting fused core register");

            if (data.getBit<C_CORE_THREAD_STATE_LPAR_FUSED_CORE_MODE>())
            {
                l_fused_core = true;
                FAPI_DBG("Fused mode enabled");
            }
            else
            {
                FAPI_DBG("Normal mode is enabled");
            }
        }

        for (auto coreTarget : l_core_targets)
        {
            //Only run this on even cores if we are in fused core mode
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, coreTarget, l_core_id), "Error getting ATTR_CHIP_UNIT_POS");

            if ((!l_fused_core) || (l_core_id % 2 == 0))
            {
                FAPI_DBG("Going to work on core %d", l_core_id);
                //-------Timebase Setup--------------
                //Read TFMR
                FAPI_TRY(p9_tod_utils_get_tfmr_reg(coreTarget, i_thread_num, data), "Could not read TFMR register");

                //Update TFMR bit (00:15) Timebase settings according to processor frequency
                data.insertFromRight((uint32_t)0xFF, TFMR_MAX_CYC_BET_STEPS, TFMR_MAX_CYC_BET_STEPS_LEN);
                data.insertFromRight(TFMR_N_CLKS_PER_STEP_4CLK, TFMR_N_CLKS_PER_STEP, TFMR_N_CLKS_PER_STEP_LEN);
                data.insertFromRight(TFMR_SYNC_BIT_SEL_16US, TFMR_SYNC_BIT_SEL, TFMR_SYNC_BIT_SEL_LEN);
                data.setBit<TFMR_TB_ECLIPZ>();

                FAPI_TRY(p9_tod_utils_set_tfmr_reg(coreTarget, i_thread_num, data),
                         "Could not write timebase settings according to processor frequency");

                tod_init_pending_count = 0;

                while(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
                {
                    FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY, P9_TOD_UTILS_SIM_CYCLE_DELAY), "fapiDelay error");
                    FAPI_TRY(p9_tod_utils_get_tfmr_reg(coreTarget, i_thread_num, data), "Could not read TFMR register for polling");
                    data.extract(tfmr_state, TFMR_STATE_START_BIT, TFMR_STATE_NUM_BITS, 60);

                    if (tfmr_state == TFMR_STATE_TB_RESET)
                    {
                        FAPI_DBG("TFMR in TB_RESET state");
                        break;
                    }

                    ++tod_init_pending_count;
                }

                FAPI_ASSERT(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                            fapi2::P9_TOD_INIT_TIMEOUT().set_TARGET(target).set_COUNT(tod_init_pending_count),
                            "TFMR state machine did not go to reset in time!");


                //-------Timebase load_tod_mode_tb(switch Timebase to "Not Set" state)
                //Update TFMR bit (16) = b'1' load_tod_mod_tb. This prepares the time facility logic to accept a new value for the 64-bit Timebase
                data.setBit<TFMR_LOAD_TOD_MOD_TB>();
                FAPI_TRY(p9_tod_utils_set_tfmr_reg(coreTarget, i_thread_num, data), "Could not load_tod_mod_tb");

                //Poll for TFMR bit (16) = b'0'. Hardware clears the bit when the operation is complete. A timeout is indicated by TFMR bit(54) = b'1'
                tod_init_pending_count = 0;

                while(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
                {
                    FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY, P9_TOD_UTILS_SIM_CYCLE_DELAY), "fapiDelay error");
                    FAPI_TRY(p9_tod_utils_get_tfmr_reg(coreTarget, i_thread_num, data), "Could not read TFMR register for polling");
                    data.extract(tfmr_state, TFMR_STATE_START_BIT, TFMR_STATE_NUM_BITS, 60);

                    if (!data.getBit<TFMR_LOAD_TOD_MOD_TB>() && (tfmr_state == TFMR_STATE_TB_NOT_SET))
                    {
                        FAPI_DBG("TFMR_LOAD_TOD_MOD cleared.");
                        break;
                    }

                    ++tod_init_pending_count;
                }

                FAPI_ASSERT(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                            fapi2::P9_TOD_INIT_TIMEOUT().set_TARGET(target).set_COUNT(tod_init_pending_count),
                            "TFMR_LOAD_TOD_MOD did not clear in time!");

                //-------TOD interrupt check----------------------
                //Read TFMR and check for TFMR(51) = b'0'. This indicates no interrupt pending from the TOD which means no STEP errors were detected, and the external TOD oscillator is operating properly.
                FAPI_TRY(p9_tod_utils_get_tfmr_reg(coreTarget, i_thread_num, data), "Could not read TFMR register to check bit 51");
                FAPI_ASSERT(!data.getBit<51>(), fapi2::P9_TOD_INIT_NOT_RUNNING(),
                            "STEP errors were detected or the external TOD oscillator is not operating properly");

                //------Move TOD value to Timebase---------
                //Update TFMR bit(18) = b'1' move_chip_tod_to_tb. This prepares the time facility logic to accept a new value after a SYNC boundary occurred
                FAPI_TRY(p9_tod_utils_get_tfmr_reg(coreTarget, i_thread_num, data), "Could not read TFMR to move_chip_tod_to_tb");
                data.setBit<TFMR_MOVE_CHIP_TOD_TO_TB>();
                FAPI_TRY(p9_tod_utils_set_tfmr_reg(coreTarget, i_thread_num, data), "Could not write TFMR to mvoe chip_tod_to_tb");

                //We don't check for TB_SYNC_WAIT since that state is fleeting

                tod_init_pending_count = 0;

                while(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
                {
                    FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY, P9_TOD_UTILS_SIM_CYCLE_DELAY), "fapiDelay error");
                    FAPI_TRY(p9_tod_utils_get_tfmr_reg(coreTarget, i_thread_num, data), "Could not read TFMR register for polling");
                    data.extract(tfmr_state, TFMR_STATE_START_BIT, TFMR_STATE_NUM_BITS, 60);

                    if (tfmr_state == TFMR_STATE_GET_TOD)
                    {
                        FAPI_DBG("TFMR in GET_TOD state");
                        break;
                    }

                    ++tod_init_pending_count;
                }

                FAPI_ASSERT(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                            fapi2::P9_TOD_INIT_TIMEOUT().set_TARGET(target).set_COUNT(tod_init_pending_count),
                            "TFMR state machine did not go to get_tod in time!");


                //Write TOD_MOVE_TOD_TO_TB_REG(@0x17)[00]=b'1'(move TOD to Timebase). The TOD transfers the TOD value to the Timebase after a SYNC boundary occurred. Note that TOD_TX_TTYPE_CTRL_REG(@0x27)[24:31] needs to be configured before issuing a TOD transfer to Timebase.The address of the PIB slave targeted by the TOD PIB master is configured as 0xNN0126a1 where NN is the configurable slave address specified in TOD_TX_TTYPE_CTRL_REG(@0x27)[24:31].
                data.flush<0>();
                //0x20 is the "base" chiplet number for all the cores that's why we add it to the core id
                l_core_id = l_core_id + 0x20;
                data.insertFromRight(l_core_id, 0, 8);

                //This will go the TOD_READ register (0x20010AA3) for the core that we are currently targeting
                data.insertFromRight(0x010AA310000000, 8, 56);
                FAPI_TRY(fapi2::putScom(*target, PERV_TOD_TX_TTYPE_CTRL_REG, data), "Could not write PERV_TOD_TX_TTYPE_CTRL_REG");

                data.flush<0>();
                data.setBit<0>();
                FAPI_TRY(fapi2::putScom(*target, PERV_TOD_MOVE_TOD_TO_TB_REG, data), "Could not write TOD_MOVE_TOD_TO_TB_REG");

                tod_init_pending_count = 0;

                while(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
                {
                    FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY, P9_TOD_UTILS_SIM_CYCLE_DELAY), "fapiDelay error");
                    FAPI_TRY(p9_tod_utils_get_tfmr_reg(coreTarget, i_thread_num, data), "Could not read TFMR register for polling");
                    data.extract(tfmr_state, TFMR_STATE_START_BIT, TFMR_STATE_NUM_BITS, 60);

                    if (tfmr_state == TFMR_STATE_TB_RUNNING)
                    {
                        FAPI_DBG("TFMR in TB_RUNNING state");
                        break;
                    }

                    ++tod_init_pending_count;
                }

                FAPI_ASSERT(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                            fapi2::P9_TOD_INIT_TIMEOUT().set_TARGET(target).set_COUNT(tod_init_pending_count),
                            "TFMR state machine did not go to TB_RUNNING in time!");

                tod_init_pending_count = 0;

                //Poll for TFMR bit(18) = b'0'. Hardware clears the bit when the operation is complete.
                while(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
                {
                    FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY, P9_TOD_UTILS_SIM_CYCLE_DELAY), "fapiDelay error");
                    FAPI_TRY(p9_tod_utils_get_tfmr_reg(coreTarget, i_thread_num, data), "Could not read TFMR");

                    if (!data.getBit<TFMR_MOVE_CHIP_TOD_TO_TB>())
                    {
                        FAPI_DBG("TFMR_MOVE_CHIP_TOD_TO_TB cleared.");
                        break;
                    }

                    ++tod_init_pending_count;
                }

                FAPI_ASSERT(tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                            fapi2::P9_TOD_INIT_TIMEOUT().set_TARGET(target).set_COUNT(tod_init_pending_count),
                            "TFMR_MOVE_CHIP_TOD_TO_TB did not clear in time!");
            }
        }

        // Finish configuring downstream nodes
        for (std::list<tod_topology_node*>::const_iterator child = (i_tod_node->i_children).begin();
             child != (i_tod_node->i_children).end();
             ++child)
        {
            tod_topology_node* tod_node = *child;
            FAPI_TRY(p9_tod_move_tod_to_tb(tod_node, i_thread_num, i_failingTodProc), "Failure configuring downstream node!");
        }


    fapi_try_exit:
        FAPI_DBG("Exiting...");
        return fapi2::current_err;
    }

    fapi2::ReturnCode p9_tod_utils_get_tfmr_reg(
        const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target,
        const uint8_t i_thread_num,
        fapi2::buffer<uint64_t>& o_tfmr_val)
    {
        // mark HWP entry
        FAPI_DBG("Entering ...\n");

        fapi2::buffer<uint64_t> data;
        fapi2::buffer<uint64_t> data2;

        //Setting SPR_MODE to thread number
        data.flush<0>().setBit<SPR_MODE_REG_MODE_SPRC_WR_EN>().setBit<SPR_MODE_REG_MODE_SPRC0_SEL>();
        data2.flush<0>();

        switch(i_thread_num)
        {
            case(0):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T0_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T0, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(1):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T1_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T1, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(2):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T2_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T2, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(3):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T3_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T3, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(4):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T4_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T4, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(5):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T5_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T5, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(6):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T6_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T6, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(7):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T7_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T7, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            default:
                FAPI_ASSERT(true, fapi2::P9_INVALID_THREAD_NUM().set_TARGET(i_target).set_THREADNUMBER(i_thread_num),
                            "Thread number error ");
        }

        FAPI_TRY(fapi2::putScom(i_target, C_SPR_MODE, data), "Error writing to EX_PERV_SPR_MODE");

        FAPI_TRY(fapi2::putScom(i_target, C_SCOMC, data2), "Error writing to EX_PERV_L0_SCOM_SPRC");

        //Reading SPRD for the thread's TMFR
        FAPI_TRY(fapi2::getScom(i_target, 0x20010A81, o_tfmr_val), "Error getting EX_PERV_SPRD_L0");
    fapi_try_exit:
        FAPI_DBG("Exiting...");
        return fapi2::current_err;
    }

    fapi2::ReturnCode p9_tod_utils_set_tfmr_reg(
        const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target,
        const uint8_t i_thread_num,
        fapi2::buffer<uint64_t>& i_tfmr_val)
    {
        // mark HWP entry
        FAPI_DBG("Entering ...\n");

        fapi2::buffer<uint64_t> data;
        fapi2::buffer<uint64_t> data2;

        //Setting SPR_MODE to thread number
        //Setting SPRC to thread's TMFR
        data.flush<0>().setBit<SPR_MODE_REG_MODE_SPRC_WR_EN>().setBit<SPR_MODE_REG_MODE_SPRC0_SEL>();
        data2.flush<0>();

        switch(i_thread_num)
        {
            case(0):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T0_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T0, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(1):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T1_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T1, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(2):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T2_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T2, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(3):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T3_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T3, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(4):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T4_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T4, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(5):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T5_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T5, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(6):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T6_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T6, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            case(7):
                data.setBit<SPR_MODE_REG_MODE_SPRC_T7_SEL>();
                data2.insertFromRight(SPRC_REG_SEL_TFMR_T7, SPRC_REG_SEL, SPRC_REG_SEL_LEN);
                break;

            default:
                FAPI_ASSERT(true, fapi2::P9_INVALID_THREAD_NUM().set_TARGET(i_target).set_THREADNUMBER(i_thread_num),
                            "Thread number error ");
                break;
        }

        FAPI_TRY(fapi2::putScom(i_target, C_SPR_MODE, data), "Error doing putscom to EX_PERV_SPR_MODE");

        FAPI_TRY(fapi2::putScom(i_target, C_SCOMC, data2), "Error doing putscom to EX_PERV_L0_SCOM_SPRC");

        //Writing SPRD to set the thread's TMFR
        FAPI_TRY(fapi2::putScom(i_target, 0x20010A81, i_tfmr_val), "Error doing putscom to EX_PERV_SPRD_L0");

    fapi_try_exit:
        FAPI_DBG("Exiting...");
        return fapi2::current_err;
    }


} // extern "C"<commit_msg>L3 update -- TOD HWPs<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_tod_move_tod_to_tb.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//--------------------------------------------------------------------------
//
//
/// @file p9_tod_move_tod_to_tb.C
/// @brief Procedures to check if move_tod_to_tb works
///
// *HWP HWP Owner: <NAME> <EMAIL>
// *HWP HWP Owner: <NAME> <EMAIL>
// *HWP FW Owner: <NAME> <EMAIL>
// *HWP Team: Nest
// *HWP Level: 3
// *HWP Consumed by: Cronus only
//
//--------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <p9_tod_move_tod_to_tb.H>


//------------------------------------------------------------------------------
// Function definitions
//------------------------------------------------------------------------------

/// @brief Sets the value in the TFMR register
/// @param[in] i_target P9 core unit target
/// @param[in] i_thread_num Thread number to target
/// @param[in] i_tfmr_val Value that will be put in the TFMR register
/// @return FAPI_RC_SUCCESS if TFMR write is successful else error
fapi2::ReturnCode p9_tod_utils_set_tfmr_reg(
    const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target,
    const uint8_t i_thread_num,
    fapi2::buffer<uint64_t>& i_tfmr_val)
{
    // mark HWP entry
    FAPI_DBG("Entering ...");

    // Setting SPR_MODE to thread number
    // Setting SPRC to thread's TMFR
    fapi2::buffer<uint64_t> l_spr_mode = 0;
    fapi2::buffer<uint64_t> l_scomc = 0;
    l_spr_mode.setBit<SPR_MODE_REG_MODE_SPRC_WR_EN>()
    .setBit<SPR_MODE_REG_MODE_SPRC0_SEL>();

    switch(i_thread_num)
    {
        case(0):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT0_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T0);
            break;

        case(1):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT1_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T1);
            break;

        case(2):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT2_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T2);
            break;

        case(3):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT3_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T3);
            break;

        case(4):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT4_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T4);
            break;

        case(5):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT5_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T5);
            break;

        case(6):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT6_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T6);
            break;

        case(7):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT7_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T7);
            break;

        default:
            FAPI_ASSERT(true,
                        fapi2::P9_TOD_MOVE_TOD_TO_TB_INVALID_THREAD_NUM()
                        .set_TARGET(i_target)
                        .set_THREAD_NUMBER(i_thread_num),
                        "Invaild thread number!");
    }

    FAPI_TRY(fapi2::putScom(i_target, C_SPR_MODE, l_spr_mode),
             "Error from putScom (C_SPR_MODE)!");

    FAPI_TRY(fapi2::putScom(i_target, C_SCOMC, l_scomc),
             "Error from putScom (C_SPRC)!");

    // Writing SPRD to set the thread's TMFR
    FAPI_TRY(fapi2::putScom(i_target, C_SCOMD, i_tfmr_val),
             "Error from putScom (C_SCOMD)!");

fapi_try_exit:
    FAPI_DBG("Exiting...");
    return fapi2::current_err;
}


/// @brief Gets the value in the TFMR register
/// @param[in] i_target P9 core unit target
/// @param[in] i_thread_num Thread number to target
/// @param[out] o_tfmr_val Value that is in the TFMR register
/// @return FAPI_RC_SUCCESS if TFMR read is successful else error
fapi2::ReturnCode p9_tod_utils_get_tfmr_reg(
    const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target,
    const uint8_t i_thread_num,
    fapi2::buffer<uint64_t>& o_tfmr_val)
{
    // mark HWP entry
    FAPI_DBG("Entering ...");

    // Setting SPR_MODE to thread number
    // Setting SPRC to thread's TMFR
    fapi2::buffer<uint64_t> l_spr_mode = 0;
    fapi2::buffer<uint64_t> l_scomc = 0;
    l_spr_mode.setBit<SPR_MODE_REG_MODE_SPRC_WR_EN>()
    .setBit<SPR_MODE_REG_MODE_SPRC0_SEL>();

    switch(i_thread_num)
    {
        case(0):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT0_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T0);
            break;

        case(1):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT1_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T1);
            break;

        case(2):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT2_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T2);
            break;

        case(3):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT3_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T3);
            break;

        case(4):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT4_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T4);
            break;

        case(5):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT5_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T5);
            break;

        case(6):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT6_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T6);
            break;

        case(7):
            l_spr_mode.setBit<C_SPR_MODE_MODEREG_SPRC_LT7_SEL>();
            l_scomc.insertFromRight<SPRC_REG_SEL, SPRC_REG_SEL_LEN>(SPRC_REG_SEL_TFMR_T7);
            break;

        default:
            FAPI_ASSERT(true,
                        fapi2::P9_TOD_MOVE_TOD_TO_TB_INVALID_THREAD_NUM()
                        .set_TARGET(i_target)
                        .set_THREAD_NUMBER(i_thread_num),
                        "Invaild thread number!");
    }

    FAPI_TRY(fapi2::putScom(i_target, C_SPR_MODE, l_spr_mode),
             "Error from putScom (C_SPR_MODE)!");

    FAPI_TRY(fapi2::putScom(i_target, C_SCOMC, l_scomc),
             "Error from putScom (C_SCOMC)!");

    // Reading SPRD for the thread's TMFR
    FAPI_TRY(fapi2::getScom(i_target,  C_SCOMD, o_tfmr_val),
             "Error from getScom (C_SCOMD)!");

fapi_try_exit:
    FAPI_DBG("Exiting...");
    return fapi2::current_err;
}


// NOTE: description in header
fapi2::ReturnCode p9_tod_move_tod_to_tb(
    const tod_topology_node* i_tod_node,
    const uint8_t i_thread_num,
    fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>* i_failingTodProc)
{
    fapi2::buffer<uint64_t> data;
    bool l_fused_core = false;

    FAPI_DBG("Start");

    // Get all the cores on this proc chip
    auto l_core_targets = i_tod_node->i_target->getChildren<fapi2::TARGET_TYPE_CORE>(
                              fapi2::TARGET_STATE_FUNCTIONAL);

    // Check if we are in fused mode
    if (l_core_targets.size() > 0)
    {
        fapi2::buffer<uint64_t> l_thread_state;
        FAPI_TRY(fapi2::getScom(l_core_targets[0],
                                C_CORE_THREAD_STATE,
                                l_thread_state),
                 "Error from getScom (C_CORE_THREAD_STATE)");

        if (l_thread_state.getBit<C_CORE_THREAD_STATE_LPAR_FUSED_CORE_MODE>())
        {
            l_fused_core = true;
            FAPI_DBG("Fused-core mode enabled");
        }
        else
        {
            l_fused_core = false;
            FAPI_DBG("Normal-core mode is enabled");
        }
    }

    for (auto l_core_target : l_core_targets)
    {
        uint8_t l_core_id = 0x0;
        fapi2::buffer<uint64_t> l_tfmr_reg;
        fapi2::buffer<uint64_t> l_tod_tx_ttype_ctrl_reg = 0;
        fapi2::buffer<uint64_t> l_move_tod_to_tb_reg = 0;
        uint64_t l_tfmr_state = 0;
        uint32_t l_tod_init_pending_count = 0;

        // Only run this on even cores if we are in fused core mode
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,
                               l_core_target,
                               l_core_id),
                 "Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS)!");

        if ((!l_fused_core) || (l_core_id % 2 == 0))
        {
            FAPI_DBG("Going to work on core %d", l_core_id);

            // -------Timebase Setup--------------
            // Read TFMR
            FAPI_TRY(p9_tod_utils_get_tfmr_reg(l_core_target,
                                               i_thread_num,
                                               l_tfmr_reg),
                     "Error from p9_tod_utils_get_tfmr_reg (setup for reset)");

            // Update TFMR bit (00:15) Timebase settings according to processor frequency
            l_tfmr_reg.setBit<CAPP_TFMR_MAX_CYC_BET_STEPS, CAPP_TFMR_MAX_CYC_BET_STEPS_LEN>()
            .insertFromRight<CAPP_TFMR_N_CLKS_PER_STEP, CAPP_TFMR_N_CLKS_PER_STEP_LEN>(TFMR_N_CLKS_PER_STEP_4CLK)
            .insertFromRight<CAPP_TFMR_SYNC_BIT_SEL, CAPP_TFMR_SYNC_BIT_SEL_LEN>(TFMR_SYNC_BIT_SEL_16US)
            .setBit<CAPP_TFMR_TB_ECLIPZ>();

            FAPI_TRY(p9_tod_utils_set_tfmr_reg(l_core_target,
                                               i_thread_num,
                                               l_tfmr_reg),
                     "Error from p9_tod_utils_set_tfmr_reg (setup for 'reset')");

            while (l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
            {
                FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY,
                                      P9_TOD_UTILS_SIM_CYCLE_DELAY),
                         "Error from delay");
                FAPI_TRY(p9_tod_utils_get_tfmr_reg(l_core_target,
                                                   i_thread_num,
                                                   l_tfmr_reg),
                         "Error from p9_tod_utils_get_tfmr_reg (poll for 'reset')");

                l_tfmr_reg.extractToRight<CAPP_TFMR_TBST_ENCODED,
                                          CAPP_TFMR_TBST_ENCODED_LEN>(l_tfmr_state);

                if (l_tfmr_state == TFMR_STATE_TB_RESET)
                {
                    FAPI_DBG("TFMR in TB_RESET state");
                    break;
                }

                ++l_tod_init_pending_count;
            }

            FAPI_ASSERT(l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                        fapi2::P9_TOD_MOVE_TOD_TO_TB_INIT_TIMEOUT()
                        .set_TARGET(*(i_tod_node->i_target))
                        .set_COUNT(l_tod_init_pending_count)
                        .set_TFMR_STATE(l_tfmr_state)
                        .set_TFMR_EXPECTED_STATE(TFMR_STATE_TB_RESET)
                        .set_TFMR_REG(l_tfmr_reg),
                        "Timeout waiting for TFMR state machine to reach 'reset' state!");

            // -------Timebase load_tod_mode_tb (switch TB to "Not Set" state)
            // Update TFMR bit (16) = b'1' load_tod_mod_tb.
            // This prepares the time facility logic to accept a new value for
            // the 64-bit Timebase
            l_tfmr_reg.setBit<CAPP_TFMR_LOAD_TOD_MOD>();
            FAPI_TRY(p9_tod_utils_set_tfmr_reg(l_core_target,
                                               i_thread_num,
                                               l_tfmr_reg),
                     "Error from p9_tod_utils_set_tfmr_reg (setup for 'not set')");

            // Poll for TFMR bit (16) = b'0'. Hardware clears the bit when the
            // operation is complete. A timeout is indicated by
            // TFMR bit(54) = b'1'
            l_tod_init_pending_count = 0;

            while (l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
            {
                FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY,
                                      P9_TOD_UTILS_SIM_CYCLE_DELAY),
                         "Error from delay");
                FAPI_TRY(p9_tod_utils_get_tfmr_reg(l_core_target,
                                                   i_thread_num,
                                                   l_tfmr_reg),
                         "Error from p9_tod_utils_get_tfmr_reg (poll for 'not set')");
                l_tfmr_reg.extract<CAPP_TFMR_TBST_ENCODED,
                                   CAPP_TFMR_TBST_ENCODED_LEN>(l_tfmr_state);

                if (!l_tfmr_reg.getBit<CAPP_TFMR_LOAD_TOD_MOD>() &&
                    (l_tfmr_state == TFMR_STATE_TB_NOT_SET))
                {
                    FAPI_DBG("TFMR_LOAD_TOD_MOD cleared.");
                    break;
                }

                ++l_tod_init_pending_count;
            }

            FAPI_ASSERT(l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                        fapi2::P9_TOD_MOVE_TOD_TO_TB_INIT_TIMEOUT()
                        .set_TARGET(*(i_tod_node->i_target))
                        .set_COUNT(l_tod_init_pending_count)
                        .set_TFMR_STATE(l_tfmr_state)
                        .set_TFMR_EXPECTED_STATE(TFMR_STATE_TB_NOT_SET)
                        .set_TFMR_REG(l_tfmr_reg),
                        "Timeout waiting for TFMR state machine to reach 'not set' state!");

            // -------TOD interrupt check----------------------
            // Read TFMR and check for TFMR(51) = b'0'. This indicates no
            // interrupt pending from the TOD which means no STEP errors were
            // detected, and the external TOD oscillator is operating properly.
            FAPI_TRY(p9_tod_utils_get_tfmr_reg(l_core_target,
                                               i_thread_num,
                                               l_tfmr_reg),
                     "Error from p9_tod_utils_get_tfmr_reg (interrupt check)");
            FAPI_ASSERT(!l_tfmr_reg.getBit<CAPP_TFMR_CHIP_TOD_INTERRUPT>(),
                        fapi2::P9_TOD_MOVE_TOD_TO_TB_INIT_ERROR()
                        .set_TARGET(*(i_tod_node->i_target))
                        .set_TFMR_REG(l_tfmr_reg),
                        "TOD interrupt detected!");

            // ------Move TOD value to Timebase---------
            // Update TFMR bit(18) = b'1' move_chip_tod_to_tb. This prepares the
            // time facility logic to accept a new value after a SYNC boundary
            // occurred
            FAPI_TRY(p9_tod_utils_get_tfmr_reg(l_core_target,
                                               i_thread_num,
                                               l_tfmr_reg),
                     "Error from p9_tod_utils_get_tfmr_reg (setup for 'get_tod')");
            l_tfmr_reg.setBit<CAPP_TFMR_MOVE_CHIP_TOD_TO_TB>();
            FAPI_TRY(p9_tod_utils_set_tfmr_reg(l_core_target,
                                               i_thread_num,
                                               l_tfmr_reg),
                     "Error from p9_tod_utils_set_tfmr_reg (setup for 'get_tod')");

            // We don't check for TB_SYNC_WAIT since that state is fleeting
            l_tod_init_pending_count = 0;

            while (l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
            {
                FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY,
                                      P9_TOD_UTILS_SIM_CYCLE_DELAY),
                         "Error from delay");
                FAPI_TRY(p9_tod_utils_get_tfmr_reg(l_core_target,
                                                   i_thread_num,
                                                   l_tfmr_reg),
                         "Error from p9_tod_utils_get_tfmr_reg (poll for 'get_tod')");
                l_tfmr_reg.extract<CAPP_TFMR_TBST_ENCODED,
                                   CAPP_TFMR_TBST_ENCODED_LEN>(l_tfmr_state);

                if (l_tfmr_state == TFMR_STATE_GET_TOD)
                {
                    FAPI_DBG("TFMR in GET_TOD state");
                    break;
                }

                ++l_tod_init_pending_count;
            }

            FAPI_ASSERT(l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                        fapi2::P9_TOD_MOVE_TOD_TO_TB_INIT_TIMEOUT()
                        .set_TARGET(*(i_tod_node->i_target))
                        .set_COUNT(l_tod_init_pending_count)
                        .set_TFMR_STATE(l_tfmr_state)
                        .set_TFMR_EXPECTED_STATE(TFMR_STATE_GET_TOD)
                        .set_TFMR_REG(l_tfmr_reg),
                        "Timeout waiting for TFMR state machine to reach 'get_tod' state!");

            // Write TOD_MOVE_TOD_TO_TB_REG(@0x17)[00]=b'1'. The TOD
            // transfers the TOD value to the Timebase after a SYNC boundary
            // occurred. Note that TOD_TX_TTYPE_CTRL_REG(@0x27)[24:31] needs to
            // be configured before issuing a TOD transfer to Timebase.
            // The address of the PIB slave targeted by the TOD PIB master is
            // configured as 0xNN0126a1 where NN is the configurable slave
            // address specified in TOD_TX_TTYPE_CTRL_REG(@0x27)[24:31].
            // add core unit position to 0x20 ("base" chiplet number for unit 0)
            l_core_id = l_core_id + 0x20;
            l_tod_tx_ttype_ctrl_reg.insertFromRight <
            PERV_TOD_TX_TTYPE_CTRL_REG_MOVE_TO_TB_CORE_ADDRESS,
            PERV_TOD_TX_TTYPE_CTRL_REG_MOVE_TO_TB_CORE_ID_LEN > (l_core_id);

            // This will go to the TOD_READ register (0x20010AA3) for the core
            // that we are currently targeting
            l_tod_tx_ttype_ctrl_reg |= PERV_TOD_TX_TTYPE_CTRL_REG_MASK_VALUE;
            FAPI_TRY(fapi2::putScom(*(i_tod_node->i_target),
                                    PERV_TOD_TX_TTYPE_CTRL_REG,
                                    l_tod_tx_ttype_ctrl_reg),
                     "Error from putScom (PERV_TOD_TX_TTYPE_CTRL_REG)!");

            l_move_tod_to_tb_reg.setBit<PERV_TOD_MOVE_TOD_TO_TB_REG_TRIGGER>();
            FAPI_TRY(fapi2::putScom(*(i_tod_node->i_target),
                                    PERV_TOD_MOVE_TOD_TO_TB_REG,
                                    l_move_tod_to_tb_reg),
                     "Error from putScom (PERV_TOD_MOVE_TOD_TO_TB_REG)!");

            l_tod_init_pending_count = 0;

            while (l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
            {
                FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY,
                                      P9_TOD_UTILS_SIM_CYCLE_DELAY),
                         "Error from delay");
                FAPI_TRY(p9_tod_utils_get_tfmr_reg(l_core_target,
                                                   i_thread_num,
                                                   l_tfmr_reg),
                         "Error from p9_tod_utils_get_tfmr_reg (poll for 'tod_running')");
                l_tfmr_reg.extract<CAPP_TFMR_TBST_ENCODED,
                                   CAPP_TFMR_TBST_ENCODED_LEN>(l_tfmr_state);

                if (l_tfmr_state == TFMR_STATE_TB_RUNNING)
                {
                    FAPI_DBG("TFMR in TB_RUNNING state");
                    break;
                }

                ++l_tod_init_pending_count;
            }

            FAPI_ASSERT(l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                        fapi2::P9_TOD_MOVE_TOD_TO_TB_INIT_TIMEOUT()
                        .set_TARGET(*(i_tod_node->i_target))
                        .set_COUNT(l_tod_init_pending_count)
                        .set_TFMR_STATE(l_tfmr_state)
                        .set_TFMR_EXPECTED_STATE(TFMR_STATE_TB_RUNNING)
                        .set_TFMR_REG(l_tfmr_reg),
                        "Timeout waiting for TFMR state machine to reach 'tb_running' state!");

            l_tod_init_pending_count = 0;

            // Poll for TFMR bit(18) = b'0'.
            // Hardware clears the bit when the operation is complete.
            while (l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT)
            {
                FAPI_TRY(fapi2::delay(P9_TOD_UTILS_HW_NS_DELAY,
                                      P9_TOD_UTILS_SIM_CYCLE_DELAY),
                         "Error from delay");
                FAPI_TRY(p9_tod_utils_get_tfmr_reg(l_core_target,
                                                   i_thread_num,
                                                   l_tfmr_reg),
                         "Error from p9_tod_utils_get_tfmr_reg (TOD to TB clear)");

                if (!l_tfmr_reg.getBit<CAPP_TFMR_MOVE_CHIP_TOD_TO_TB>())
                {
                    FAPI_DBG("TFMR_MOVE_CHIP_TOD_TO_TB cleared.");
                    break;
                }

                ++l_tod_init_pending_count;
            }

            FAPI_ASSERT(l_tod_init_pending_count < P9_TOD_UTIL_TIMEOUT_COUNT,
                        fapi2::P9_TOD_MOVE_TOD_TO_TB_INIT_TIMEOUT()
                        .set_TARGET(*(i_tod_node->i_target))
                        .set_COUNT(l_tod_init_pending_count)
                        .set_TFMR_STATE(l_tfmr_state)
                        .set_TFMR_EXPECTED_STATE(TFMR_STATE_TB_RUNNING)
                        .set_TFMR_REG(l_tfmr_reg),
                        "Timeout waiting for TOD to TB bit to clear!");
        }
    }

    // Finish configuring downstream nodes
    for (auto l_child = (i_tod_node->i_children).begin();
         l_child != (i_tod_node->i_children).end();
         ++l_child)
    {
        FAPI_TRY(p9_tod_move_tod_to_tb(*l_child, i_thread_num, i_failingTodProc),
                 "Failure configuring downstream node!");
    }

fapi_try_exit:
    FAPI_DBG("Exiting...");
    return fapi2::current_err;
}
{'fraction_non_alphanumeric': 0.1067877018520208, 'fraction_numerical': 0.0143463187665359, 'mean_word_length': 1.5848956490979837, 'pattern_counts': {'":': 0, '<': 151, '<?xml version=': 0, '>': 149, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 122, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '137557', 'n_tokens_mistral': 14556, 'n_tokens_neox': 13777, 'n_words': 2226}