<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/io/p9_io_xbus_clear_firs.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_io_xbus_clear_firs.C
/// @brief Clears I/O Firs
///-----------------------------------------------------------------------------
/// *HWP HWP Owner        : Chris Steffen <cwsteffen@us.ibm.com>
/// *HWP HWP Backup Owner : Gary Peterson <garyp@us.ibm.com>
/// *HWP FW Owner         : Jamie Knight <rjknight@us.ibm.com>
/// *HWP Team             : IO
/// *HWP Level            : 3
/// *HWP Consumed by      : FSP:HB
///-----------------------------------------------------------------------------
///
/// @verbatim
/// High-level procedure flow:
///
/// Clears I/O Xbus FIRs on the PHY Rx/Tx.
///
/// Clocks must be running.
///
/// @endverbatim
///----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//  Includes
//-----------------------------------------------------------------------------
#include <p9_io_xbus_clear_firs.H>
#include <p9_io_scom.H>
#include <p9_io_regs.H>

//-----------------------------------------------------------------------------
//  Definitions
//-----------------------------------------------------------------------------
fapi2::ReturnCode io_rx_fir_reset(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t&                                   i_clock_group );

fapi2::ReturnCode io_tx_fir_reset(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t&                                   i_clock_group );

/**
 * @brief Clears PHY Rx/Tx FIRs on the XBUS(EDI+) specified target.  The FIRs
 *   are cleared by toggling a rx & tx fir reset bit.
 * @param[in] i_target         FAPI2 Target
 * @param[in] i_clock_group    Clock Group
 * @retval ReturnCode
 */
fapi2::ReturnCode p9_io_xbus_clear_firs(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t&                                   i_clock_group )
{
    FAPI_IMP( "I/O Start Xbus Clear FIRs" );

    FAPI_TRY( io_tx_fir_reset( i_target, i_clock_group ), "Tx Reset Failed" );

    FAPI_TRY( io_rx_fir_reset( i_target, i_clock_group ), "Rx Reset Failed" );

fapi_try_exit:
    FAPI_IMP( "I/O End Xbus Clear FIRs" );
    return fapi2::current_err;
}

/**
 * @brief This function resets the Rx Firs on a EDI+ Xbus
 * @param[in] i_target       FAPI2 Target
 * @param[in] i_clock_group  Clock Group
 * @retval ReturnCode
 */
fapi2::ReturnCode io_rx_fir_reset(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t& i_clock_group)
{
    const uint8_t LANE_00 = 0;
    uint64_t l_data = 0;

    FAPI_TRY( io::read( EDIP_RX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
              "Reading Rx Fir Reg Failed");

    io::set (EDIP_RX_FIR_RESET, 0, l_data);
    FAPI_TRY(io::write( EDIP_RX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Rx Fir Reg Failed");

    io::set (EDIP_RX_FIR_RESET, 1, l_data);
    FAPI_TRY(io::write( EDIP_RX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Rx Fir Reg Failed");

    io::set (EDIP_RX_FIR_RESET, 0, l_data);
    FAPI_TRY(io::write( EDIP_RX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Rx Fir Reg Failed");

fapi_try_exit:
    return fapi2::current_err;
}

/**
 * @brief This function resets the Tx Firs on a EDI+ Xbus
 * @param[in] i_target       FAPI2 Target
 * @param[in] i_clock_group  Clock Group
 * @retval ReturnCode
 */
fapi2::ReturnCode io_tx_fir_reset(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t& i_clock_group)
{
    const uint8_t LANE_00 = 0;
    uint64_t l_data = 0;

    FAPI_TRY( io::read( EDIP_TX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
              "Reading Tx Fir Reg Failed");

    io::set (EDIP_TX_FIR_RESET, 0, l_data);
    FAPI_TRY(io::write( EDIP_TX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Tx Fir Reg Failed");

    io::set (EDIP_TX_FIR_RESET, 1, l_data);
    FAPI_TRY(io::write( EDIP_TX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Tx Fir Reg Failed");

    io::set (EDIP_TX_FIR_RESET, 0, l_data);
    FAPI_TRY(io::write( EDIP_TX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Tx Fir Reg Failed");

fapi_try_exit:
    return fapi2::current_err;
}
<commit_msg>Move Xbus Erepair FIR Clearing<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/io/p9_io_xbus_clear_firs.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_io_xbus_clear_firs.C
/// @brief Clears I/O Firs
///-----------------------------------------------------------------------------
/// *HWP HWP Owner        : Chris Steffen <cwsteffen@us.ibm.com>
/// *HWP HWP Backup Owner : Gary Peterson <garyp@us.ibm.com>
/// *HWP FW Owner         : Jamie Knight <rjknight@us.ibm.com>
/// *HWP Team             : IO
/// *HWP Level            : 3
/// *HWP Consumed by      : FSP:HB
///-----------------------------------------------------------------------------
///
/// @verbatim
/// High-level procedure flow:
///
/// Clears I/O Xbus FIRs on the PHY Rx/Tx.
///
/// Clocks must be running.
///
/// @endverbatim
///----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//  Includes
//-----------------------------------------------------------------------------
#include <p9_io_xbus_clear_firs.H>
#include <p9_io_xbus_read_erepair.H>
#include <p9_io_scom.H>
#include <p9_io_regs.H>

#include <p9_xbus_scom_addresses.H>
#include <p9_xbus_scom_addresses_fld.H>

//-----------------------------------------------------------------------------
//  Definitions
//-----------------------------------------------------------------------------
fapi2::ReturnCode io_rx_fir_reset(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t&                                   i_clock_group );

fapi2::ReturnCode io_tx_fir_reset(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t&                                   i_clock_group );

/**
 * @brief Clears PHY Rx/Tx FIRs on the XBUS(EDI+) specified target.  The FIRs
 *   are cleared by toggling a rx & tx fir reset bit.
 * @param[in] i_target         FAPI2 Target
 * @param[in] i_clock_group    Clock Group
 * @retval ReturnCode
 */
fapi2::ReturnCode p9_io_xbus_clear_firs(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t&                                   i_clock_group )
{
    FAPI_IMP( "I/O Start Xbus Clear FIRs" );

    FAPI_TRY( io_tx_fir_reset( i_target, i_clock_group ), "Tx Reset Failed" );

    FAPI_TRY( io_rx_fir_reset( i_target, i_clock_group ), "Rx Reset Failed" );

fapi_try_exit:
    FAPI_IMP( "I/O End Xbus Clear FIRs" );
    return fapi2::current_err;
}

/**
 * @brief This function resets the Rx Firs on a EDI+ Xbus
 * @param[in] i_target       FAPI2 Target
 * @param[in] i_clock_group  Clock Group
 * @retval ReturnCode
 */
fapi2::ReturnCode io_rx_fir_reset(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t& i_clock_group)
{
    const uint8_t LANE_00 = 0;
    uint64_t l_data = 0;

    FAPI_TRY( io::read( EDIP_RX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
              "Reading Rx Fir Reg Failed");

    io::set (EDIP_RX_FIR_RESET, 0, l_data);
    FAPI_TRY(io::write( EDIP_RX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Rx Fir Reg Failed");

    io::set (EDIP_RX_FIR_RESET, 1, l_data);
    FAPI_TRY(io::write( EDIP_RX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Rx Fir Reg Failed");

    io::set (EDIP_RX_FIR_RESET, 0, l_data);
    FAPI_TRY(io::write( EDIP_RX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Rx Fir Reg Failed");

fapi_try_exit:
    return fapi2::current_err;
}

/**
 * @brief This function resets the Tx Firs on a EDI+ Xbus
 * @param[in] i_target       FAPI2 Target
 * @param[in] i_clock_group  Clock Group
 * @retval ReturnCode
 */
fapi2::ReturnCode io_tx_fir_reset(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t& i_clock_group)
{
    const uint8_t LANE_00 = 0;
    uint64_t l_data = 0;

    FAPI_TRY( io::read( EDIP_TX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
              "Reading Tx Fir Reg Failed");

    io::set (EDIP_TX_FIR_RESET, 0, l_data);
    FAPI_TRY(io::write( EDIP_TX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Tx Fir Reg Failed");

    io::set (EDIP_TX_FIR_RESET, 1, l_data);
    FAPI_TRY(io::write( EDIP_TX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Tx Fir Reg Failed");

    io::set (EDIP_TX_FIR_RESET, 0, l_data);
    FAPI_TRY(io::write( EDIP_TX_FIR_RESET, i_target, i_clock_group, LANE_00, l_data ),
             "Writing Tx Fir Reg Failed");

fapi_try_exit:
    return fapi2::current_err;
}

/**
 * @brief This function reads the bad lane data of a EDI+ Xbus
 * @param[in]  i_target        FAPI2 Target
 * @param[in]  i_clock_group   Clock Group
 * @param[out] o_bad_lane_data Bit representation of each lane in the clock group
 * @retval ReturnCode
 */
fapi2::ReturnCode p9_io_xbus_get_bad_lane_data(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target,
    const uint8_t& i_clock_group,
    uint32_t& o_bad_lane_data)
{
    FAPI_IMP("I/O EDI+ Xbus Get Current Bad Lane Data :: Start");
    const uint8_t LN0    = 0;
    uint64_t      l_data = 0;
    std::vector<uint8_t> l_bad_lanes;

    FAPI_DBG("Read Bad Lane Vector 0 15");
    FAPI_TRY(io::read(EDIP_RX_LANE_BAD_VEC_0_15, i_target, i_clock_group, LN0, l_data),
             "rmw to edip_rx_lane_bad_vec_0_15 failed.");

    o_bad_lane_data = (io::get(EDIP_RX_LANE_BAD_VEC_0_15, l_data) << 8) & 0x00FFFF00;

    FAPI_DBG("Read Bad Lane Vector 16 23");
    FAPI_TRY(io::read(EDIP_RX_LANE_BAD_VEC_16_23, i_target, i_clock_group, LN0, l_data),
             "rmw to edip_rx_lane_bad_vec_16_23 failed.");

    o_bad_lane_data |= (io::get(EDIP_RX_LANE_BAD_VEC_16_23, l_data) & 0x000000FF);

    FAPI_DBG("Call xbus read erepair");
    FAPI_TRY(p9_io_xbus_read_erepair(i_target, i_clock_group, l_bad_lanes));

    for(auto bad_lane : l_bad_lanes)
    {
        o_bad_lane_data |= (0x1 << (23 - bad_lane));
    }

fapi_try_exit:
    FAPI_IMP("I/O EDI+ Xbus Get Current Bad Lane Data :: Exit");
    return fapi2::current_err;
}

/**
 * @brief Clears PHY Rx/Tx FIRs on the XBUS(EDI+) specified target.  The FIRs
 *   are cleared by toggling a rx & tx fir reset bit.
 * @param[in] i_target         FAPI2 Target
 * @retval ReturnCode
 */
fapi2::ReturnCode p9_io_xbus_erepair_cleanup(
    const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target)
{
    const uint8_t MAX_CLOCK_GROUPS = 2;
    bool l_clear_pb_spare_deployed = true;
    uint32_t l_grp0_pre_bad_lane_data = 0;
    uint32_t l_grp1_pre_bad_lane_data = 0;
    uint32_t l_pre_bad_lane_data   = 0;
    uint32_t l_post_bad_lane_data  = 0;
    FAPI_IMP("I/O Start Xbus Clear FIRs");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IO_XBUS_GRP0_PRE_BAD_LANE_DATA,
                           i_target, l_grp0_pre_bad_lane_data));

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IO_XBUS_GRP1_PRE_BAD_LANE_DATA,
                           i_target, l_grp1_pre_bad_lane_data));

    for (uint8_t l_group = 0; l_group < MAX_CLOCK_GROUPS; ++l_group)
    {
        // Get attribute of pre bad lane data
        FAPI_IMP("Get Pre Bad Lane Data");

        if (l_group == 0)
        {
            l_pre_bad_lane_data = l_grp0_pre_bad_lane_data;
        }
        else
        {
            l_pre_bad_lane_data = l_grp1_pre_bad_lane_data;
        }

        // Get current bad lane data
        //  - bad_lane_vector AND bad_lane_code
        FAPI_IMP("Get Current Bad Lane Data");
        FAPI_TRY(p9_io_xbus_get_bad_lane_data(i_target, l_group, l_post_bad_lane_data));

        FAPI_IMP("Compare Bad Lane Data");

        if (l_pre_bad_lane_data == l_post_bad_lane_data)
        {
            FAPI_DBG("I/O EDI+ Xbus Pre/Post Bad Lane Data Match");

            // If the entire bad lane vector equals 0, then we don't need to clear
            //   any firs.
            if (l_pre_bad_lane_data != 0)
            {
                FAPI_DBG("I/O EDI+ Xbus Clearing PG Firs");

                FAPI_TRY(io_tx_fir_reset(i_target, l_group), "Tx Reset Failed");
                FAPI_TRY(io_rx_fir_reset(i_target, l_group), "Rx Reset Failed");

            }
        }
        else
        {
            FAPI_DBG("Bad lane data does NOT match.");
            l_clear_pb_spare_deployed = false;
        }
    }

    // Clearing of the Spare Lane Deployed FIR when:
    // - the pre/post bad lane data match on both groups. (l_clear_pb_spare_deployed)
    // - AND if either groups have nonzero bad lane data
    if (l_clear_pb_spare_deployed &&
        ((l_grp0_pre_bad_lane_data != 0x0) || (l_grp1_pre_bad_lane_data != 0x0)) )
    {
        fapi2::buffer<uint64_t> l_data;
        fapi2::buffer<uint64_t> l_mask;

        // Clear BUS0_SPARE_DEPLOYED (Bit 9).
        l_data.clearBit<XBUS_1_FIR_REG_RX_BUS0_SPARE_DEPLOYED>();
        l_mask.setBit<XBUS_1_FIR_REG_RX_BUS0_SPARE_DEPLOYED>();
        FAPI_TRY(fapi2::putScomUnderMask(i_target, XBUS_FIR_REG, l_data, l_mask));

    }

fapi_try_exit:
    FAPI_IMP("I/O End Xbus Clear FIRs");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015-2016 WinT 3794 <http://wint3794.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <QDir>
#include <QApplication>

#include "dashboards.h"

#if defined Q_OS_WIN
#include <windows.h>
#define IS_64_BIT true
#if _WIN32
#undef  IS_64_BIT
#define IS_64_BIT GetProcAddress (GetModuleHandle (TEXT ("kernel32")), \
                                                         "IsWow64Process")
#endif
#define PF IS_64_BIT ? "C:/Program Files (x86)" : "C:/Program Files"
#endif

#if defined Q_OS_WIN
#define JAVA_OPEN "java -jar"
#elif defined Q_OS_LINUX
#define JAVA_OPEN "xdg-open"
#elif defined Q_OS_MAC
#define JAVA_OPEN "java -jar"
#endif

Dashboards::Dashboards()
{
    connect (qApp, &QApplication::aboutToQuit, this, &Dashboards::closeDashboard);
}

QStringList Dashboards::dashboardList()
{
    QStringList list;
    list.append (tr ("None"));
    list.append (tr ("SFX Dashboard"));
    list.append (tr ("SmartDashboard"));

#if defined Q_OS_WIN
    list.append (tr ("LabVIEW Dashboard"));
#endif

    return list;
}

void Dashboards::closeDashboard()
{
    m_process.close();
}

void Dashboards::openDashboard (int dashboard)
{
    QString path;
    QString home = QDir::homePath();

    switch (dashboard) {
    case kSFXDashboard:
        path = QString ("%1 \"%2/wpilib/tools/sfx.jar\"").arg (JAVA_OPEN, home);
        break;
    case kSmartDashboard:
        path = QString ("%1 \"%2/wpilib/tools/SmartDashboard.jar\"")
               .arg (JAVA_OPEN , home);
        break;
#if defined Q_OS_WIN
    case kLabVIEWDashboard:
        path = QString ("\"%1/FRC Dashboard/Dashboard.exe\"").arg (PF);
        break;
#endif
    default:
        path = "";
    }

    closeDashboard();
    m_process.start (path);
}
<commit_msg>Use "java -jar" to start dashboards on all platforms.<commit_after>/*
 * Copyright (c) 2015-2016 WinT 3794 <http://wint3794.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <QDir>
#include <QApplication>

#include "dashboards.h"

#if defined Q_OS_WIN
#include <windows.h>
#define IS_64_BIT true
#if _WIN32
#undef  IS_64_BIT
#define IS_64_BIT GetProcAddress (GetModuleHandle (TEXT ("kernel32")), \
                                                         "IsWow64Process")
#endif
#define PF IS_64_BIT ? "C:/Program Files (x86)" : "C:/Program Files"
#endif

#define JAVA_OPEN "java -jar"

Dashboards::Dashboards()
{
    connect (qApp, &QApplication::aboutToQuit, this, &Dashboards::closeDashboard);
}

QStringList Dashboards::dashboardList()
{
    QStringList list;
    list.append (tr ("None"));
    list.append (tr ("SFX Dashboard"));
    list.append (tr ("SmartDashboard"));

#if defined Q_OS_WIN
    list.append (tr ("LabVIEW Dashboard"));
#endif

    return list;
}

void Dashboards::closeDashboard()
{
    m_process.close();
}

void Dashboards::openDashboard (int dashboard)
{
    QString path;
    QString home = QDir::homePath();

    switch (dashboard) {
    case kSFXDashboard:
        path = QString ("%1 \"%2/wpilib/tools/sfx.jar\"").arg (JAVA_OPEN, home);
        break;
    case kSmartDashboard:
        path = QString ("%1 \"%2/wpilib/tools/SmartDashboard.jar\"")
               .arg (JAVA_OPEN , home);
        break;
#if defined Q_OS_WIN
    case kLabVIEWDashboard:
        path = QString ("\"%1/FRC Dashboard/Dashboard.exe\"").arg (PF);
        break;
#endif
    default:
        path = "";
    }

    closeDashboard();
    m_process.start (path);
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,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 phy_cntrl.C
/// @brief Subroutines for the PHY PC registers
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/phy/phy_cntrl.H>
#include <lib/utils/scom.H>
#include <lib/utils/c_str.H>
#include <lib/utils/index.H>

#include <lib/mss_attribute_accessors.H>

using fapi2::TARGET_TYPE_MCA;

namespace mss
{

// Definition of the PHY PC MR shadow registers
// indexed by [rank_pair][MR index]
const std::vector< std::vector<uint64_t> > pcTraits<TARGET_TYPE_MCA>::PC_MR_SHADOW_REGS =
{
    {
        MCA_DDRPHY_PC_MR0_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP0_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP0_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP0_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP1_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP1_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP1_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP2_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP2_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP2_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP3_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP3_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP3_P0,
    },
};

namespace pc
{

///
/// @brief Reset the PC CONFIG0 register
/// @param[in] i_target the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
fapi2::ReturnCode reset_config0(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    typedef pcTraits<TARGET_TYPE_MCA> TT;

    fapi2::buffer<uint64_t> l_data;

    l_data.setBit<TT::DDR4_CMD_SIG_REDUCTION>();
    l_data.setBit<TT::DDR4_VLEVEL_BANK_GROUP>();

    FAPI_TRY( write_config0(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Reset the PC CONFIG1 register
/// @param[in] i_target <the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
fapi2::ReturnCode reset_config1(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    typedef pcTraits<TARGET_TYPE_MCA> TT;

    // Static table of PHY config values for MEMORY_TYPE.
    // [EMPTY, RDIMM, CDIMM, or LRDIMM][EMPTY, DDR3 or DDR4]
    constexpr uint64_t memory_type[4][3] =
    {
        { 0, 0,     0     },  // Empty, never really used.
        { 0, 0b001, 0b101 },  // RDIMM
        { 0, 0b000, 0b000 },  // CDIMM bits, UDIMM enum (placeholder, never used on Nimbus)
        { 0, 0b011, 0b111 },  // LRDIMM
    };

    fapi2::buffer<uint64_t> l_data;

    uint8_t l_rlo = 0;
    uint8_t l_wlo = 0;
    uint8_t l_dram_gen[MAX_DIMM_PER_PORT]    = {0};
    uint8_t l_dimm_type[MAX_DIMM_PER_PORT]   = {0};
    uint8_t l_type_index = 0;
    uint8_t l_gen_index = 0;

    FAPI_TRY( mss::vpd_mr_dphy_rlo(i_target, l_rlo) );
    FAPI_TRY( mss::vpd_mr_dphy_wlo(i_target, l_wlo) );
    FAPI_TRY( mss::eff_dram_gen(i_target, &(l_dram_gen[0])) );
    FAPI_TRY( mss::eff_dimm_type(i_target, &(l_dimm_type[0])) );

    // There's no way to configure the PHY for more than one value. However, we don't know if there's
    // a DIMM in one slot, the other or double drop. So we do a little gyration here to make sure
    // we have one of the two values (and assume effective config caught a bad config)
    l_type_index = l_dimm_type[0] | l_dimm_type[1];
    l_gen_index = l_dram_gen[0] | l_dram_gen[1];

    // FOR NIMBUS PHY (as the protocol choice above is) BRS
    FAPI_TRY( mss::getScom(i_target, MCA_DDRPHY_PC_CONFIG1_P0, l_data) );

    l_data.insertFromRight<TT::MEMORY_TYPE, TT::MEMORY_TYPE_LEN>(memory_type[l_type_index][l_gen_index]);
    l_data.insertFromRight<TT::WRITE_LATENCY_OFFSET, TT::WRITE_LATENCY_OFFSET_LEN>(l_wlo);

    // Always set this bit. It forces the PHY to use A12 when figuring out latency. This makes sense in
    // all cases as A12 is 0 for non-3DS in MR0.
    l_data.setBit<TT::DDR4_LATENCY_SW>();

    // If we are 2N mode we add one to the RLO (see also Centaur initfile)
    l_data.insertFromRight<TT::READ_LATENCY_OFFSET, TT::READ_LATENCY_OFFSET_LEN>(
        mss::two_n_mode_helper(i_target) ? l_rlo + 1 : l_rlo);

    FAPI_TRY( write_config1(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace pc
} // close namespace mss
<commit_msg>Add c_str generic API and update makefiles<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,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 phy_cntrl.C
/// @brief Subroutines for the PHY PC registers
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/phy/phy_cntrl.H>
#include <lib/utils/scom.H>
#include <c_str.H>
#include <lib/utils/index.H>

#include <lib/mss_attribute_accessors.H>

using fapi2::TARGET_TYPE_MCA;

namespace mss
{

// Definition of the PHY PC MR shadow registers
// indexed by [rank_pair][MR index]
const std::vector< std::vector<uint64_t> > pcTraits<TARGET_TYPE_MCA>::PC_MR_SHADOW_REGS =
{
    {
        MCA_DDRPHY_PC_MR0_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP0_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP0_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP0_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP0_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP1_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP1_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP1_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP1_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP2_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP2_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP2_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP2_P0,
    },
    {
        MCA_DDRPHY_PC_MR0_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR1_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR2_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR3_PRI_RP3_P0,
        MCA_DDRPHY_PC_MR0_SEC_RP3_P0,
        MCA_DDRPHY_PC_MR1_SEC_RP3_P0,
        MCA_DDRPHY_PC_MR2_SEC_RP3_P0,
    },
};

namespace pc
{

///
/// @brief Reset the PC CONFIG0 register
/// @param[in] i_target the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
fapi2::ReturnCode reset_config0(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    typedef pcTraits<TARGET_TYPE_MCA> TT;

    fapi2::buffer<uint64_t> l_data;

    l_data.setBit<TT::DDR4_CMD_SIG_REDUCTION>();
    l_data.setBit<TT::DDR4_VLEVEL_BANK_GROUP>();

    FAPI_TRY( write_config0(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Reset the PC CONFIG1 register
/// @param[in] i_target <the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
fapi2::ReturnCode reset_config1(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    typedef pcTraits<TARGET_TYPE_MCA> TT;

    // Static table of PHY config values for MEMORY_TYPE.
    // [EMPTY, RDIMM, CDIMM, or LRDIMM][EMPTY, DDR3 or DDR4]
    constexpr uint64_t memory_type[4][3] =
    {
        { 0, 0,     0     },  // Empty, never really used.
        { 0, 0b001, 0b101 },  // RDIMM
        { 0, 0b000, 0b000 },  // CDIMM bits, UDIMM enum (placeholder, never used on Nimbus)
        { 0, 0b011, 0b111 },  // LRDIMM
    };

    fapi2::buffer<uint64_t> l_data;

    uint8_t l_rlo = 0;
    uint8_t l_wlo = 0;
    uint8_t l_dram_gen[MAX_DIMM_PER_PORT]    = {0};
    uint8_t l_dimm_type[MAX_DIMM_PER_PORT]   = {0};
    uint8_t l_type_index = 0;
    uint8_t l_gen_index = 0;

    FAPI_TRY( mss::vpd_mr_dphy_rlo(i_target, l_rlo) );
    FAPI_TRY( mss::vpd_mr_dphy_wlo(i_target, l_wlo) );
    FAPI_TRY( mss::eff_dram_gen(i_target, &(l_dram_gen[0])) );
    FAPI_TRY( mss::eff_dimm_type(i_target, &(l_dimm_type[0])) );

    // There's no way to configure the PHY for more than one value. However, we don't know if there's
    // a DIMM in one slot, the other or double drop. So we do a little gyration here to make sure
    // we have one of the two values (and assume effective config caught a bad config)
    l_type_index = l_dimm_type[0] | l_dimm_type[1];
    l_gen_index = l_dram_gen[0] | l_dram_gen[1];

    // FOR NIMBUS PHY (as the protocol choice above is) BRS
    FAPI_TRY( mss::getScom(i_target, MCA_DDRPHY_PC_CONFIG1_P0, l_data) );

    l_data.insertFromRight<TT::MEMORY_TYPE, TT::MEMORY_TYPE_LEN>(memory_type[l_type_index][l_gen_index]);
    l_data.insertFromRight<TT::WRITE_LATENCY_OFFSET, TT::WRITE_LATENCY_OFFSET_LEN>(l_wlo);

    // Always set this bit. It forces the PHY to use A12 when figuring out latency. This makes sense in
    // all cases as A12 is 0 for non-3DS in MR0.
    l_data.setBit<TT::DDR4_LATENCY_SW>();

    // If we are 2N mode we add one to the RLO (see also Centaur initfile)
    l_data.insertFromRight<TT::READ_LATENCY_OFFSET, TT::READ_LATENCY_OFFSET_LEN>(
        mss::two_n_mode_helper(i_target) ? l_rlo + 1 : l_rlo);

    FAPI_TRY( write_config1(i_target, l_data) );

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace pc
} // close namespace mss
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.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_mss_eff_config.C
/// @brief Command and Control for the memory subsystem - populate attributes
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <p9_mss_eff_config.H>

// std
#include <vector>

// fapi2
#include <fapi2.H>

// mss lib
#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
#include <lib/spd/spd_factory.H>
#include <generic/memory/lib/utils/pos.H>
#include <lib/utils/checker.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/shared/mss_kind.H>
#include <lib/dimm/eff_dimm.H>
#include <lib/eff_config/plug_rules.H>

///
/// @brief Configure the attributes for each controller
/// @param[in] i_target the controller (e.g., MCS)
/// @param[in] i_decode_spd_only options to set VPD and SPD attrs only
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
                                     const bool i_decode_spd_only )
{
    fapi2::ReturnCode l_rc;
    std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches;
    // Caches
    FAPI_TRY( mss::spd::populate_decoder_caches(i_target, l_factory_caches) );

    // Need to check dead load before we get the VPD.
    // MR and MT VPD depends on DIMM ranks and freaks out if it recieves 0 ranks from DIMM 0 and 1 or more ranks for DIMM 1
    FAPI_TRY( mss::plug_rule::check_dead_load (i_target) );
    FAPI_TRY( mss::plug_rule::empty_slot_zero (i_target) );

    // We need to decode the VPD. We don't do this in the ctor as we need
    // the rank information and for that we need the SPD caches (which we get when we populate the cache.)
    // However, we need to do the VPD decode before the others so that they might
    // be able to use VPD information to make decisions about setting up eff attributes.
    if( !i_decode_spd_only )
    {
        // Always set VPD attributes unless we enable the SPD_ONLY flag
        // Enables skipping VPD decoder when a valid VPD template isn't available
        FAPI_TRY( mss::eff_dimm::decode_vpd(i_target),
                  "Unable to decode VPD for %s", mss::c_str(i_target) );
    }

    for( const auto& l_cache : l_factory_caches )
    {
        std::shared_ptr<mss::eff_dimm> l_eff_dimm;

        FAPI_TRY( mss::eff_dimm::eff_dimm_factory( l_cache, l_eff_dimm));

        FAPI_TRY( l_eff_dimm->dram_mfg_id() );
        FAPI_TRY( l_eff_dimm->dram_width() );
        FAPI_TRY( l_eff_dimm->dram_density() );
        FAPI_TRY( l_eff_dimm->ranks_per_dimm() );
        FAPI_TRY( l_eff_dimm->prim_die_count() );
        FAPI_TRY( l_eff_dimm->primary_stack_type() );
        FAPI_TRY( l_eff_dimm->dimm_size() );
        FAPI_TRY( l_eff_dimm->hybrid_memory_type() );
        FAPI_TRY( l_eff_dimm->dram_trefi() );
        FAPI_TRY( l_eff_dimm->dram_trfc() );
        FAPI_TRY( l_eff_dimm->dram_trfc_dlr() );
        FAPI_TRY( l_eff_dimm->rcd_mirror_mode() );
        FAPI_TRY( l_eff_dimm->dram_bank_bits() );
        FAPI_TRY( l_eff_dimm->dram_row_bits() );
        FAPI_TRY( l_eff_dimm->dram_dqs_time() );
        FAPI_TRY( l_eff_dimm->dram_tccd_l() );
        FAPI_TRY( l_eff_dimm->dimm_rc00() );
        FAPI_TRY( l_eff_dimm->dimm_rc01() );
        FAPI_TRY( l_eff_dimm->dimm_rc02() );
        FAPI_TRY( l_eff_dimm->dimm_rc03() );
        FAPI_TRY( l_eff_dimm->dimm_rc04() );
        FAPI_TRY( l_eff_dimm->dimm_rc05() );
        FAPI_TRY( l_eff_dimm->dimm_rc06_07() );
        FAPI_TRY( l_eff_dimm->dimm_rc08() );
        FAPI_TRY( l_eff_dimm->dimm_rc09() );
        FAPI_TRY( l_eff_dimm->dimm_rc0a() );
        FAPI_TRY( l_eff_dimm->dimm_rc0b() );
        FAPI_TRY( l_eff_dimm->dimm_rc0c() );
        FAPI_TRY( l_eff_dimm->dimm_rc0d() );
        FAPI_TRY( l_eff_dimm->dimm_rc0e() );
        FAPI_TRY( l_eff_dimm->dimm_rc0f() );
        FAPI_TRY( l_eff_dimm->dimm_rc1x() );
        FAPI_TRY( l_eff_dimm->dimm_rc2x() );
        FAPI_TRY( l_eff_dimm->dimm_rc3x() );
        FAPI_TRY( l_eff_dimm->dimm_rc4x() );
        FAPI_TRY( l_eff_dimm->dimm_rc5x() );
        FAPI_TRY( l_eff_dimm->dimm_rc6x() );
        FAPI_TRY( l_eff_dimm->dimm_rc7x() );
        FAPI_TRY( l_eff_dimm->dimm_rc8x() );
        FAPI_TRY( l_eff_dimm->dimm_rc9x() );
        FAPI_TRY( l_eff_dimm->dimm_rcax() );
        FAPI_TRY( l_eff_dimm->dimm_rcbx() );
        FAPI_TRY( l_eff_dimm->dram_twr() );
        FAPI_TRY( l_eff_dimm->read_burst_type() );
        FAPI_TRY( l_eff_dimm->dram_tm() );
        FAPI_TRY( l_eff_dimm->dram_cwl() );
        FAPI_TRY( l_eff_dimm->dram_lpasr() );
        FAPI_TRY( l_eff_dimm->dll_enable() );
        FAPI_TRY( l_eff_dimm->dll_reset() );
        FAPI_TRY( l_eff_dimm->write_level_enable() );
        FAPI_TRY( l_eff_dimm->output_buffer() );
        FAPI_TRY( l_eff_dimm->vref_dq_train_value() );
        FAPI_TRY( l_eff_dimm->vref_dq_train_range() );
        FAPI_TRY( l_eff_dimm->vref_dq_train_enable() );
        FAPI_TRY( l_eff_dimm->ca_parity_latency() );
        FAPI_TRY( l_eff_dimm->ca_parity_error_status() );
        FAPI_TRY( l_eff_dimm->ca_parity() );
        FAPI_TRY( l_eff_dimm->crc_error_clear() );
        FAPI_TRY( l_eff_dimm->odt_input_buffer() );
        FAPI_TRY( l_eff_dimm->post_package_repair() );
        FAPI_TRY( l_eff_dimm->read_preamble_train() );
        FAPI_TRY( l_eff_dimm->read_preamble() );
        FAPI_TRY( l_eff_dimm->write_preamble() );
        FAPI_TRY( l_eff_dimm->self_refresh_abort() );
        FAPI_TRY( l_eff_dimm->cs_to_cmd_addr_latency() );
        FAPI_TRY( l_eff_dimm->internal_vref_monitor() );
        FAPI_TRY( l_eff_dimm->max_powerdown_mode() );
        FAPI_TRY( l_eff_dimm->mpr_read_format() );
        FAPI_TRY( l_eff_dimm->temp_readout() );
        FAPI_TRY( l_eff_dimm->crc_wr_latency() );
        FAPI_TRY( l_eff_dimm->per_dram_addressability() );
        FAPI_TRY( l_eff_dimm->geardown_mode() );
        FAPI_TRY( l_eff_dimm->mpr_page() );
        FAPI_TRY( l_eff_dimm->mpr_mode() );
        FAPI_TRY( l_eff_dimm->write_crc() );
        FAPI_TRY( l_eff_dimm->zqcal_interval() );
        FAPI_TRY( l_eff_dimm->memcal_interval() );
        FAPI_TRY( l_eff_dimm->dram_trp() );
        FAPI_TRY( l_eff_dimm->dram_trcd() );
        FAPI_TRY( l_eff_dimm->dram_trc() );
        FAPI_TRY( l_eff_dimm->dram_twtr_l() );
        FAPI_TRY( l_eff_dimm->dram_twtr_s() );
        FAPI_TRY( l_eff_dimm->dram_trrd_s() );
        FAPI_TRY( l_eff_dimm->dram_trrd_l() );
        FAPI_TRY( l_eff_dimm->dram_trrd_dlr() );
        FAPI_TRY( l_eff_dimm->dram_tfaw() );
        FAPI_TRY( l_eff_dimm->dram_tfaw_dlr() );
        FAPI_TRY( l_eff_dimm->dram_tras() );
        FAPI_TRY( l_eff_dimm->dram_trtp() );
        FAPI_TRY( l_eff_dimm->read_dbi() );
        FAPI_TRY( l_eff_dimm->write_dbi() );
        FAPI_TRY( l_eff_dimm->additive_latency() );
        FAPI_TRY( l_eff_dimm->data_mask() );
        FAPI_TRY( l_eff_dimm->dimm_bc00());
        FAPI_TRY( l_eff_dimm->dimm_bc01());
        FAPI_TRY( l_eff_dimm->dimm_bc02());
        FAPI_TRY( l_eff_dimm->dimm_bc03());
        FAPI_TRY( l_eff_dimm->dimm_bc04());
        FAPI_TRY( l_eff_dimm->dimm_bc05());
        FAPI_TRY( l_eff_dimm->dimm_bc07());
        FAPI_TRY( l_eff_dimm->dimm_bc08());
        FAPI_TRY( l_eff_dimm->dimm_bc09());
        FAPI_TRY( l_eff_dimm->dimm_bc0a());
        FAPI_TRY( l_eff_dimm->dimm_bc0b());
        FAPI_TRY( l_eff_dimm->dimm_bc0c());
        FAPI_TRY( l_eff_dimm->dimm_bc0d());
        FAPI_TRY( l_eff_dimm->dimm_bc0e());
        FAPI_TRY( l_eff_dimm->dimm_bc0f());
        FAPI_TRY( l_eff_dimm->dram_rtt_nom () );
        FAPI_TRY( l_eff_dimm->dram_rtt_wr  () );
        FAPI_TRY( l_eff_dimm->dram_rtt_park() );
        FAPI_TRY(  l_eff_dimm->phy_seq_refresh() );

        // Sets up the calibration steps
        FAPI_TRY( l_eff_dimm->cal_step_enable() );
        FAPI_TRY( l_eff_dimm->rdvref_enable_bit() );

        //Let's do some checking
        FAPI_TRY( mss::check::temp_refresh_mode());
    }// dimm

    // Check plug rules. We check the MCS, and this will iterate down to children as needed.
    FAPI_TRY( mss::plug_rule::enforce_plug_rules(i_target) );

fapi_try_exit:
    return fapi2::current_err;
}
<commit_msg>Add in RCD attributes for DD2 debug<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.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_mss_eff_config.C
/// @brief Command and Control for the memory subsystem - populate attributes
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <p9_mss_eff_config.H>

// std
#include <vector>

// fapi2
#include <fapi2.H>

// mss lib
#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
#include <lib/spd/spd_factory.H>
#include <generic/memory/lib/utils/pos.H>
#include <lib/utils/checker.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/shared/mss_kind.H>
#include <lib/dimm/eff_dimm.H>
#include <lib/eff_config/plug_rules.H>

///
/// @brief Configure the attributes for each controller
/// @param[in] i_target the controller (e.g., MCS)
/// @param[in] i_decode_spd_only options to set VPD and SPD attrs only
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
                                     const bool i_decode_spd_only )
{
    fapi2::ReturnCode l_rc;
    std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches;
    // Caches
    FAPI_TRY( mss::spd::populate_decoder_caches(i_target, l_factory_caches) );

    // Need to check dead load before we get the VPD.
    // MR and MT VPD depends on DIMM ranks and freaks out if it recieves 0 ranks from DIMM 0 and 1 or more ranks for DIMM 1
    FAPI_TRY( mss::plug_rule::check_dead_load (i_target) );
    FAPI_TRY( mss::plug_rule::empty_slot_zero (i_target) );

    // We need to decode the VPD. We don't do this in the ctor as we need
    // the rank information and for that we need the SPD caches (which we get when we populate the cache.)
    // However, we need to do the VPD decode before the others so that they might
    // be able to use VPD information to make decisions about setting up eff attributes.
    if( !i_decode_spd_only )
    {
        // Always set VPD attributes unless we enable the SPD_ONLY flag
        // Enables skipping VPD decoder when a valid VPD template isn't available
        FAPI_TRY( mss::eff_dimm::decode_vpd(i_target),
                  "Unable to decode VPD for %s", mss::c_str(i_target) );
    }

    for( const auto& l_cache : l_factory_caches )
    {

        std::shared_ptr<mss::eff_dimm> l_eff_dimm;

        FAPI_TRY( mss::eff_dimm::eff_dimm_factory( l_cache, l_eff_dimm));
        FAPI_INF("%s Running eff_config", mss::c_str(l_cache->iv_target) );

        FAPI_TRY( l_eff_dimm->rcd_mfg_id() );
        FAPI_TRY( l_eff_dimm->register_type() );
        FAPI_TRY( l_eff_dimm->register_rev() );
        FAPI_TRY( l_eff_dimm->dram_mfg_id() );
        FAPI_TRY( l_eff_dimm->dram_width() );
        FAPI_TRY( l_eff_dimm->dram_density() );
        FAPI_TRY( l_eff_dimm->ranks_per_dimm() );
        FAPI_TRY( l_eff_dimm->prim_die_count() );
        FAPI_TRY( l_eff_dimm->primary_stack_type() );
        FAPI_TRY( l_eff_dimm->dimm_size() );
        FAPI_TRY( l_eff_dimm->hybrid_memory_type() );
        FAPI_TRY( l_eff_dimm->dram_trefi() );
        FAPI_TRY( l_eff_dimm->dram_trfc() );
        FAPI_TRY( l_eff_dimm->dram_trfc_dlr() );
        FAPI_TRY( l_eff_dimm->rcd_mirror_mode() );
        FAPI_TRY( l_eff_dimm->dram_bank_bits() );
        FAPI_TRY( l_eff_dimm->dram_row_bits() );
        FAPI_TRY( l_eff_dimm->dram_dqs_time() );
        FAPI_TRY( l_eff_dimm->dram_tccd_l() );
        FAPI_TRY( l_eff_dimm->dimm_rc00() );
        FAPI_TRY( l_eff_dimm->dimm_rc01() );
        FAPI_TRY( l_eff_dimm->dimm_rc02() );
        FAPI_TRY( l_eff_dimm->dimm_rc03() );
        FAPI_TRY( l_eff_dimm->dimm_rc04() );
        FAPI_TRY( l_eff_dimm->dimm_rc05() );
        FAPI_TRY( l_eff_dimm->dimm_rc06_07() );
        FAPI_TRY( l_eff_dimm->dimm_rc08() );
        FAPI_TRY( l_eff_dimm->dimm_rc09() );
        FAPI_TRY( l_eff_dimm->dimm_rc0a() );
        FAPI_TRY( l_eff_dimm->dimm_rc0b() );
        FAPI_TRY( l_eff_dimm->dimm_rc0c() );
        FAPI_TRY( l_eff_dimm->dimm_rc0d() );
        FAPI_TRY( l_eff_dimm->dimm_rc0e() );
        FAPI_TRY( l_eff_dimm->dimm_rc0f() );
        FAPI_TRY( l_eff_dimm->dimm_rc1x() );
        FAPI_TRY( l_eff_dimm->dimm_rc2x() );
        FAPI_TRY( l_eff_dimm->dimm_rc3x() );
        FAPI_TRY( l_eff_dimm->dimm_rc4x() );
        FAPI_TRY( l_eff_dimm->dimm_rc5x() );
        FAPI_TRY( l_eff_dimm->dimm_rc6x() );
        FAPI_TRY( l_eff_dimm->dimm_rc7x() );
        FAPI_TRY( l_eff_dimm->dimm_rc8x() );
        FAPI_TRY( l_eff_dimm->dimm_rc9x() );
        FAPI_TRY( l_eff_dimm->dimm_rcax() );
        FAPI_TRY( l_eff_dimm->dimm_rcbx() );
        FAPI_TRY( l_eff_dimm->dram_twr() );
        FAPI_TRY( l_eff_dimm->read_burst_type() );
        FAPI_TRY( l_eff_dimm->dram_tm() );
        FAPI_TRY( l_eff_dimm->dram_cwl() );
        FAPI_TRY( l_eff_dimm->dram_lpasr() );
        FAPI_TRY( l_eff_dimm->dll_enable() );
        FAPI_TRY( l_eff_dimm->dll_reset() );
        FAPI_TRY( l_eff_dimm->write_level_enable() );
        FAPI_TRY( l_eff_dimm->output_buffer() );
        FAPI_TRY( l_eff_dimm->vref_dq_train_value() );
        FAPI_TRY( l_eff_dimm->vref_dq_train_range() );
        FAPI_TRY( l_eff_dimm->vref_dq_train_enable() );
        FAPI_TRY( l_eff_dimm->ca_parity_latency() );
        FAPI_TRY( l_eff_dimm->ca_parity_error_status() );
        FAPI_TRY( l_eff_dimm->ca_parity() );
        FAPI_TRY( l_eff_dimm->crc_error_clear() );
        FAPI_TRY( l_eff_dimm->odt_input_buffer() );
        FAPI_TRY( l_eff_dimm->post_package_repair() );
        FAPI_TRY( l_eff_dimm->read_preamble_train() );
        FAPI_TRY( l_eff_dimm->read_preamble() );
        FAPI_TRY( l_eff_dimm->write_preamble() );
        FAPI_TRY( l_eff_dimm->self_refresh_abort() );
        FAPI_TRY( l_eff_dimm->cs_to_cmd_addr_latency() );
        FAPI_TRY( l_eff_dimm->internal_vref_monitor() );
        FAPI_TRY( l_eff_dimm->max_powerdown_mode() );
        FAPI_TRY( l_eff_dimm->mpr_read_format() );
        FAPI_TRY( l_eff_dimm->temp_readout() );
        FAPI_TRY( l_eff_dimm->crc_wr_latency() );
        FAPI_TRY( l_eff_dimm->per_dram_addressability() );
        FAPI_TRY( l_eff_dimm->geardown_mode() );
        FAPI_TRY( l_eff_dimm->mpr_page() );
        FAPI_TRY( l_eff_dimm->mpr_mode() );
        FAPI_TRY( l_eff_dimm->write_crc() );
        FAPI_TRY( l_eff_dimm->zqcal_interval() );
        FAPI_TRY( l_eff_dimm->memcal_interval() );
        FAPI_TRY( l_eff_dimm->dram_trp() );
        FAPI_TRY( l_eff_dimm->dram_trcd() );
        FAPI_TRY( l_eff_dimm->dram_trc() );
        FAPI_TRY( l_eff_dimm->dram_twtr_l() );
        FAPI_TRY( l_eff_dimm->dram_twtr_s() );
        FAPI_TRY( l_eff_dimm->dram_trrd_s() );
        FAPI_TRY( l_eff_dimm->dram_trrd_l() );
        FAPI_TRY( l_eff_dimm->dram_trrd_dlr() );
        FAPI_TRY( l_eff_dimm->dram_tfaw() );
        FAPI_TRY( l_eff_dimm->dram_tfaw_dlr() );
        FAPI_TRY( l_eff_dimm->dram_tras() );
        FAPI_TRY( l_eff_dimm->dram_trtp() );
        FAPI_TRY( l_eff_dimm->read_dbi() );
        FAPI_TRY( l_eff_dimm->write_dbi() );
        FAPI_TRY( l_eff_dimm->additive_latency() );
        FAPI_TRY( l_eff_dimm->data_mask() );
        FAPI_TRY( l_eff_dimm->dimm_bc00());
        FAPI_TRY( l_eff_dimm->dimm_bc01());
        FAPI_TRY( l_eff_dimm->dimm_bc02());
        FAPI_TRY( l_eff_dimm->dimm_bc03());
        FAPI_TRY( l_eff_dimm->dimm_bc04());
        FAPI_TRY( l_eff_dimm->dimm_bc05());
        FAPI_TRY( l_eff_dimm->dimm_bc07());
        FAPI_TRY( l_eff_dimm->dimm_bc08());
        FAPI_TRY( l_eff_dimm->dimm_bc09());
        FAPI_TRY( l_eff_dimm->dimm_bc0a());
        FAPI_TRY( l_eff_dimm->dimm_bc0b());
        FAPI_TRY( l_eff_dimm->dimm_bc0c());
        FAPI_TRY( l_eff_dimm->dimm_bc0d());
        FAPI_TRY( l_eff_dimm->dimm_bc0e());
        FAPI_TRY( l_eff_dimm->dimm_bc0f());
        FAPI_TRY( l_eff_dimm->dram_rtt_nom () );
        FAPI_TRY( l_eff_dimm->dram_rtt_wr  () );
        FAPI_TRY( l_eff_dimm->dram_rtt_park() );
        FAPI_TRY(  l_eff_dimm->phy_seq_refresh() );

        // Sets up the calibration steps
        FAPI_TRY( l_eff_dimm->cal_step_enable() );
        FAPI_TRY( l_eff_dimm->rdvref_enable_bit() );

        //Let's do some checking
        FAPI_TRY( mss::check::temp_refresh_mode());
    }// dimm

    // Check plug rules. We check the MCS, and this will iterate down to children as needed.
    FAPI_TRY( mss::plug_rule::enforce_plug_rules(i_target) );

fapi_try_exit:
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_update_ec_eq_state.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_update_ec_eq_state.H
/// @brief Update the "permanent" multicast groups  reflect any additional
///          deconfigured by Hostboot
///
// *HWP HWP Owner: Amit Kumar <akumar3@us.ibm.com>
// *HWP Backup HWP Owner: Greg Still <stillgs@us.ibm.com>
// *HWP FW Owner: Sangeetha T S <sangeet2@in.ibm.com>
// *HWP Team: PM
// *HWP Level: 1
// *HWP Consumed by: SBE
///
///
///
/// High-level procedure flow:
/// @verbatim
///   Update the "permanent" multicast groups  reflect any additional
///        deconfiguration by Hostboot
///   Use the functional state to find all good cores
///   Write the good core and quad mask into OCC CCSR and QCSR respectively
///         These become the "master record " of the enabled cores/quad in
///         the system for runtime
/// @endverbatim

// -----------------------------------------------------------------------------
//  Includes
// -----------------------------------------------------------------------------
#include "p9_update_ec_eq_state.H"

// -----------------------------------------------------------------------------
//  Function prototypes
// -----------------------------------------------------------------------------

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

// See .H for documentation
fapi2::ReturnCode p9_update_ec_eq_state(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_IMP("p9_update_ec_eq_state start");

    FAPI_INF("p9_update_ec_eq_state end");

    return fapi2::current_err;
} // END p9_update_ec_eq_state
<commit_msg>p9_update_ec_eq_state Level 2<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_update_ec_eq_state.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_update_ec_eq_state.H
/// @brief Update the "permanent" multicast groups  reflect any additional
///          deconfigured by Hostboot
///
// *HWP HWP Owner: Amit Kumar <akumar3@us.ibm.com>
// *HWP Backup HWP Owner: Greg Still <stillgs@us.ibm.com>
// *HWP FW Owner: Sangeetha T S <sangeet2@in.ibm.com>
// *HWP Team: PM
// *HWP Level: 2
// *HWP Consumed by: SBE
///
///
///
/// High-level procedure flow:
/// @verbatim
///  - Update the "permanent" multicast groups  reflect any additional
///        deconfiguration by Hostboot.
///     - MC group 0 (using MC register #1) - All good chiplets (deal with EC
//          and EQ chiplets)
///     - MC group 1 (using EC MC register @2)  - All good cores (EC only)
///  - Use the functional state to find all good cores
///  -Write the good core and quad mask into OCC CCSR and QCSR respectively
///         These become the "master record " of the enabled cores/quad in
///         the system for runtime
/// @endverbatim

// -----------------------------------------------------------------------------
//  Includes
// -----------------------------------------------------------------------------
#include "p9_update_ec_eq_state.H"

// -----------------------------------------------------------------------------
//  Function prototypes
// -----------------------------------------------------------------------------
static fapi2::ReturnCode update_ec_config(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target);

static fapi2::ReturnCode update_eq_config(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target);

// -----------------------------------------------------------------------------
//  Constants
// -----------------------------------------------------------------------------
static const uint8_t CORE_CHIPLET_START     = 0x20;
static const uint8_t CORE_CHIPLET_COUNT     = 24;

// See .H for documentation
fapi2::ReturnCode p9_update_ec_eq_state(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_IMP("> p9_update_ec_eq_state");

    FAPI_TRY(update_ec_config(i_target),
             "Error update_core_config detected");

    FAPI_TRY(update_eq_config(i_target),
             "Error update_cache_config detected");

fapi_try_exit:
    FAPI_INF("< p9_update_ec_eq_state");

    return fapi2::current_err;
} // END p9_update_ec_eq_state

/// @brief Update multicast groups and the CCSR for cores
///
/// @param[in]     i_target   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
static fapi2::ReturnCode update_ec_config(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_INF("> update_core_config...");

    uint8_t l_present_core_unit_pos;
    uint8_t l_functional_core_unit_pos;
    fapi2::buffer<uint64_t> l_core_config = 0;

    auto l_core_present_vector =
        i_target.getChildren<fapi2::TARGET_TYPE_CORE>
        (fapi2::TARGET_STATE_PRESENT);

    auto l_core_functional_vector =
        i_target.getChildren<fapi2::TARGET_TYPE_CORE>
        (fapi2::TARGET_STATE_FUNCTIONAL);

    FAPI_INF("  Number of present cores = %d; Number of functional cores = %d",
             l_core_present_vector.size(),
             l_core_functional_vector.size());

    // For each present core,  set multicast groups and the CCSR
    for (auto core_present_it : l_core_present_vector)
    {
        bool b_core_functional = false;

        FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS,
                                core_present_it,
                                l_present_core_unit_pos));
        FAPI_DBG("  Checking if present EC %d is functional",
                 l_present_core_unit_pos);

        for (auto core_functional_it : l_core_functional_vector)
        {
            FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS,
                                    core_functional_it,
                                    l_functional_core_unit_pos));
            FAPI_DBG("  Functional EC %d",
                     l_functional_core_unit_pos);

            if (l_functional_core_unit_pos == l_present_core_unit_pos)
            {

                // Set this core into the multicast groups.  These should already
                // be set but we won't assume anything

                // Setting into ALL chiplets group (multicast group 0) using
                // MULTICAST_GROUP_1 register
                FAPI_INF("  Setting EC %d into MC group 0 (All chiplets)",
                         l_present_core_unit_pos);
                FAPI_TRY(fapi2::putScom(core_functional_it, C_MULTICAST_GROUP_1,
                                        p9UpdateECEQ::MCGR0_CNFG_SETTINGS));

                // Setting into good core group (multicast group 1) using
                // MULTICAST_GROUP_2 register in the EC chiplets
                FAPI_INF("  Setting EC %d into MC group 1 (All core chiplets)",
                         l_present_core_unit_pos);
                FAPI_TRY(fapi2::putScom(core_functional_it, C_MULTICAST_GROUP_2,
                                        p9UpdateECEQ::MCGR1_CNFG_SETTINGS));

                // Set the appropriate bit in the Core Configuration Status
                // Register buffer
                FAPI_INF("  Setting EC %d as good in value to be written to CCSR",
                         l_present_core_unit_pos);
                l_core_config.setBit(l_present_core_unit_pos);

                b_core_functional = true;

                break;
            }
        }

        // If not functional, clear the core chiplet out of all multicast groups
        // As the chiplet is not functional, it can only addressed with the chip
        // target, not a core target
        if (!b_core_functional)
        {

            // Clearing from the ALL chiplets group (multicast group 0) using
            // MULTICAST_GROUP_1 register
            FAPI_INF("  Removing EC %d from MC group 0 (All chiplets)",
                     l_present_core_unit_pos);

            uint32_t address = C_MULTICAST_GROUP_1 +
                               0x01000000 * l_present_core_unit_pos;
            FAPI_TRY(fapi2::putScom(i_target, address,
                                    p9UpdateECEQ::MCGR_CLEAR_CNFG_SETTINGS));

            // Clearing from the good cores (multicast group 1) using
            // MULTICAST_GROUP_2 register
            FAPI_INF("  Removing EC %d from MC group 1 (All core chiplets)",
                     l_present_core_unit_pos);
            address = C_MULTICAST_GROUP_2 +
                      0x01000000 * l_present_core_unit_pos;
            FAPI_TRY(fapi2::putScom(i_target, address,
                                    p9UpdateECEQ::MCGR_CLEAR_CNFG_SETTINGS));

            // The Core Configuration Status Register buffer bit is already clear

        }
    }

    // Write the recalculated OCC Core Configuration Status Register
    FAPI_INF("  Writing OCC CCSR");
    FAPI_TRY(fapi2::putScom(i_target, PU_OCB_OCI_CCSR_SCOM2, l_core_config),
             "Error writing to CCSR");

fapi_try_exit:
    FAPI_INF("< update_core_config...");
    return fapi2::current_err;

}

/// @brief Update multicast groups and the QCSR for caches
///
/// @param[in]     i_target   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
static fapi2::ReturnCode update_eq_config(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_INF("> update_cache_config...");

    uint8_t l_present_eq_unit_pos;
    uint8_t l_present_ex_unit_pos;
    uint8_t l_functional_eq_unit_pos;
    uint8_t l_functional_ex_unit_pos;
    fapi2::buffer<uint64_t> l_ex_config = 0;

    auto l_eq_present_vector =
        i_target.getChildren<fapi2::TARGET_TYPE_EQ>
        (fapi2::TARGET_STATE_PRESENT);

    auto l_eq_functional_vector =
        i_target.getChildren<fapi2::TARGET_TYPE_EQ>
        (fapi2::TARGET_STATE_FUNCTIONAL);

    auto l_ex_present_vector =
        i_target.getChildren<fapi2::TARGET_TYPE_EX>
        (fapi2::TARGET_STATE_PRESENT);

    auto l_ex_functional_vector =
        i_target.getChildren<fapi2::TARGET_TYPE_EX>
        (fapi2::TARGET_STATE_FUNCTIONAL);

    FAPI_INF("  Number of present cache chiplets = %d; Number of functional cache chiplets = %d",
             l_eq_present_vector.size(),
             l_eq_functional_vector.size());

    FAPI_INF("  Number of functional EX regions = %d",
             l_ex_functional_vector.size());

    // For each functinal EQ,  set the multicast groups to match (including
    // removal of the non-functional ones from all groups)
    for (auto eq_present_it : l_eq_present_vector)
    {
        bool b_eq_functional = false;

        FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS,
                                eq_present_it,
                                l_present_eq_unit_pos));
        FAPI_DBG("  Checking if present EQ %d is functional)",
                 l_present_eq_unit_pos);

        for (auto eq_functional_it : l_eq_functional_vector)
        {

            FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS,
                                    eq_functional_it,
                                    l_functional_eq_unit_pos));

            if (l_functional_eq_unit_pos == l_present_eq_unit_pos)
            {

                // Setting into ALL chiplets group (multicast group 0) using
                // MULTICAST_GROUP_1 register
                FAPI_INF("  Setting EQ %d into MC group 0 (All chiplets)",
                         l_functional_eq_unit_pos);
                FAPI_TRY(fapi2::putScom(eq_functional_it, EQ_MULTICAST_GROUP_1,
                                        p9UpdateECEQ::MCGR0_CNFG_SETTINGS));

                b_eq_functional = true;

            }
        }

        // If not functional, clear the eq chiplet out of all multicast groups
        // As the chiplet is not functional, it can only addressed with the chip
        // target, not an EQ target
        if (!b_eq_functional)
        {

            // Clearing from the ALL chiplets group (multicast group 0) using
            // MULTICAST_GROUP_1 register
            FAPI_INF("  Remove EQ %d from MC group 0 (All chiplets)",
                     l_present_eq_unit_pos);
            uint32_t address = EQ_MULTICAST_GROUP_1 +
                               0x01000000 * l_present_eq_unit_pos;
            FAPI_DBG("  address = 0x%X", address);
            FAPI_TRY(fapi2::putScom(i_target, address,
                                    p9UpdateECEQ::MCGR_CLEAR_CNFG_SETTINGS));

        }
    }

    // For each present EX,  set the QCSR
    // This is done last so that hardware is accurate in the event of errors.
    for (auto ex_present_it : l_ex_present_vector)
    {
        FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS,
                                ex_present_it,
                                l_present_ex_unit_pos));

        for (auto ex_functional_it : l_ex_functional_vector)
        {

            FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS,
                                    ex_functional_it,
                                    l_functional_ex_unit_pos));

            if (l_functional_ex_unit_pos == l_present_ex_unit_pos)
            {

                // Set the bit in the buffer to written to the hardware
                FAPI_INF("  Setting EX %d as good in value to be written to QCSR",
                         l_present_ex_unit_pos);
                l_ex_config.setBit(l_present_ex_unit_pos);

            }
        }
    }

    // Write the recalculated OCC Quad Configuration Status Register
    FAPI_INF("  Writing OCC QCSR");
    FAPI_TRY(fapi2::putScom(i_target, PU_OCB_OCI_QCSR_SCOM2, l_ex_config),
             "Error writing to CCSR");

fapi_try_exit:
    FAPI_INF("< update_cache_config");
    return fapi2::current_err;

} // END p9_update_ec_eq_state
<|endoftext|>


<commit_before>#ifndef AMGCL_COARSENING_SMOOTHED_AGGREGATION_HPP
#define AMGCL_COARSENING_SMOOTHED_AGGREGATION_HPP

/*
The MIT License

Copyright (c) 2012-2018 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/coarsening/smoothed_aggregation.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Smoothed aggregation coarsening scheme.
 */

#ifdef _OPENMP
#  include <omp.h>
#endif

#include <boost/tuple/tuple.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>

#include <amgcl/backend/builtin.hpp>
#include <amgcl/coarsening/detail/galerkin.hpp>
#include <amgcl/coarsening/pointwise_aggregates.hpp>
#include <amgcl/coarsening/tentative_prolongation.hpp>
#include <amgcl/util.hpp>

namespace amgcl {
namespace coarsening {

/// Smoothed aggregation coarsening.
/**
 * \ingroup coarsening
 * \sa \cite Vanek1996
 */
template <class Backend>
struct smoothed_aggregation {
    typedef pointwise_aggregates Aggregates;

    /// Coarsening parameters
    struct params {
        /// Aggregation parameters.
        Aggregates::params aggr;

        /// Near nullspace parameters.
        nullspace_params nullspace;

        /// Relaxation factor.
        /**
         * Used as a scaling for the damping factor omega.
         * When estimate_spectral_radius is set, then
         *   omega = relax * (4/3) / rho.
         * Otherwise
         *   omega = relax * (2/3).
         *
         * Piecewise constant prolongation \f$\tilde P\f$ from non-smoothed
         * aggregation is improved by a smoothing to get the final prolongation
         * matrix \f$P\f$. Simple Jacobi smoother is used here, giving the
         * prolongation matrix
         * \f[P = \left( I - \omega D^{-1} A^F \right) \tilde P.\f]
         * Here \f$A^F = (a_{ij}^F)\f$ is the filtered matrix given by
         * \f[
         * a_{ij}^F =
         * \begin{cases}
         * a_{ij} \quad \text{if} \; j \in N_i\\
         * 0 \quad \text{otherwise}
         * \end{cases}, \quad \text{if}\; i \neq j,
         * \quad a_{ii}^F = a_{ii} - \sum\limits_{j=1,j\neq i}^n
         * \left(a_{ij} - a_{ij}^F \right),
         * \f]
         * where \f$N_i\f$ is the set of variables, strongly coupled to
         * variable \f$i\f$, and \f$D\f$ denotes the diagonal of \f$A^F\f$.
         */
        float relax;

        // Use power iterations to estimate the matrix spectral radius.
        // This usually improves convergence rate and results in faster solves,
        // but costs some time during setup.
        bool estimate_spectral_radius;

        // Number of power iterations to apply for the spectral radius
        // estimation.
        int power_iters;

        params() : relax(1.0f), estimate_spectral_radius(true), power_iters(5) { }

        params(const boost::property_tree::ptree &p)
            : AMGCL_PARAMS_IMPORT_CHILD(p, aggr),
              AMGCL_PARAMS_IMPORT_CHILD(p, nullspace),
              AMGCL_PARAMS_IMPORT_VALUE(p, relax),
              AMGCL_PARAMS_IMPORT_VALUE(p, estimate_spectral_radius),
              AMGCL_PARAMS_IMPORT_VALUE(p, power_iters)
        {
            AMGCL_PARAMS_CHECK(p, (aggr)(nullspace)(relax)(estimate_spectral_radius)(power_iters));
        }

        void get(boost::property_tree::ptree &p, const std::string &path) const {
            AMGCL_PARAMS_EXPORT_CHILD(p, path, aggr);
            AMGCL_PARAMS_EXPORT_CHILD(p, path, nullspace);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, relax);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, estimate_spectral_radius);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, power_iters);
        }
    } prm;

    smoothed_aggregation(const params &prm = params()) : prm(prm) {}

    /// \copydoc amgcl::coarsening::aggregation::transfer_operators
    template <class Matrix>
    boost::tuple< boost::shared_ptr<Matrix>, boost::shared_ptr<Matrix> >
    transfer_operators(const Matrix &A) {
        typedef typename backend::value_type<Matrix>::type value_type;
        typedef typename math::scalar_of<value_type>::type scalar_type;

        const size_t n = rows(A);

        AMGCL_TIC("aggregates");
        Aggregates aggr(A, prm.aggr, prm.nullspace.cols);
        prm.aggr.eps_strong *= 0.5;
        AMGCL_TOC("aggregates");

        AMGCL_TIC("interpolation");
        boost::shared_ptr<Matrix> P_tent = tentative_prolongation<Matrix>(
                n, aggr.count, aggr.id, prm.nullspace, prm.aggr.block_size
                );

        boost::shared_ptr<Matrix> P = boost::make_shared<Matrix>();
        P->set_size(rows(*P_tent), cols(*P_tent), true);

        scalar_type omega = prm.relax;
        if (prm.estimate_spectral_radius) {
            omega *= static_cast<scalar_type>(4.0/3) / spectral_radius(A, prm.power_iters);
        } else {
            omega *= static_cast<scalar_type>(2.0/3);
        }

#pragma omp parallel
        {
            std::vector<ptrdiff_t> marker(P->ncols, -1);

            // Count number of entries in P.
#pragma omp for
            for(ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(n); ++i) {
                for(ptrdiff_t ja = A.ptr[i], ea = A.ptr[i+1]; ja < ea; ++ja) {
                    ptrdiff_t ca = A.col[ja];

                    // Skip weak off-diagonal connections.
                    if (ca != i && !aggr.strong_connection[ja])
                        continue;

                    for(ptrdiff_t jp = P_tent->ptr[ca], ep = P_tent->ptr[ca+1]; jp < ep; ++jp) {
                        ptrdiff_t cp = P_tent->col[jp];

                        if (marker[cp] != i) {
                            marker[cp] = i;
                            ++( P->ptr[i + 1] );
                        }
                    }
                }
            }
        }

        P->scan_row_sizes();
        P->set_nonzeros();

#pragma omp parallel
        {
            std::vector<ptrdiff_t> marker(P->ncols, -1);

            // Fill the interpolation matrix.
#pragma omp for
            for(ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(n); ++i) {

                // Diagonal of the filtered matrix is the original matrix
                // diagonal minus its weak connections.
                value_type dia = math::zero<value_type>();
                for(ptrdiff_t j = A.ptr[i], e = A.ptr[i+1]; j < e; ++j) {
                    if (A.col[j] == i || !aggr.strong_connection[j])
                        dia += A.val[j];
                }
                dia = -omega * math::inverse(dia);

                ptrdiff_t row_beg = P->ptr[i];
                ptrdiff_t row_end = row_beg;
                for(ptrdiff_t ja = A.ptr[i], ea = A.ptr[i + 1]; ja < ea; ++ja) {
                    ptrdiff_t ca = A.col[ja];

                    // Skip weak off-diagonal connections.
                    if (ca != i && !aggr.strong_connection[ja]) continue;

                    value_type va = (ca == i)
                        ? static_cast<value_type>(static_cast<scalar_type>(1 - omega) * math::identity<value_type>())
                        : dia * A.val[ja]);

                    for(ptrdiff_t jp = P_tent->ptr[ca], ep = P_tent->ptr[ca+1]; jp < ep; ++jp) {
                        ptrdiff_t cp = P_tent->col[jp];
                        value_type vp = P_tent->val[jp];

                        if (marker[cp] < row_beg) {
                            marker[cp] = row_end;
                            P->col[row_end] = cp;
                            P->val[row_end] = va * vp;
                            ++row_end;
                        } else {
                            P->val[ marker[cp] ] += va * vp;
                        }
                    }
                }
            }
        }
        AMGCL_TOC("interpolation");

        if (prm.nullspace.cols > 0)
            prm.aggr.block_size = prm.nullspace.cols;

        return boost::make_tuple(P, transpose(*P));
    }

    /// \copydoc amgcl::coarsening::aggregation::coarse_operator
    template <class Matrix>
    boost::shared_ptr<Matrix>
    coarse_operator(const Matrix &A, const Matrix &P, const Matrix &R) const {
        return detail::galerkin(A, P, R);
    }

    // Uses power iteration to estimate spectral readius of the matrix,
    // scaled by its inverse diagonal.
    template <class Matrix>
    static
    typename math::scalar_of<typename backend::value_type<Matrix>::type>::type
    spectral_radius(const Matrix &A, int power_iters)
    {
        typedef typename backend::value_type<Matrix>::type   value_type;
        typedef typename math::rhs_of<value_type>::type      rhs_type;
        typedef typename math::scalar_of<value_type>::type   scalar_type;

        const ptrdiff_t n = backend::rows(A);

        backend::numa_vector<value_type> D(n, false);
        backend::numa_vector<rhs_type>   b0(n, false), b1(n, false);

        // Fill the initial vector with random values.
        // Also extract the inverted matrix diagonal values.
        scalar_type b0_norm = 0;
#pragma omp parallel
        {
#ifdef _OPENMP
            int tid = omp_get_thread_num();
#else
            int tid = 0;
#endif
            boost::random::mt11213b rng(tid);
            boost::random::uniform_real_distribution<scalar_type> rnd(-1, 1);

            scalar_type loc_norm = 0;

#pragma omp for nowait
            for(ptrdiff_t i = 0; i < n; ++i) {
                rhs_type v = math::constant<rhs_type>(rnd(rng));

                b0[i] = v;
                loc_norm += math::norm(math::inner_product(v,v));

                for(ptrdiff_t j = A.ptr[i], e = A.ptr[i+1]; j < e; ++j) {
                    if (A.col[j] == i) {
                        D[i] = math::inverse(A.val[j]);
                        break;
                    }
                }
            }

#pragma omp critical
            b0_norm += loc_norm;
        }

        // Normalize b0
        b0_norm = 1 / sqrt(b0_norm);
#pragma omp parallel for
        for(ptrdiff_t i = 0; i < n; ++i) {
            b0[i] = b0_norm * b0[i];
        }

        scalar_type radius = 1;

        for(int iter = 0; iter < power_iters;) {
            // b1 = (D * A) * b0
            // b1_norm = ||b1||
            // radius = <b1,b0>
            scalar_type b1_norm = 0;
            radius = 0;
#pragma omp parallel
            {
                scalar_type loc_norm = 0;
                scalar_type loc_radi = 0;

#pragma omp for nowait
                for(ptrdiff_t i = 0; i < n; ++i) {
                    rhs_type s = math::zero<rhs_type>();

                    for(ptrdiff_t j = A.ptr[i], e = A.ptr[i+1]; j < e; ++j) {
                        s += A.val[j] * b0[A.col[j]];
                    }

                    s = D[i] * s;

                    loc_norm += math::norm(math::inner_product(s, s));
                    loc_radi += math::norm(math::inner_product(s, b0[i]));

                    b1[i] = s;
                }

#pragma omp critical
                {
                    b1_norm += loc_norm;
                    radius  += loc_radi;
                }
            }

            if (++iter < power_iters) {
                // b0 = b1 / b1_norm
                b1_norm = 1 / sqrt(b1_norm);
#pragma omp parallel for
                for(ptrdiff_t i = 0; i < n; ++i) {
                    b0[i] = b1_norm * b1[i];
                }
            }
        }

        return radius < 0 ? static_cast<scalar_type>(2) : radius;
    }
};

} // namespace coarsening
} // namespace amgcl

#endif
<commit_msg>Missing paren<commit_after>#ifndef AMGCL_COARSENING_SMOOTHED_AGGREGATION_HPP
#define AMGCL_COARSENING_SMOOTHED_AGGREGATION_HPP

/*
The MIT License

Copyright (c) 2012-2018 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/coarsening/smoothed_aggregation.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Smoothed aggregation coarsening scheme.
 */

#ifdef _OPENMP
#  include <omp.h>
#endif

#include <boost/tuple/tuple.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>

#include <amgcl/backend/builtin.hpp>
#include <amgcl/coarsening/detail/galerkin.hpp>
#include <amgcl/coarsening/pointwise_aggregates.hpp>
#include <amgcl/coarsening/tentative_prolongation.hpp>
#include <amgcl/util.hpp>

namespace amgcl {
namespace coarsening {

/// Smoothed aggregation coarsening.
/**
 * \ingroup coarsening
 * \sa \cite Vanek1996
 */
template <class Backend>
struct smoothed_aggregation {
    typedef pointwise_aggregates Aggregates;

    /// Coarsening parameters
    struct params {
        /// Aggregation parameters.
        Aggregates::params aggr;

        /// Near nullspace parameters.
        nullspace_params nullspace;

        /// Relaxation factor.
        /**
         * Used as a scaling for the damping factor omega.
         * When estimate_spectral_radius is set, then
         *   omega = relax * (4/3) / rho.
         * Otherwise
         *   omega = relax * (2/3).
         *
         * Piecewise constant prolongation \f$\tilde P\f$ from non-smoothed
         * aggregation is improved by a smoothing to get the final prolongation
         * matrix \f$P\f$. Simple Jacobi smoother is used here, giving the
         * prolongation matrix
         * \f[P = \left( I - \omega D^{-1} A^F \right) \tilde P.\f]
         * Here \f$A^F = (a_{ij}^F)\f$ is the filtered matrix given by
         * \f[
         * a_{ij}^F =
         * \begin{cases}
         * a_{ij} \quad \text{if} \; j \in N_i\\
         * 0 \quad \text{otherwise}
         * \end{cases}, \quad \text{if}\; i \neq j,
         * \quad a_{ii}^F = a_{ii} - \sum\limits_{j=1,j\neq i}^n
         * \left(a_{ij} - a_{ij}^F \right),
         * \f]
         * where \f$N_i\f$ is the set of variables, strongly coupled to
         * variable \f$i\f$, and \f$D\f$ denotes the diagonal of \f$A^F\f$.
         */
        float relax;

        // Use power iterations to estimate the matrix spectral radius.
        // This usually improves convergence rate and results in faster solves,
        // but costs some time during setup.
        bool estimate_spectral_radius;

        // Number of power iterations to apply for the spectral radius
        // estimation.
        int power_iters;

        params() : relax(1.0f), estimate_spectral_radius(true), power_iters(5) { }

        params(const boost::property_tree::ptree &p)
            : AMGCL_PARAMS_IMPORT_CHILD(p, aggr),
              AMGCL_PARAMS_IMPORT_CHILD(p, nullspace),
              AMGCL_PARAMS_IMPORT_VALUE(p, relax),
              AMGCL_PARAMS_IMPORT_VALUE(p, estimate_spectral_radius),
              AMGCL_PARAMS_IMPORT_VALUE(p, power_iters)
        {
            AMGCL_PARAMS_CHECK(p, (aggr)(nullspace)(relax)(estimate_spectral_radius)(power_iters));
        }

        void get(boost::property_tree::ptree &p, const std::string &path) const {
            AMGCL_PARAMS_EXPORT_CHILD(p, path, aggr);
            AMGCL_PARAMS_EXPORT_CHILD(p, path, nullspace);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, relax);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, estimate_spectral_radius);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, power_iters);
        }
    } prm;

    smoothed_aggregation(const params &prm = params()) : prm(prm) {}

    /// \copydoc amgcl::coarsening::aggregation::transfer_operators
    template <class Matrix>
    boost::tuple< boost::shared_ptr<Matrix>, boost::shared_ptr<Matrix> >
    transfer_operators(const Matrix &A) {
        typedef typename backend::value_type<Matrix>::type value_type;
        typedef typename math::scalar_of<value_type>::type scalar_type;

        const size_t n = rows(A);

        AMGCL_TIC("aggregates");
        Aggregates aggr(A, prm.aggr, prm.nullspace.cols);
        prm.aggr.eps_strong *= 0.5;
        AMGCL_TOC("aggregates");

        AMGCL_TIC("interpolation");
        boost::shared_ptr<Matrix> P_tent = tentative_prolongation<Matrix>(
                n, aggr.count, aggr.id, prm.nullspace, prm.aggr.block_size
                );

        boost::shared_ptr<Matrix> P = boost::make_shared<Matrix>();
        P->set_size(rows(*P_tent), cols(*P_tent), true);

        scalar_type omega = prm.relax;
        if (prm.estimate_spectral_radius) {
            omega *= static_cast<scalar_type>(4.0/3) / spectral_radius(A, prm.power_iters);
        } else {
            omega *= static_cast<scalar_type>(2.0/3);
        }

#pragma omp parallel
        {
            std::vector<ptrdiff_t> marker(P->ncols, -1);

            // Count number of entries in P.
#pragma omp for
            for(ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(n); ++i) {
                for(ptrdiff_t ja = A.ptr[i], ea = A.ptr[i+1]; ja < ea; ++ja) {
                    ptrdiff_t ca = A.col[ja];

                    // Skip weak off-diagonal connections.
                    if (ca != i && !aggr.strong_connection[ja])
                        continue;

                    for(ptrdiff_t jp = P_tent->ptr[ca], ep = P_tent->ptr[ca+1]; jp < ep; ++jp) {
                        ptrdiff_t cp = P_tent->col[jp];

                        if (marker[cp] != i) {
                            marker[cp] = i;
                            ++( P->ptr[i + 1] );
                        }
                    }
                }
            }
        }

        P->scan_row_sizes();
        P->set_nonzeros();

#pragma omp parallel
        {
            std::vector<ptrdiff_t> marker(P->ncols, -1);

            // Fill the interpolation matrix.
#pragma omp for
            for(ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(n); ++i) {

                // Diagonal of the filtered matrix is the original matrix
                // diagonal minus its weak connections.
                value_type dia = math::zero<value_type>();
                for(ptrdiff_t j = A.ptr[i], e = A.ptr[i+1]; j < e; ++j) {
                    if (A.col[j] == i || !aggr.strong_connection[j])
                        dia += A.val[j];
                }
                dia = -omega * math::inverse(dia);

                ptrdiff_t row_beg = P->ptr[i];
                ptrdiff_t row_end = row_beg;
                for(ptrdiff_t ja = A.ptr[i], ea = A.ptr[i + 1]; ja < ea; ++ja) {
                    ptrdiff_t ca = A.col[ja];

                    // Skip weak off-diagonal connections.
                    if (ca != i && !aggr.strong_connection[ja]) continue;

                    value_type va = (ca == i)
                        ? static_cast<value_type>(static_cast<scalar_type>(1 - omega) * math::identity<value_type>())
                        : dia * A.val[ja];

                    for(ptrdiff_t jp = P_tent->ptr[ca], ep = P_tent->ptr[ca+1]; jp < ep; ++jp) {
                        ptrdiff_t cp = P_tent->col[jp];
                        value_type vp = P_tent->val[jp];

                        if (marker[cp] < row_beg) {
                            marker[cp] = row_end;
                            P->col[row_end] = cp;
                            P->val[row_end] = va * vp;
                            ++row_end;
                        } else {
                            P->val[ marker[cp] ] += va * vp;
                        }
                    }
                }
            }
        }
        AMGCL_TOC("interpolation");

        if (prm.nullspace.cols > 0)
            prm.aggr.block_size = prm.nullspace.cols;

        return boost::make_tuple(P, transpose(*P));
    }

    /// \copydoc amgcl::coarsening::aggregation::coarse_operator
    template <class Matrix>
    boost::shared_ptr<Matrix>
    coarse_operator(const Matrix &A, const Matrix &P, const Matrix &R) const {
        return detail::galerkin(A, P, R);
    }

    // Uses power iteration to estimate spectral readius of the matrix,
    // scaled by its inverse diagonal.
    template <class Matrix>
    static
    typename math::scalar_of<typename backend::value_type<Matrix>::type>::type
    spectral_radius(const Matrix &A, int power_iters)
    {
        typedef typename backend::value_type<Matrix>::type   value_type;
        typedef typename math::rhs_of<value_type>::type      rhs_type;
        typedef typename math::scalar_of<value_type>::type   scalar_type;

        const ptrdiff_t n = backend::rows(A);

        backend::numa_vector<value_type> D(n, false);
        backend::numa_vector<rhs_type>   b0(n, false), b1(n, false);

        // Fill the initial vector with random values.
        // Also extract the inverted matrix diagonal values.
        scalar_type b0_norm = 0;
#pragma omp parallel
        {
#ifdef _OPENMP
            int tid = omp_get_thread_num();
#else
            int tid = 0;
#endif
            boost::random::mt11213b rng(tid);
            boost::random::uniform_real_distribution<scalar_type> rnd(-1, 1);

            scalar_type loc_norm = 0;

#pragma omp for nowait
            for(ptrdiff_t i = 0; i < n; ++i) {
                rhs_type v = math::constant<rhs_type>(rnd(rng));

                b0[i] = v;
                loc_norm += math::norm(math::inner_product(v,v));

                for(ptrdiff_t j = A.ptr[i], e = A.ptr[i+1]; j < e; ++j) {
                    if (A.col[j] == i) {
                        D[i] = math::inverse(A.val[j]);
                        break;
                    }
                }
            }

#pragma omp critical
            b0_norm += loc_norm;
        }

        // Normalize b0
        b0_norm = 1 / sqrt(b0_norm);
#pragma omp parallel for
        for(ptrdiff_t i = 0; i < n; ++i) {
            b0[i] = b0_norm * b0[i];
        }

        scalar_type radius = 1;

        for(int iter = 0; iter < power_iters;) {
            // b1 = (D * A) * b0
            // b1_norm = ||b1||
            // radius = <b1,b0>
            scalar_type b1_norm = 0;
            radius = 0;
#pragma omp parallel
            {
                scalar_type loc_norm = 0;
                scalar_type loc_radi = 0;

#pragma omp for nowait
                for(ptrdiff_t i = 0; i < n; ++i) {
                    rhs_type s = math::zero<rhs_type>();

                    for(ptrdiff_t j = A.ptr[i], e = A.ptr[i+1]; j < e; ++j) {
                        s += A.val[j] * b0[A.col[j]];
                    }

                    s = D[i] * s;

                    loc_norm += math::norm(math::inner_product(s, s));
                    loc_radi += math::norm(math::inner_product(s, b0[i]));

                    b1[i] = s;
                }

#pragma omp critical
                {
                    b1_norm += loc_norm;
                    radius  += loc_radi;
                }
            }

            if (++iter < power_iters) {
                // b0 = b1 / b1_norm
                b1_norm = 1 / sqrt(b1_norm);
#pragma omp parallel for
                for(ptrdiff_t i = 0; i < n; ++i) {
                    b0[i] = b1_norm * b1[i];
                }
            }
        }

        return radius < 0 ? static_cast<scalar_type>(2) : radius;
    }
};

} // namespace coarsening
} // namespace amgcl

#endif
<|endoftext|>