<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/core/p9_hcd_core_stopclocks.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_hcd_core_stopclocks.C
/// @brief Core Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@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 Consumed by        : HB:PREV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include <p9_common_clk_ctrl_state.H>
#include "p9_hcd_core_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

enum P9_HCD_CORE_STOPCLOCKS_CONSTANTS
{
    CORE_PCB_MUX_POLLING_HW_NS_DELAY      = 10000,
    CORE_PCB_MUX_POLLING_SIM_CYCLE_DELAY  = 320000,
    CORE_CLK_SYNC_POLLING_HW_NS_DELAY     = 10000,
    CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY = 320000,
    CORE_CLK_STOP_POLLING_HW_NS_DELAY     = 10000,
    CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY = 320000
};

//------------------------------------------------------------------------------
// Procedure: Core Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_core_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target)
{
    FAPI_INF(">>p9_hcd_core_stopclocks");
    fapi2::ReturnCode                              l_rc;
    fapi2::buffer<uint64_t>                        l_ccsr;
    fapi2::buffer<uint64_t>                        l_data64;
    fapi2::buffer<uint64_t>                        l_temp64;
    uint32_t                                       l_loops1ms;
    uint8_t                                        l_attr_chip_unit_pos;
    uint8_t                                        l_attr_vdm_enable;
    uint8_t                                        l_attr_sdisn_setup;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sys;
    auto  l_quad = i_target.getParent<fapi2::TARGET_TYPE_EQ>();
    auto  l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();
    auto  l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_SDISN_SETUP, l_chip,
                           l_attr_sdisn_setup));

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_VDM_ENABLE,       l_sys,
                           l_attr_vdm_enable));
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,    l_perv,
                           l_attr_chip_unit_pos));
    l_attr_chip_unit_pos = (l_attr_chip_unit_pos -
                            p9hcd::PERV_TO_CORE_POS_OFFSET) % 4;

    // ----------------------------
    // Prepare to stop core clocks
    // ----------------------------

    FAPI_DBG("Check PM_RESET_STATE_INDICATOR via GPMMR[15]");
    FAPI_TRY(getScom(i_target, C_PPM_GPMMR_SCOM, l_data64));

    if (!l_data64.getBit<15>())
    {
        FAPI_DBG("Gracefully turn off power management, continue anyways if fail");
        /// @todo suspend_pm()
    }

    FAPI_DBG("Check core clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_CORE>(i_target);

    if (l_rc)
    {
        FAPI_INF("Clock controller of this core chiplet is inaccessible, return");
        goto fapi_try_exit;
    }

    FAPI_DBG("Check cache clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_EQ>(l_quad);

    if (l_rc)
    {
        FAPI_INF("WARNING: core is enabled while cache is not, continue anyways");
    }
    else
    {

        FAPI_DBG("Check PERV clock status for access to CME via CLOCK_STAT[4]");
        FAPI_TRY(getScom(l_quad, EQ_CLOCK_STAT_SL, l_data64));

        FAPI_DBG("Check PERV fence status for access to CME via CPLT_CTRL1[4]");
        FAPI_TRY(getScom(l_quad, EQ_CPLT_CTRL1, l_temp64));

        if (l_data64.getBit<4>() == 0 && l_temp64.getBit<4>() == 0)
        {
            //halt cme(poll for halted, if timeout, print warnning keep going).

            FAPI_DBG("Assert Core-L2/CC Quiesces via CME_SCOM_SICR[6,8]/[7,9]");
            FAPI_TRY(putScom(l_quad,
                             (l_attr_chip_unit_pos < 2) ?
                             EX_0_CME_SCOM_SICR_OR : EX_1_CME_SCOM_SICR_OR,
                             (BIT64(6 + (l_attr_chip_unit_pos % 2)) |
                              BIT64(8 + (l_attr_chip_unit_pos % 2)))));
        }
    }

    FAPI_DBG("Assert pm_mux_disable to get PCB Mux from CME via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_SET(7)));

    FAPI_DBG("Override possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_OR, MASK_SET(1)));

    FAPI_DBG("Assert chiplet fence via NET_CTRL0[18]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(18)));

    // -------------------------------
    // Stop core clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, C_SCAN_REGION_TYPE, MASK_ZERO));

    FAPI_DBG("Stop core clocks(all but pll) via CLK_REGION");
    l_data64 = (p9hcd::CLK_STOP_CMD           |
                p9hcd::CLK_REGION_ALL_BUT_PLL |
                p9hcd::CLK_THOLD_ALL);
    FAPI_TRY(putScom(i_target, C_CLK_REGION, l_data64));

    FAPI_DBG("Poll for core clocks stopped via CPLT_STAT0[8]");
    l_loops1ms = 1E6 / CORE_CLK_STOP_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CORE_CLK_STOP_POLLING_HW_NS_DELAY,
                     CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, C_CPLT_STAT0, l_data64));
    }
    while((l_data64.getBit<8>() != 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CORECLKSTOP_TIMEOUT().set_CORECPLTSTAT(l_data64),
                "Core Clock Stop Timeout");

    FAPI_DBG("Check core clocks stopped via CLOCK_STAT_SL[4-13]");
    FAPI_TRY(getScom(i_target, C_CLOCK_STAT_SL, l_data64));

    FAPI_ASSERT((((~l_data64) & p9hcd::CLK_REGION_ALL_BUT_PLL) == 0),
                fapi2::PMPROC_CORECLKSTOP_FAILED().set_CORECLKSTAT(l_data64),
                "Core Clock Stop Failed");
    FAPI_DBG("Core clocks stopped now");

    // -------------------------------
    // Disable core clock sync
    // -------------------------------

    FAPI_DBG("Drop core clock sync enable via CPPM_CACCR[15]");
    FAPI_TRY(putScom(i_target, C_CPPM_CACCR_CLEAR, MASK_SET(15)));

    FAPI_DBG("Poll for core clock sync done to drop via CPPM_CACSR[13]");
    l_loops1ms = 1E6 / CORE_CLK_SYNC_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CORE_CLK_SYNC_POLLING_HW_NS_DELAY,
                     CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, C_CPPM_CACSR, l_data64));
    }
    while((l_data64.getBit<13>() == 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CORECLKSYNCDROP_TIMEOUT().set_COREPPMCACSR(l_data64),
                "Core Clock Sync Drop Timeout");
    FAPI_DBG("Core clock sync done dropped");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert skew sense to skew adjust fence via NET_CTRL0[22]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(22)));

    FAPI_DBG("Assert vital fence via CPLT_CTRL1[3]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, MASK_SET(3)));

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[4-14]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, p9hcd::CLK_REGION_ALL));

    if (l_attr_sdisn_setup)
    {
        FAPI_DBG("DD1 Only: Drop sdis_n(flushing LCBES condition) vai CPLT_CONF0[34]");
        FAPI_TRY(putScom(i_target, C_CPLT_CONF0_CLEAR, MASK_SET(34)));
    }

    // -------------------------------
    // Disable VDM
    // -------------------------------

    if (l_attr_vdm_enable == fapi2::ENUM_ATTR_VDM_ENABLE_ON)
    {
        FAPI_DBG("Drop vdm enable via CPPM_VDMCR[0]");
        FAPI_TRY(putScom(i_target, C_PPM_VDMCR_CLEAR, MASK_SET(0)));
    }

    // -------------------------------
    // Update stop history
    // -------------------------------

    FAPI_DBG("Set core as stopped in STOP history register");
    FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0)));

    // -------------------------------
    // Clean up
    // -------------------------------

    FAPI_DBG("Return possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_CLEAR, MASK_SET(1)));

    FAPI_DBG("Drop pm_mux_disable to release PCB Mux via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_UNSET(7)));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_core_stopclocks");
    return fapi2::current_err;
}
<commit_msg>Istep4: clean up istep4 todo items and mark them with RTC<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/core/p9_hcd_core_stopclocks.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_hcd_core_stopclocks.C
/// @brief Core Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@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 Consumed by        : HB:PREV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include <p9_common_clk_ctrl_state.H>
#include "p9_hcd_core_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

enum P9_HCD_CORE_STOPCLOCKS_CONSTANTS
{
    CORE_PCB_MUX_POLLING_HW_NS_DELAY      = 10000,
    CORE_PCB_MUX_POLLING_SIM_CYCLE_DELAY  = 320000,
    CORE_CLK_SYNC_POLLING_HW_NS_DELAY     = 10000,
    CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY = 320000,
    CORE_CLK_STOP_POLLING_HW_NS_DELAY     = 10000,
    CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY = 320000
};

//------------------------------------------------------------------------------
// Procedure: Core Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_core_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target)
{
    FAPI_INF(">>p9_hcd_core_stopclocks");
    fapi2::ReturnCode                              l_rc;
    fapi2::buffer<uint64_t>                        l_ccsr;
    fapi2::buffer<uint64_t>                        l_data64;
    fapi2::buffer<uint64_t>                        l_temp64;
    uint32_t                                       l_loops1ms;
    uint8_t                                        l_attr_chip_unit_pos;
    uint8_t                                        l_attr_vdm_enable;
    uint8_t                                        l_attr_sdisn_setup;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sys;
    auto  l_quad = i_target.getParent<fapi2::TARGET_TYPE_EQ>();
    auto  l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();
    auto  l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_SDISN_SETUP, l_chip,
                           l_attr_sdisn_setup));

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_VDM_ENABLE,       l_sys,
                           l_attr_vdm_enable));
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,    l_perv,
                           l_attr_chip_unit_pos));
    l_attr_chip_unit_pos = (l_attr_chip_unit_pos -
                            p9hcd::PERV_TO_CORE_POS_OFFSET) % 4;

    // ----------------------------
    // Prepare to stop core clocks
    // ----------------------------

    FAPI_DBG("Check PM_RESET_STATE_INDICATOR via GPMMR[15]");
    FAPI_TRY(getScom(i_target, C_PPM_GPMMR_SCOM, l_data64));

    if (!l_data64.getBit<15>())
    {
        FAPI_DBG("Gracefully turn off power management, continue anyways if fail");
        /// @todo RTC158181 suspend_pm()
    }

    FAPI_DBG("Check core clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_CORE>(i_target);

    if (l_rc)
    {
        FAPI_INF("Clock controller of this core chiplet is inaccessible, return");
        goto fapi_try_exit;
    }

    FAPI_DBG("Check cache clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_EQ>(l_quad);

    if (l_rc)
    {
        FAPI_INF("WARNING: core is enabled while cache is not, continue anyways");
    }
    else
    {

        FAPI_DBG("Check PERV clock status for access to CME via CLOCK_STAT[4]");
        FAPI_TRY(getScom(l_quad, EQ_CLOCK_STAT_SL, l_data64));

        FAPI_DBG("Check PERV fence status for access to CME via CPLT_CTRL1[4]");
        FAPI_TRY(getScom(l_quad, EQ_CPLT_CTRL1, l_temp64));

        if (l_data64.getBit<4>() == 0 && l_temp64.getBit<4>() == 0)
        {
            //halt cme(poll for halted, if timeout, print warnning keep going).

            FAPI_DBG("Assert Core-L2/CC Quiesces via CME_SCOM_SICR[6,8]/[7,9]");
            FAPI_TRY(putScom(l_quad,
                             (l_attr_chip_unit_pos < 2) ?
                             EX_0_CME_SCOM_SICR_OR : EX_1_CME_SCOM_SICR_OR,
                             (BIT64(6 + (l_attr_chip_unit_pos % 2)) |
                              BIT64(8 + (l_attr_chip_unit_pos % 2)))));
        }
    }

    FAPI_DBG("Assert pm_mux_disable to get PCB Mux from CME via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_SET(7)));

    FAPI_DBG("Override possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_OR, MASK_SET(1)));

    FAPI_DBG("Assert chiplet fence via NET_CTRL0[18]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(18)));

    // -------------------------------
    // Stop core clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, C_SCAN_REGION_TYPE, MASK_ZERO));

    FAPI_DBG("Stop core clocks(all but pll) via CLK_REGION");
    l_data64 = (p9hcd::CLK_STOP_CMD           |
                p9hcd::CLK_REGION_ALL_BUT_PLL |
                p9hcd::CLK_THOLD_ALL);
    FAPI_TRY(putScom(i_target, C_CLK_REGION, l_data64));

    FAPI_DBG("Poll for core clocks stopped via CPLT_STAT0[8]");
    l_loops1ms = 1E6 / CORE_CLK_STOP_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CORE_CLK_STOP_POLLING_HW_NS_DELAY,
                     CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, C_CPLT_STAT0, l_data64));
    }
    while((l_data64.getBit<8>() != 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CORECLKSTOP_TIMEOUT().set_CORECPLTSTAT(l_data64),
                "Core Clock Stop Timeout");

    FAPI_DBG("Check core clocks stopped via CLOCK_STAT_SL[4-13]");
    FAPI_TRY(getScom(i_target, C_CLOCK_STAT_SL, l_data64));

    FAPI_ASSERT((((~l_data64) & p9hcd::CLK_REGION_ALL_BUT_PLL) == 0),
                fapi2::PMPROC_CORECLKSTOP_FAILED().set_CORECLKSTAT(l_data64),
                "Core Clock Stop Failed");
    FAPI_DBG("Core clocks stopped now");

    // -------------------------------
    // Disable core clock sync
    // -------------------------------

    FAPI_DBG("Drop core clock sync enable via CPPM_CACCR[15]");
    FAPI_TRY(putScom(i_target, C_CPPM_CACCR_CLEAR, MASK_SET(15)));

    FAPI_DBG("Poll for core clock sync done to drop via CPPM_CACSR[13]");
    l_loops1ms = 1E6 / CORE_CLK_SYNC_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CORE_CLK_SYNC_POLLING_HW_NS_DELAY,
                     CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, C_CPPM_CACSR, l_data64));
    }
    while((l_data64.getBit<13>() == 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CORECLKSYNCDROP_TIMEOUT().set_COREPPMCACSR(l_data64),
                "Core Clock Sync Drop Timeout");
    FAPI_DBG("Core clock sync done dropped");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert skew sense to skew adjust fence via NET_CTRL0[22]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(22)));

    FAPI_DBG("Assert vital fence via CPLT_CTRL1[3]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, MASK_SET(3)));

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[4-14]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, p9hcd::CLK_REGION_ALL));

    if (l_attr_sdisn_setup)
    {
        FAPI_DBG("DD1 Only: Drop sdis_n(flushing LCBES condition) vai CPLT_CONF0[34]");
        FAPI_TRY(putScom(i_target, C_CPLT_CONF0_CLEAR, MASK_SET(34)));
    }

    // -------------------------------
    // Disable VDM
    // -------------------------------

    if (l_attr_vdm_enable == fapi2::ENUM_ATTR_VDM_ENABLE_ON)
    {
        FAPI_DBG("Drop vdm enable via CPPM_VDMCR[0]");
        FAPI_TRY(putScom(i_target, C_PPM_VDMCR_CLEAR, MASK_SET(0)));
    }

    // -------------------------------
    // Update stop history
    // -------------------------------

    FAPI_DBG("Set core as stopped in STOP history register");
    FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0)));

    // -------------------------------
    // Clean up
    // -------------------------------

    FAPI_DBG("Return possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_CLEAR, MASK_SET(1)));

    FAPI_DBG("Drop pm_mux_disable to release PCB Mux via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_UNSET(7)));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_core_stopclocks");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.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_ddr_phy_reset.C
/// @brief Reset the DDR PHY
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <stdint.h>
#include <string.h>

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_ddr_phy_reset.H>
#include <lib/utils/count_dimm.H>
#include <lib/phy/adr32s.H>
#include <lib/workarounds/dp16_workarounds.H>
#include <lib/workarounds/dll_workarounds.H>
#include <lib/fir/check.H>
#include <lib/fir/unmask.H>

using fapi2::TARGET_TYPE_MCBIST;

extern "C"
{

///
/// @brief Perform a phy reset on all the PHY related to this half-chip (mcbist)
/// @param[in] the mcbist representing the PHY
/// @return FAPI2_RC_SUCCESS iff OK
///
    fapi2::ReturnCode p9_mss_ddr_phy_reset(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target)
    {
        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping ddr_phy_reset %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::LOW),
                 "force_mclk_low (set high) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );

        // 1. Drive all control signals to the PHY to their inactive state, idle state, or inactive value.
        FAPI_TRY( mss::dp16::reset_sysclk(i_target) );

        //    (Note: The chip should already be in this state.)
        FAPI_DBG("All control signals to the PHYs should be set to their inactive state, idle state, or inactive values");

        // 2. Assert reset to PHY for 32 memory clocks
        FAPI_TRY( mss::change_resetn(i_target, mss::HIGH), "change_resetn for %s failed", mss::c_str(i_target) );
        fapi2::delay(mss::cycles_to_ns(i_target, 32), mss::cycles_to_simcycles(32));

        // 3. Deassert reset_n
        FAPI_TRY( mss::change_resetn(i_target, mss::LOW), "change_resetn for %s failed", mss::c_str(i_target) );

        //
        // Flush output drivers
        //

        // 8. Set FLUSH=1 and INIT_IO=1 in the DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL and DDRPHY_DP16_DATA_BIT_DIR1 register
        // 9. Wait at least 32 dphy_gckn clock cycles.
        // 10. Set FLUSH=0 and INIT_IO=0 in the DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL register
        FAPI_TRY( mss::flush_output_drivers(i_target), "unable to flush output drivers for %s", mss::c_str(i_target) );

        //
        // ZCTL Enable
        //

        // 11. Assert the ZCNTL enable to the internal impedance controller in DDRPHY_PC_RESETS register
        // 12. Wait at least 1024 dphy_gckn cycles
        // 13. Deassert the ZCNTL impedance controller enable, Check for DONE in DDRPHY_PC_DLL_ZCAL
        FAPI_TRY( mss::enable_zctl(i_target), "enable_zctl for %s failed", mss::c_str(i_target) );

        //
        // DLL calibration
        //

        // 14. Begin DLL calibrations by setting INIT_RXDLL_CAL_RESET=0 in the DDRPHY_DP16_DLL_CNTL{0:1} registers
        // and DDRPHY_ADR_DLL_CNTL registers
        // 15. Monitor the DDRPHY_PC_DLL_ZCAL_CAL_STATUS register to determine when calibration is
        // complete. One of the 3 bits will be asserted for ADR and DP16.
        {
            FAPI_INF( "starting DLL calibration %s", mss::c_str(i_target) );
            bool l_run_workaround = false;
            FAPI_TRY( mss::dll_calibration(i_target, l_run_workaround), "%s Error in p9_mss_ddr_phy_reset.C",
                      mss::c_str(i_target)  );

            // Only run DLL workaround if we fail DLL cal
            // Note: there is no EC workaround for this workaround
            // The designer team informed me that there is no hardware fix in plan for this type of fail as of DD2 - SPG
            if( l_run_workaround )
            {
                FAPI_INF( "%s Applying DLL workaround", mss::c_str(i_target) );
                FAPI_TRY( mss::workarounds::dll::fix_bad_voltage_settings(i_target), "%s Error in p9_mss_ddr_phy_reset.C",
                          mss::c_str(i_target)  );
            }
        }

        //
        // Start bang-bang-lock
        //

        // 16. Take dphy_nclk/SysClk alignment circuits out of reset and put into continuous update mode,
        FAPI_INF("set up of phase rotator controls %s", mss::c_str(i_target) );
        FAPI_TRY( mss::setup_phase_rotator_control_registers(i_target, mss::ON), "%s Error in p9_mss_ddr_phy_reset.C",
                  mss::c_str(i_target)  );

        // 17. Wait at least 5932 dphy_nclk clock cycles to allow the dphy_nclk/SysClk alignment circuit to
        // perform initial alignment.
        FAPI_INF("Wait at least 5932 memory clock cycles for clock alignment circuit to perform initial alignment %s",
                 mss::c_str(i_target));
        FAPI_TRY( fapi2::delay(mss::cycles_to_ns(i_target, 5932), 2000) );

        // 18. Check for LOCK in DDRPHY_DP16_SYSCLK_PR_VALUE registers and DDRPHY_ADR_SYSCLK_PR_VALUE
        FAPI_INF("Checking for bang-bang lock %s ...", mss::c_str(i_target));
        FAPI_TRY( mss::check_bang_bang_lock(i_target), "%s Error in p9_mss_ddr_phy_reset.C", mss::c_str(i_target)  );

        // 19. Write 0b0 into the DDRPHY_PC_RESETS register bit 1. This write de-asserts the SYSCLK_RESET.
        FAPI_INF("deassert sysclk reset %s", mss::c_str(i_target));
        FAPI_TRY( mss::deassert_sysclk_reset(i_target), "deassert_sysclk_reset failed for %s", mss::c_str(i_target),
                  "%s Error in p9_mss_ddr_phy_reset.C", mss::c_str(i_target)  );

        // Reset the windage registers
        // According to the PHY team, resetting the read delay offset must be done after SYSCLK_RESET
        for( const auto& p : mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target) )
        {
            FAPI_TRY( mss::dp16::reset_read_delay_offset_registers(p),
                      "Failed reset_read_delay_offset_registers() for %s", mss::c_str(p) );
        }

        // 20. Write 8020h into the DDRPHY_ADR_SYSCLK_CNTL_PR Registers and
        // DDRPHY_DP16_SYSCLK_PR0/1 registers This write takes the dphy_nclk/
        // SysClk alignment circuit out of the Continuous Update mode.
        FAPI_INF("take sysclk alignment out of cont update mode %s", mss::c_str(i_target));
        FAPI_TRY( mss::setup_phase_rotator_control_registers(i_target, mss::OFF),
                  "set up of phase rotator controls failed (out of cont update) %s", mss::c_str(i_target) );

        // 21. Wait at least 32 dphy_nclk clock cycles.
        FAPI_DBG("Wait at least 32 memory clock cycles %s", mss::c_str(i_target));
        FAPI_TRY( fapi2::delay(mss::cycles_to_ns(i_target, 32), mss::cycles_to_simcycles(32)),
                  "%s Error in p9_mss_ddr_phy_reset.C", mss::c_str(i_target)  );

        //
        // Done bang-bang-lock
        //

        // Per J. Bialas, force_mclk_low can be dasserted.
        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::HIGH),
                 "force_mclk_low (set low) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );

        // Workarounds
        FAPI_TRY( mss::workarounds::dp16::after_phy_reset(i_target), "%s Error in p9_mss_ddr_phy_reset.C",
                  mss::c_str(i_target) );

        // New for Nimbus - perform duty cycle clock distortion calibration (DCD cal)
        // Per PHY team's characterization, the DCD cal needs to be run after DLL calibration
        FAPI_TRY( mss::adr32s::duty_cycle_distortion_calibration(i_target), "%s Error in p9_mss_ddr_phy_reset.C",
                  mss::c_str(i_target)  );

        // mss::check::during_phy_reset checks to see if there are any FIR. We do this 'twice' once here
        // (as part of the good-path) and once if we jump to the fapi_try label.
        if ((fapi2::current_err = mss::check::during_phy_reset(i_target)) != fapi2::FAPI2_RC_SUCCESS)
        {
            goto leave_for_real;
        }

        // Unmask the FIR we want unmasked after phy reset is complete. Note this is the "good path."
        // The algorithm is 'good path do after_phy_reset, all paths (error or not) perform the checks
        // which are defined in during_phy_reset'. We won't run after_phy_reset (unmask of FIR) unless
        // we're done with a success.
        FAPI_TRY( mss::unmask::after_phy_reset(i_target), "%s Error in p9_mss_ddr_phy_reset.C", mss::c_str(i_target)  );

        // Leave as we're all good and checked the FIR already ...
        return fapi2::current_err;

        // ... here on a bad-path, check FIR and leave ...
    fapi_try_exit:

        // mss::check::during_phy_reset handles the error/no error case internally. All we need to do is
        // return the ReturnCode it hands us - it's taken care of commiting anything it needed to.
        return mss::check::during_phy_reset(i_target);

        // ... here if the good-path FIR check found an error. We jumped over the unmasking and are
        // returning an error to the caller.
    leave_for_real:
        return fapi2::current_err;

    }
}
<commit_msg>Updated MSS HWP's level and owner change<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.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_ddr_phy_reset.C
/// @brief Reset the DDR PHY
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <stdint.h>
#include <string.h>

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_ddr_phy_reset.H>
#include <lib/utils/count_dimm.H>
#include <lib/phy/adr32s.H>
#include <lib/workarounds/dp16_workarounds.H>
#include <lib/workarounds/dll_workarounds.H>
#include <lib/fir/check.H>
#include <lib/fir/unmask.H>

using fapi2::TARGET_TYPE_MCBIST;

extern "C"
{

///
/// @brief Perform a phy reset on all the PHY related to this half-chip (mcbist)
/// @param[in] the mcbist representing the PHY
/// @return FAPI2_RC_SUCCESS iff OK
///
    fapi2::ReturnCode p9_mss_ddr_phy_reset(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target)
    {
        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping ddr_phy_reset %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::LOW),
                 "force_mclk_low (set high) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );

        // 1. Drive all control signals to the PHY to their inactive state, idle state, or inactive value.
        FAPI_TRY( mss::dp16::reset_sysclk(i_target) );

        //    (Note: The chip should already be in this state.)
        FAPI_DBG("All control signals to the PHYs should be set to their inactive state, idle state, or inactive values");

        // 2. Assert reset to PHY for 32 memory clocks
        FAPI_TRY( mss::change_resetn(i_target, mss::HIGH), "change_resetn for %s failed", mss::c_str(i_target) );
        fapi2::delay(mss::cycles_to_ns(i_target, 32), mss::cycles_to_simcycles(32));

        // 3. Deassert reset_n
        FAPI_TRY( mss::change_resetn(i_target, mss::LOW), "change_resetn for %s failed", mss::c_str(i_target) );

        //
        // Flush output drivers
        //

        // 8. Set FLUSH=1 and INIT_IO=1 in the DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL and DDRPHY_DP16_DATA_BIT_DIR1 register
        // 9. Wait at least 32 dphy_gckn clock cycles.
        // 10. Set FLUSH=0 and INIT_IO=0 in the DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL register
        FAPI_TRY( mss::flush_output_drivers(i_target), "unable to flush output drivers for %s", mss::c_str(i_target) );

        //
        // ZCTL Enable
        //

        // 11. Assert the ZCNTL enable to the internal impedance controller in DDRPHY_PC_RESETS register
        // 12. Wait at least 1024 dphy_gckn cycles
        // 13. Deassert the ZCNTL impedance controller enable, Check for DONE in DDRPHY_PC_DLL_ZCAL
        FAPI_TRY( mss::enable_zctl(i_target), "enable_zctl for %s failed", mss::c_str(i_target) );

        //
        // DLL calibration
        //

        // 14. Begin DLL calibrations by setting INIT_RXDLL_CAL_RESET=0 in the DDRPHY_DP16_DLL_CNTL{0:1} registers
        // and DDRPHY_ADR_DLL_CNTL registers
        // 15. Monitor the DDRPHY_PC_DLL_ZCAL_CAL_STATUS register to determine when calibration is
        // complete. One of the 3 bits will be asserted for ADR and DP16.
        {
            FAPI_INF( "starting DLL calibration %s", mss::c_str(i_target) );
            bool l_run_workaround = false;
            FAPI_TRY( mss::dll_calibration(i_target, l_run_workaround), "%s Error in p9_mss_ddr_phy_reset.C",
                      mss::c_str(i_target)  );

            // Only run DLL workaround if we fail DLL cal
            // Note: there is no EC workaround for this workaround
            // The designer team informed me that there is no hardware fix in plan for this type of fail as of DD2 - SPG
            if( l_run_workaround )
            {
                FAPI_INF( "%s Applying DLL workaround", mss::c_str(i_target) );
                FAPI_TRY( mss::workarounds::dll::fix_bad_voltage_settings(i_target), "%s Error in p9_mss_ddr_phy_reset.C",
                          mss::c_str(i_target)  );
            }
        }

        //
        // Start bang-bang-lock
        //

        // 16. Take dphy_nclk/SysClk alignment circuits out of reset and put into continuous update mode,
        FAPI_INF("set up of phase rotator controls %s", mss::c_str(i_target) );
        FAPI_TRY( mss::setup_phase_rotator_control_registers(i_target, mss::ON), "%s Error in p9_mss_ddr_phy_reset.C",
                  mss::c_str(i_target)  );

        // 17. Wait at least 5932 dphy_nclk clock cycles to allow the dphy_nclk/SysClk alignment circuit to
        // perform initial alignment.
        FAPI_INF("Wait at least 5932 memory clock cycles for clock alignment circuit to perform initial alignment %s",
                 mss::c_str(i_target));
        FAPI_TRY( fapi2::delay(mss::cycles_to_ns(i_target, 5932), 2000) );

        // 18. Check for LOCK in DDRPHY_DP16_SYSCLK_PR_VALUE registers and DDRPHY_ADR_SYSCLK_PR_VALUE
        FAPI_INF("Checking for bang-bang lock %s ...", mss::c_str(i_target));
        FAPI_TRY( mss::check_bang_bang_lock(i_target), "%s Error in p9_mss_ddr_phy_reset.C", mss::c_str(i_target)  );

        // 19. Write 0b0 into the DDRPHY_PC_RESETS register bit 1. This write de-asserts the SYSCLK_RESET.
        FAPI_INF("deassert sysclk reset %s", mss::c_str(i_target));
        FAPI_TRY( mss::deassert_sysclk_reset(i_target), "deassert_sysclk_reset failed for %s", mss::c_str(i_target),
                  "%s Error in p9_mss_ddr_phy_reset.C", mss::c_str(i_target)  );

        // Reset the windage registers
        // According to the PHY team, resetting the read delay offset must be done after SYSCLK_RESET
        for( const auto& p : mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target) )
        {
            FAPI_TRY( mss::dp16::reset_read_delay_offset_registers(p),
                      "Failed reset_read_delay_offset_registers() for %s", mss::c_str(p) );
        }

        // 20. Write 8020h into the DDRPHY_ADR_SYSCLK_CNTL_PR Registers and
        // DDRPHY_DP16_SYSCLK_PR0/1 registers This write takes the dphy_nclk/
        // SysClk alignment circuit out of the Continuous Update mode.
        FAPI_INF("take sysclk alignment out of cont update mode %s", mss::c_str(i_target));
        FAPI_TRY( mss::setup_phase_rotator_control_registers(i_target, mss::OFF),
                  "set up of phase rotator controls failed (out of cont update) %s", mss::c_str(i_target) );

        // 21. Wait at least 32 dphy_nclk clock cycles.
        FAPI_DBG("Wait at least 32 memory clock cycles %s", mss::c_str(i_target));
        FAPI_TRY( fapi2::delay(mss::cycles_to_ns(i_target, 32), mss::cycles_to_simcycles(32)),
                  "%s Error in p9_mss_ddr_phy_reset.C", mss::c_str(i_target)  );

        //
        // Done bang-bang-lock
        //

        // Per J. Bialas, force_mclk_low can be dasserted.
        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::HIGH),
                 "force_mclk_low (set low) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );

        // Workarounds
        FAPI_TRY( mss::workarounds::dp16::after_phy_reset(i_target), "%s Error in p9_mss_ddr_phy_reset.C",
                  mss::c_str(i_target) );

        // New for Nimbus - perform duty cycle clock distortion calibration (DCD cal)
        // Per PHY team's characterization, the DCD cal needs to be run after DLL calibration
        FAPI_TRY( mss::adr32s::duty_cycle_distortion_calibration(i_target), "%s Error in p9_mss_ddr_phy_reset.C",
                  mss::c_str(i_target)  );

        // mss::check::during_phy_reset checks to see if there are any FIR. We do this 'twice' once here
        // (as part of the good-path) and once if we jump to the fapi_try label.
        if ((fapi2::current_err = mss::check::during_phy_reset(i_target)) != fapi2::FAPI2_RC_SUCCESS)
        {
            goto leave_for_real;
        }

        // Unmask the FIR we want unmasked after phy reset is complete. Note this is the "good path."
        // The algorithm is 'good path do after_phy_reset, all paths (error or not) perform the checks
        // which are defined in during_phy_reset'. We won't run after_phy_reset (unmask of FIR) unless
        // we're done with a success.
        FAPI_TRY( mss::unmask::after_phy_reset(i_target), "%s Error in p9_mss_ddr_phy_reset.C", mss::c_str(i_target)  );

        // Leave as we're all good and checked the FIR already ...
        return fapi2::current_err;

        // ... here on a bad-path, check FIR and leave ...
    fapi_try_exit:

        // mss::check::during_phy_reset handles the error/no error case internally. All we need to do is
        // return the ReturnCode it hands us - it's taken care of commiting anything it needed to.
        return mss::check::during_phy_reset(i_target);

        // ... here if the good-path FIR check found an error. We jumped over the unmasking and are
        // returning an error to the caller.
    leave_for_real:
        return fapi2::current_err;

    }
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_chiplet_enable_ridi.H $ */
/*                                                                        */
/* 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_chiplet_enable_ridi.H
///
/// @brief Enable RI/DI chip wide
//------------------------------------------------------------------------------
// *HWP HW Owner        : Abhishek Agarwal <abagarw8@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Sunil kumar <skumar8j@in.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : HB
//------------------------------------------------------------------------------

#ifndef _P9_CHIPLET_ENABLE_RIDI_H_
#define _P9_CHIPLET_ENABLE_RIDI_H_

#include <fapi2.H>

typedef fapi2::ReturnCode (*p9_chiplet_enable_ridi_FP_t)(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

/// @brief Drop RI/DI for all chiplets being used (A, X, O, Pcie, DMI)
///
/// @param[in]     i_target_chip   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.

extern "C"
{
    fapi2::ReturnCode p9_chiplet_enable_ridi(const
            fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip);
}

#endif
<commit_msg>security -- split p9_chiplet_scominit and p9_chiplet_enable_ridi isteps<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_chiplet_enable_ridi.H $ */
/*                                                                        */
/* 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_chiplet_enable_ridi.H
///
/// @brief Enable RI/DI for all IO chiplets (excluding XBUS)
//------------------------------------------------------------------------------
// *HWP HW Owner        : Abhishek Agarwal <abagarw8@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Sunil kumar <skumar8j@in.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : HB
//------------------------------------------------------------------------------

#ifndef _P9_CHIPLET_ENABLE_RIDI_H_
#define _P9_CHIPLET_ENABLE_RIDI_H_

#include <fapi2.H>

typedef fapi2::ReturnCode (*p9_chiplet_enable_ridi_FP_t)(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

/// @brief Drop RI/DI for O, PCIE, MC
///
/// @param[in]     i_target_chip   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.

extern "C"
{
    fapi2::ReturnCode p9_chiplet_enable_ridi(const
            fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip);
}

#endif
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquicklinearlayout_p.h"
#include <QtCore/qnumeric.h>
#include "qdebug.h"
/*!
    \qmltype RowLayout
    \instantiates QQuickRowLayout
    \inqmlmodule QtDesktop 1.0
    \brief RowLayout is doing bla...bla...
*/

/*!
    \qmltype ColumnLayout
    \instantiates QQuickColumnLayout
    \inqmlmodule QtDesktop 1.0
    \brief ColumnLayout is doing bla...bla...
*/

QT_BEGIN_NAMESPACE

static const qreal q_declarativeLayoutDefaultSpacing = 4.0;

QQuickGridLayoutBase::QQuickGridLayoutBase(QQuickGridLayoutBasePrivate &dd,
                                           Qt::Orientation orientation,
                                           QQuickItem *parent /*= 0*/)
    : QQuickLayout(dd, parent)
{
    Q_D(QQuickGridLayoutBase);
    d->orientation = orientation;
}

Qt::Orientation QQuickGridLayoutBase::orientation() const
{
    Q_D(const QQuickGridLayoutBase);
    return d->orientation;
}

void QQuickGridLayoutBase::setOrientation(Qt::Orientation orientation)
{
    Q_D(QQuickGridLayoutBase);
    if (d->orientation == orientation)
        return;

    d->orientation = orientation;
    invalidate();
}

void QQuickGridLayoutBase::componentComplete()
{
    Q_D(QQuickGridLayoutBase);
    quickLayoutDebug() << objectName() << "QQuickGridLayoutBase::componentComplete()" << parent();
    d->m_disableRearrange = true;
    QQuickLayout::componentComplete();    // will call our geometryChange(), (where isComponentComplete() == true)
    d->m_disableRearrange = false;
    updateLayoutItems();

    QQuickItem *par = parentItem();
    if (qobject_cast<QQuickLayout*>(par))
        return;
    rearrange(QSizeF(width(), height()));
}

/*
  Invalidation happens like this as a reaction to that a size hint changes on an item "a":

  Suppose we have the following Qml document:
    RowLayout {
        id: l1
        RowLayout {
            id: l2
            Item {
                id: a
            }
            Item {
                id: b
            }
        }
    }

  1.    l2->invalidateChildItem(a) is called on l2, where item refers to "a".
        (this will dirty the cached size hints of item "a")
  2.    l2->invalidate() is called
        this will :
            i)  invalidate the layout engine
            ii) dirty the cached size hints of item "l2" (by calling parentLayout()->invalidateChildItem

 */
/*!
   \internal

    Invalidates \a childItem and this layout.
    After a call to invalidate, the next call to retrieve e.g. sizeHint will be up-to date.
    This function will also call QQuickLayout::invalidate(0), to ensure that the parent layout
    is invalidated.
 */
void QQuickGridLayoutBase::invalidate(QQuickItem *childItem)
{
    Q_D(QQuickGridLayoutBase);
    if (!isComponentComplete())
        return;
    quickLayoutDebug() << "QQuickGridLayoutBase::invalidate()";

    if (childItem) {
        if (QQuickGridLayoutItem *layoutItem = d->engine.findLayoutItem(childItem))
            layoutItem->invalidate();
    }
    // invalidate engine
    d->engine.invalidate();

    QQuickLayout::invalidate(this);
}

void QQuickGridLayoutBase::updateLayoutItems()
{
    Q_D(QQuickGridLayoutBase);
    if (!isComponentComplete())
        return;
    quickLayoutDebug() << "QQuickGridLayoutBase::updateLayoutItems";
    d->engine.deleteItems();
    foreach (QQuickItem *child,  childItems()) {
        if (child->isVisible())
            insertLayoutItem(child);
    }

    invalidate();
    quickLayoutDebug() << "QQuickGridLayoutBase::updateLayoutItems LEAVING";
    propagateLayoutSizeHints();
}

void QQuickGridLayoutBase::propagateLayoutSizeHints()
{
    Q_D(QQuickGridLayoutBase);
    quickLayoutDebug() << "propagateLayoutSizeHints()";
    QObject *attached = qmlAttachedPropertiesObject<QQuickLayout>(this);
    QQuickLayoutAttached *info = static_cast<QQuickLayoutAttached *>(attached);

    const QSizeF min = d->engine.sizeHint(Qt::MinimumSize, QSizeF());
    const QSizeF pref = d->engine.sizeHint(Qt::PreferredSize, QSizeF());
    const QSizeF max = d->engine.sizeHint(Qt::MaximumSize, QSizeF());

    info->setMinimumWidth(min.width());
    info->setMinimumHeight(min.height());
    setImplicitWidth(pref.width());
    setImplicitHeight(pref.height());
    info->setMaximumWidth(max.width());
    info->setMaximumHeight(max.height());
}

void QQuickGridLayoutBase::itemChange(ItemChange change, const ItemChangeData &value)
{
    if (change == ItemChildAddedChange) {
        quickLayoutDebug() << "ItemChildAddedChange";
        QQuickItem *item = value.item;
        QObject::connect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
        QObject::connect(item, SIGNAL(visibleChanged()), this, SLOT(onItemVisibleChanged()));
        QObject::connect(item, SIGNAL(implicitWidthChanged()), this, SLOT(onItemImplicitSizeChanged()));

        if (isComponentComplete() && isVisible())
            updateLayoutItems();
    } else if (change == ItemChildRemovedChange) {
        quickLayoutDebug() << "ItemChildRemovedChange";
        QQuickItem *item = value.item;
        QObject::disconnect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
        QObject::disconnect(item, SIGNAL(visibleChanged()), this, SLOT(onItemVisibleChanged()));
        QObject::disconnect(item, SIGNAL(implicitWidthChanged()), this, SLOT(onItemImplicitSizeChanged()));
        if (isComponentComplete() && isVisible())
            updateLayoutItems();
    }

    QQuickLayout::itemChange(change, value);
}

void QQuickGridLayoutBase::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    Q_D(QQuickGridLayoutBase);
    QQuickLayout::geometryChanged(newGeometry, oldGeometry);
    if (d->m_disableRearrange || !isComponentComplete() || !newGeometry.isValid())
        return;
    quickLayoutDebug() << "QQuickGridLayoutBase::geometryChanged" << newGeometry << oldGeometry;
    rearrange(newGeometry.size());
}

void QQuickGridLayoutBase::insertLayoutItem(QQuickItem *item)
{
    Q_D(QQuickGridLayoutBase);
    if (!item) {
        qWarning("QGraphicsGridLayout::addItem: cannot add null item");
        return;
    }
    QQuickLayoutAttached *info = attachedLayoutObject(item, false);
    int row = 0;
    int column = 0;
    int rowSpan = 1;
    int columnSpan = 1;
    Qt::Alignment alignment = 0;
    if (info) {
        row = info->row();
        column = info->column();
        rowSpan = info->rowSpan();
        columnSpan = info->columnSpan();
    }
    if (row < 0 || column < 0) {
        qWarning("QQuickGridLayoutBase::insertLayoutItemAt: invalid row/column: %d",
                 row < 0 ? row : column);
        return;
    }
    if (columnSpan < 1 || rowSpan < 1) {
        qWarning("QQuickGridLayoutBase::addItem: invalid row span/column span: %d",
                 rowSpan < 1 ? rowSpan : columnSpan);
        return;
    }
    QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(item, row, column, rowSpan, columnSpan, alignment);
    d->engine.insertItem(layoutItem, -1);

    setupItemLayout(item);
}

void QQuickGridLayoutBase::removeGridItem(QGridLayoutItem *gridItem)
{
    Q_D(QQuickGridLayoutBase);
    const int index = gridItem->firstRow(d->orientation);
    d->engine.removeItem(gridItem);
    d->engine.removeRows(index, 1, d->orientation);
}

void QQuickGridLayoutBase::removeLayoutItem(QQuickItem *item)
{
    Q_D(QQuickGridLayoutBase);
    quickLayoutDebug() << "QQuickGridLayoutBase::removeLayoutItem";
    if (QQuickGridLayoutItem *gridItem = d->engine.findLayoutItem(item)) {
        removeGridItem(gridItem);
        delete gridItem;
        invalidate();
    }
}

void QQuickGridLayoutBase::onItemVisibleChanged()
{
    if (!isComponentComplete())
        return;
    quickLayoutDebug() << "QQuickGridLayoutBase::onItemVisibleChanged";
    updateLayoutItems();
}

void QQuickGridLayoutBase::onItemDestroyed()
{
    Q_D(QQuickGridLayoutBase);
    quickLayoutDebug() << "QQuickGridLayoutBase::onItemDestroyed";
    QQuickItem *inDestruction = static_cast<QQuickItem *>(sender());
    if (QQuickGridLayoutItem *gridItem = d->engine.findLayoutItem(inDestruction)) {
        removeGridItem(gridItem);
        delete gridItem;
        invalidate();
    }
}

void QQuickGridLayoutBase::onItemImplicitSizeChanged()
{
    //QQuickItem *item = static_cast<QQuickItem *>(sender());
    //Q_ASSERT(item);
    //invalidate(item);
}

void QQuickGridLayoutBase::rearrange(const QSizeF &size)
{
    Q_D(QQuickGridLayoutBase);
    if (!isComponentComplete())
        return;

    quickLayoutDebug() << objectName() << "QQuickGridLayoutBase::rearrange()" << size;
    Qt::LayoutDirection visualDir = Qt::LeftToRight;    // ### Fix if RTL support is needed
    d->engine.setVisualDirection(visualDir);

    /*
    qreal left, top, right, bottom;
    left = top = right = bottom = 0;                    // ### support for margins?
    if (visualDir == Qt::RightToLeft)
        qSwap(left, right);
    */

    d->engine.setGeometries(QRectF(QPointF(0,0), size));

    QQuickLayout::rearrange(size);
    // propagate hints to upper levels
    propagateLayoutSizeHints();
}

/**********************************
 **
 ** QQuickGridLayout
 **
 **/
QQuickGridLayout::QQuickGridLayout(QQuickItem *parent /* = 0*/)
    : QQuickGridLayoutBase(*new QQuickGridLayoutPrivate, Qt::Horizontal, parent)
{
    Q_D(QQuickGridLayout);
    d->horizontalSpacing = q_declarativeLayoutDefaultSpacing;
    d->verticalSpacing = q_declarativeLayoutDefaultSpacing;
    d->engine.setSpacing(d->horizontalSpacing, Qt::Horizontal);
    d->engine.setSpacing(d->verticalSpacing, Qt::Vertical);
}

qreal QQuickGridLayout::horizontalSpacing() const
{
    Q_D(const QQuickGridLayout);
    return d->horizontalSpacing;
}

void QQuickGridLayout::setHorizontalSpacing(qreal spacing)
{
    Q_D(QQuickGridLayout);
    if (qIsNaN(spacing) || d->horizontalSpacing == spacing)
        return;

    d->horizontalSpacing = spacing;
    d->engine.setSpacing(spacing, Qt::Horizontal | Qt::Vertical);
    invalidate();
}

qreal QQuickGridLayout::verticalSpacing() const
{
    Q_D(const QQuickGridLayout);
    return d->verticalSpacing;
}

void QQuickGridLayout::setVerticalSpacing(qreal spacing)
{
    Q_D(QQuickGridLayout);
    if (qIsNaN(spacing) || d->verticalSpacing == spacing)
        return;

    d->verticalSpacing = spacing;
    d->engine.setSpacing(spacing, Qt::Horizontal | Qt::Vertical);
    invalidate();
}

/**********************************
 **
 ** QQuickLinearLayout
 **
 **/
QQuickLinearLayout::QQuickLinearLayout(Qt::Orientation orientation,
                                        QQuickItem *parent /*= 0*/)
    : QQuickGridLayoutBase(*new QQuickLinearLayoutPrivate, orientation, parent)
{
    Q_D(QQuickLinearLayout);
    d->spacing = q_declarativeLayoutDefaultSpacing;
    d->engine.setSpacing(d->spacing, Qt::Horizontal | Qt::Vertical);
}

qreal QQuickLinearLayout::spacing() const
{
    Q_D(const QQuickLinearLayout);
    return d->spacing;
}

void QQuickLinearLayout::setSpacing(qreal spacing)
{
    Q_D(QQuickLinearLayout);
    if (qIsNaN(spacing) || d->spacing == spacing)
        return;

    d->spacing = spacing;
    d->engine.setSpacing(spacing, Qt::Horizontal | Qt::Vertical);
    invalidate();
}

void QQuickLinearLayout::insertLayoutItem(QQuickItem *item)
{
    Q_D(QQuickLinearLayout);
    const int index = d->engine.rowCount(d->orientation);
    d->engine.insertRow(index, d->orientation);

    int gridRow = 0;
    int gridColumn = index;
    if (d->orientation == Qt::Vertical)
        qSwap(gridRow, gridColumn);
    QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(item, gridRow, gridColumn, 1, 1, 0);
    d->engine.insertItem(layoutItem, index);

    setupItemLayout(item);
}

QT_END_NAMESPACE
<commit_msg>React to implicit size changes<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquicklinearlayout_p.h"
#include <QtCore/qnumeric.h>
#include "qdebug.h"
/*!
    \qmltype RowLayout
    \instantiates QQuickRowLayout
    \inqmlmodule QtDesktop 1.0
    \brief RowLayout is doing bla...bla...
*/

/*!
    \qmltype ColumnLayout
    \instantiates QQuickColumnLayout
    \inqmlmodule QtDesktop 1.0
    \brief ColumnLayout is doing bla...bla...
*/

QT_BEGIN_NAMESPACE

static const qreal q_declarativeLayoutDefaultSpacing = 4.0;

QQuickGridLayoutBase::QQuickGridLayoutBase(QQuickGridLayoutBasePrivate &dd,
                                           Qt::Orientation orientation,
                                           QQuickItem *parent /*= 0*/)
    : QQuickLayout(dd, parent)
{
    Q_D(QQuickGridLayoutBase);
    d->orientation = orientation;
}

Qt::Orientation QQuickGridLayoutBase::orientation() const
{
    Q_D(const QQuickGridLayoutBase);
    return d->orientation;
}

void QQuickGridLayoutBase::setOrientation(Qt::Orientation orientation)
{
    Q_D(QQuickGridLayoutBase);
    if (d->orientation == orientation)
        return;

    d->orientation = orientation;
    invalidate();
}

void QQuickGridLayoutBase::componentComplete()
{
    Q_D(QQuickGridLayoutBase);
    quickLayoutDebug() << objectName() << "QQuickGridLayoutBase::componentComplete()" << parent();
    d->m_disableRearrange = true;
    QQuickLayout::componentComplete();    // will call our geometryChange(), (where isComponentComplete() == true)
    d->m_disableRearrange = false;
    updateLayoutItems();

    QQuickItem *par = parentItem();
    if (qobject_cast<QQuickLayout*>(par))
        return;
    rearrange(QSizeF(width(), height()));
}

/*
  Invalidation happens like this as a reaction to that a size hint changes on an item "a":

  Suppose we have the following Qml document:
    RowLayout {
        id: l1
        RowLayout {
            id: l2
            Item {
                id: a
            }
            Item {
                id: b
            }
        }
    }

  1.    l2->invalidateChildItem(a) is called on l2, where item refers to "a".
        (this will dirty the cached size hints of item "a")
  2.    l2->invalidate() is called
        this will :
            i)  invalidate the layout engine
            ii) dirty the cached size hints of item "l2" (by calling parentLayout()->invalidateChildItem

 */
/*!
   \internal

    Invalidates \a childItem and this layout.
    After a call to invalidate, the next call to retrieve e.g. sizeHint will be up-to date.
    This function will also call QQuickLayout::invalidate(0), to ensure that the parent layout
    is invalidated.
 */
void QQuickGridLayoutBase::invalidate(QQuickItem *childItem)
{
    Q_D(QQuickGridLayoutBase);
    if (!isComponentComplete())
        return;
    quickLayoutDebug() << "QQuickGridLayoutBase::invalidate()";

    if (childItem) {
        if (QQuickGridLayoutItem *layoutItem = d->engine.findLayoutItem(childItem))
            layoutItem->invalidate();
    }
    // invalidate engine
    d->engine.invalidate();

    QQuickLayout::invalidate(this);
}

void QQuickGridLayoutBase::updateLayoutItems()
{
    Q_D(QQuickGridLayoutBase);
    if (!isComponentComplete())
        return;
    quickLayoutDebug() << "QQuickGridLayoutBase::updateLayoutItems";
    d->engine.deleteItems();
    foreach (QQuickItem *child,  childItems()) {
        if (child->isVisible())
            insertLayoutItem(child);
    }

    invalidate();
    quickLayoutDebug() << "QQuickGridLayoutBase::updateLayoutItems LEAVING";
    propagateLayoutSizeHints();
}

void QQuickGridLayoutBase::propagateLayoutSizeHints()
{
    Q_D(QQuickGridLayoutBase);
    quickLayoutDebug() << "propagateLayoutSizeHints()";
    QObject *attached = qmlAttachedPropertiesObject<QQuickLayout>(this);
    QQuickLayoutAttached *info = static_cast<QQuickLayoutAttached *>(attached);

    const QSizeF min = d->engine.sizeHint(Qt::MinimumSize, QSizeF());
    const QSizeF pref = d->engine.sizeHint(Qt::PreferredSize, QSizeF());
    const QSizeF max = d->engine.sizeHint(Qt::MaximumSize, QSizeF());

    info->setMinimumWidth(min.width());
    info->setMinimumHeight(min.height());
    setImplicitWidth(pref.width());
    setImplicitHeight(pref.height());
    info->setMaximumWidth(max.width());
    info->setMaximumHeight(max.height());
}

void QQuickGridLayoutBase::itemChange(ItemChange change, const ItemChangeData &value)
{
    if (change == ItemChildAddedChange) {
        quickLayoutDebug() << "ItemChildAddedChange";
        QQuickItem *item = value.item;
        QObject::connect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
        QObject::connect(item, SIGNAL(visibleChanged()), this, SLOT(onItemVisibleChanged()));
        QObject::connect(item, SIGNAL(implicitWidthChanged()), this, SLOT(onItemImplicitSizeChanged()));
        QObject::connect(item, SIGNAL(implicitHeightChanged()), this, SLOT(onItemImplicitSizeChanged()));

        if (isComponentComplete() && isVisible())
            updateLayoutItems();
    } else if (change == ItemChildRemovedChange) {
        quickLayoutDebug() << "ItemChildRemovedChange";
        QQuickItem *item = value.item;
        QObject::disconnect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
        QObject::disconnect(item, SIGNAL(visibleChanged()), this, SLOT(onItemVisibleChanged()));
        QObject::disconnect(item, SIGNAL(implicitWidthChanged()), this, SLOT(onItemImplicitSizeChanged()));
        QObject::disconnect(item, SIGNAL(implicitHeightChanged()), this, SLOT(onItemImplicitSizeChanged()));
        if (isComponentComplete() && isVisible())
            updateLayoutItems();
    }

    QQuickLayout::itemChange(change, value);
}

void QQuickGridLayoutBase::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    Q_D(QQuickGridLayoutBase);
    QQuickLayout::geometryChanged(newGeometry, oldGeometry);
    if (d->m_disableRearrange || !isComponentComplete() || !newGeometry.isValid())
        return;
    quickLayoutDebug() << "QQuickGridLayoutBase::geometryChanged" << newGeometry << oldGeometry;
    rearrange(newGeometry.size());
}

void QQuickGridLayoutBase::insertLayoutItem(QQuickItem *item)
{
    Q_D(QQuickGridLayoutBase);
    if (!item) {
        qWarning("QGraphicsGridLayout::addItem: cannot add null item");
        return;
    }
    QQuickLayoutAttached *info = attachedLayoutObject(item, false);
    int row = 0;
    int column = 0;
    int rowSpan = 1;
    int columnSpan = 1;
    Qt::Alignment alignment = 0;
    if (info) {
        row = info->row();
        column = info->column();
        rowSpan = info->rowSpan();
        columnSpan = info->columnSpan();
    }
    if (row < 0 || column < 0) {
        qWarning("QQuickGridLayoutBase::insertLayoutItemAt: invalid row/column: %d",
                 row < 0 ? row : column);
        return;
    }
    if (columnSpan < 1 || rowSpan < 1) {
        qWarning("QQuickGridLayoutBase::addItem: invalid row span/column span: %d",
                 rowSpan < 1 ? rowSpan : columnSpan);
        return;
    }
    QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(item, row, column, rowSpan, columnSpan, alignment);
    d->engine.insertItem(layoutItem, -1);

    setupItemLayout(item);
}

void QQuickGridLayoutBase::removeGridItem(QGridLayoutItem *gridItem)
{
    Q_D(QQuickGridLayoutBase);
    const int index = gridItem->firstRow(d->orientation);
    d->engine.removeItem(gridItem);
    d->engine.removeRows(index, 1, d->orientation);
}

void QQuickGridLayoutBase::removeLayoutItem(QQuickItem *item)
{
    Q_D(QQuickGridLayoutBase);
    quickLayoutDebug() << "QQuickGridLayoutBase::removeLayoutItem";
    if (QQuickGridLayoutItem *gridItem = d->engine.findLayoutItem(item)) {
        removeGridItem(gridItem);
        delete gridItem;
        invalidate();
    }
}

void QQuickGridLayoutBase::onItemVisibleChanged()
{
    if (!isComponentComplete())
        return;
    quickLayoutDebug() << "QQuickGridLayoutBase::onItemVisibleChanged";
    updateLayoutItems();
}

void QQuickGridLayoutBase::onItemDestroyed()
{
    Q_D(QQuickGridLayoutBase);
    quickLayoutDebug() << "QQuickGridLayoutBase::onItemDestroyed";
    QQuickItem *inDestruction = static_cast<QQuickItem *>(sender());
    if (QQuickGridLayoutItem *gridItem = d->engine.findLayoutItem(inDestruction)) {
        removeGridItem(gridItem);
        delete gridItem;
        invalidate();
    }
}

void QQuickGridLayoutBase::onItemImplicitSizeChanged()
{
    QQuickItem *item = static_cast<QQuickItem *>(sender());
    Q_ASSERT(item);
    invalidate(item);
    propagateLayoutSizeHints();
}

void QQuickGridLayoutBase::rearrange(const QSizeF &size)
{
    Q_D(QQuickGridLayoutBase);
    if (!isComponentComplete())
        return;

    quickLayoutDebug() << objectName() << "QQuickGridLayoutBase::rearrange()" << size;
    Qt::LayoutDirection visualDir = Qt::LeftToRight;    // ### Fix if RTL support is needed
    d->engine.setVisualDirection(visualDir);

    /*
    qreal left, top, right, bottom;
    left = top = right = bottom = 0;                    // ### support for margins?
    if (visualDir == Qt::RightToLeft)
        qSwap(left, right);
    */

    d->engine.setGeometries(QRectF(QPointF(0,0), size));

    QQuickLayout::rearrange(size);
    // propagate hints to upper levels
    propagateLayoutSizeHints();
}

/**********************************
 **
 ** QQuickGridLayout
 **
 **/
QQuickGridLayout::QQuickGridLayout(QQuickItem *parent /* = 0*/)
    : QQuickGridLayoutBase(*new QQuickGridLayoutPrivate, Qt::Horizontal, parent)
{
    Q_D(QQuickGridLayout);
    d->horizontalSpacing = q_declarativeLayoutDefaultSpacing;
    d->verticalSpacing = q_declarativeLayoutDefaultSpacing;
    d->engine.setSpacing(d->horizontalSpacing, Qt::Horizontal);
    d->engine.setSpacing(d->verticalSpacing, Qt::Vertical);
}

qreal QQuickGridLayout::horizontalSpacing() const
{
    Q_D(const QQuickGridLayout);
    return d->horizontalSpacing;
}

void QQuickGridLayout::setHorizontalSpacing(qreal spacing)
{
    Q_D(QQuickGridLayout);
    if (qIsNaN(spacing) || d->horizontalSpacing == spacing)
        return;

    d->horizontalSpacing = spacing;
    d->engine.setSpacing(spacing, Qt::Horizontal | Qt::Vertical);
    invalidate();
}

qreal QQuickGridLayout::verticalSpacing() const
{
    Q_D(const QQuickGridLayout);
    return d->verticalSpacing;
}

void QQuickGridLayout::setVerticalSpacing(qreal spacing)
{
    Q_D(QQuickGridLayout);
    if (qIsNaN(spacing) || d->verticalSpacing == spacing)
        return;

    d->verticalSpacing = spacing;
    d->engine.setSpacing(spacing, Qt::Horizontal | Qt::Vertical);
    invalidate();
}

/**********************************
 **
 ** QQuickLinearLayout
 **
 **/
QQuickLinearLayout::QQuickLinearLayout(Qt::Orientation orientation,
                                        QQuickItem *parent /*= 0*/)
    : QQuickGridLayoutBase(*new QQuickLinearLayoutPrivate, orientation, parent)
{
    Q_D(QQuickLinearLayout);
    d->spacing = q_declarativeLayoutDefaultSpacing;
    d->engine.setSpacing(d->spacing, Qt::Horizontal | Qt::Vertical);
}

qreal QQuickLinearLayout::spacing() const
{
    Q_D(const QQuickLinearLayout);
    return d->spacing;
}

void QQuickLinearLayout::setSpacing(qreal spacing)
{
    Q_D(QQuickLinearLayout);
    if (qIsNaN(spacing) || d->spacing == spacing)
        return;

    d->spacing = spacing;
    d->engine.setSpacing(spacing, Qt::Horizontal | Qt::Vertical);
    invalidate();
}

void QQuickLinearLayout::insertLayoutItem(QQuickItem *item)
{
    Q_D(QQuickLinearLayout);
    const int index = d->engine.rowCount(d->orientation);
    d->engine.insertRow(index, d->orientation);

    int gridRow = 0;
    int gridColumn = index;
    if (d->orientation == Qt::Vertical)
        qSwap(gridRow, gridColumn);
    QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(item, gridRow, gridColumn, 1, 1, 0);
    d->engine.insertItem(layoutItem, index);

    setupItemLayout(item);
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2019 LibRaw LLC (info@libraw.org)
    Copyright (C) 2020 Roman Lebedev

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "decompressors/PanasonicDecompressorV6.h" // for PanasonicDecompre...
#include "common/Array2DRef.h"                     // for Array2DRef
#include "common/Point.h"                          // for iPoint2D
#include "common/RawImage.h"                       // for RawImage, RawImag...
#include "decoders/RawDecoderException.h"          // for ThrowRDE
#include <algorithm>                               // for copy_n
#include <array>
#include <cstdint> // for uint16_t, uint32_t
#include <cstdlib> // for free, malloc

namespace rawspeed {

constexpr int PanasonicDecompressorV6::PixelsPerBlock;
constexpr int PanasonicDecompressorV6::BytesPerBlock;

namespace {
struct pana_cs6_page_decoder {
  std::array<uint16_t, 14> pixelbuffer;
  unsigned char current = 0;

  explicit pana_cs6_page_decoder(const ByteStream& bs) {
    pixelbuffer[0] = (bs.peekByte(15) << 6) | (bs.peekByte(14) >> 2); // 14 bit
    pixelbuffer[1] = (((bs.peekByte(14) & 0x3) << 12) | (bs.peekByte(13) << 4) |
                      (bs.peekByte(12) >> 4)) &
                     0x3fff;
    pixelbuffer[2] = (bs.peekByte(12) >> 2) & 0x3;
    pixelbuffer[3] = ((bs.peekByte(12) & 0x3) << 8) | bs.peekByte(11);
    pixelbuffer[4] = (bs.peekByte(10) << 2) | (bs.peekByte(9) >> 6);
    pixelbuffer[5] = ((bs.peekByte(9) & 0x3f) << 4) | (bs.peekByte(8) >> 4);
    pixelbuffer[6] = (bs.peekByte(8) >> 2) & 0x3;
    pixelbuffer[7] = ((bs.peekByte(8) & 0x3) << 8) | bs.peekByte(7);
    pixelbuffer[8] = ((bs.peekByte(6) << 2) & 0x3fc) | (bs.peekByte(5) >> 6);
    pixelbuffer[9] = ((bs.peekByte(5) << 4) | (bs.peekByte(4) >> 4)) & 0x3ff;
    pixelbuffer[10] = (bs.peekByte(4) >> 2) & 0x3;
    pixelbuffer[11] = ((bs.peekByte(4) & 0x3) << 8) | bs.peekByte(3);
    pixelbuffer[12] =
        (((bs.peekByte(2) << 2) & 0x3fc) | bs.peekByte(1) >> 6) & 0x3ff;
    pixelbuffer[13] = ((bs.peekByte(1) << 4) | (bs.peekByte(0) >> 4)) & 0x3ff;
  }

  uint16_t nextpixel() { return pixelbuffer[current++]; }
};
} // namespace

PanasonicDecompressorV6::PanasonicDecompressorV6(const RawImage& img,
                                                 ByteStream input_)
    : mRaw(img), input(std::move(input_)) {
  if (mRaw->getCpp() != 1 || mRaw->getDataType() != TYPE_USHORT16 ||
      mRaw->getBpp() != sizeof(uint16_t))
    ThrowRDE("Unexpected component count / data type");

  if (!mRaw->dim.hasPositiveArea()) {
    ThrowRDE("Unexpected image dimensions found: (%i; %i)", mRaw->dim.x,
             mRaw->dim.y);
  }

  const int blocksperrow =
      mRaw->dim.x / PanasonicDecompressorV6::PixelsPerBlock;
  const int bytesPerRow = PanasonicDecompressorV6::BytesPerBlock * blocksperrow;
  const int bytesTotal = bytesPerRow * mRaw->dim.y;
  input = input_.peekStream(bytesTotal);
}

void PanasonicDecompressorV6::decompressBlock(ByteStream* rowInput, int row,
                                              int col) const {
  const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());

  pana_cs6_page_decoder page(
      rowInput->getStream(PanasonicDecompressorV6::BytesPerBlock));

  std::array<unsigned, 2> oddeven = {0, 0};
  std::array<unsigned, 2> nonzero = {0, 0};
  unsigned pmul = 0;
  unsigned pixel_base = 0;
  for (int pix = 0; pix < PanasonicDecompressorV6::PixelsPerBlock;
       pix++, col++) {
    if (pix % 3 == 2) {
      uint16_t base = page.nextpixel();
      if (base > 3)
        ThrowRDE("Invariant failure");
      if (base == 3)
        base = 4;
      pixel_base = 0x200 << base;
      pmul = 1 << base;
    }
    uint16_t epixel = page.nextpixel();
    if (oddeven[pix % 2]) {
      epixel *= pmul;
      if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base)
        epixel += nonzero[pix % 2] - pixel_base;
      nonzero[pix % 2] = epixel;
    } else {
      oddeven[pix % 2] = epixel;
      if (epixel)
        nonzero[pix % 2] = epixel;
      else
        epixel = nonzero[pix % 2];
    }
    auto spix = static_cast<unsigned>(static_cast<int>(epixel) - 0xf);
    if (spix <= 0xffff)
      out(row, col) = spix & 0xffff;
    else {
      epixel = static_cast<int>(epixel + 0x7ffffff1) >> 0x1f;
      out(row, col) = epixel & 0x3fff;
    }
  }
}

void PanasonicDecompressorV6::decompressRow(int row) const {
  const int blocksperrow =
      mRaw->dim.x / PanasonicDecompressorV6::PixelsPerBlock;
  const int bytesPerRow = PanasonicDecompressorV6::BytesPerBlock * blocksperrow;

  ByteStream rowInput = input.getSubStream(bytesPerRow * row, bytesPerRow);
  for (int rblock = 0, col = 0; rblock < blocksperrow;
       rblock++, col += PanasonicDecompressorV6::PixelsPerBlock)
    decompressBlock(&rowInput, row, col);
}

void PanasonicDecompressorV6::decompress() const {
#ifdef HAVE_OPENMP
#pragma omp parallel for num_threads(rawspeed_get_number_of_processor_cores()) \
    schedule(static) default(none)
#endif
  for (int row = 0; row < mRaw->dim.y; ++row) {
    try {
      decompressRow(row);
    } catch (RawspeedException& err) {
      // Propagate the exception out of OpenMP magic.
      mRaw->setError(err.what());
    }
  }

  std::string firstErr;
  if (mRaw->isTooManyErrors(1, &firstErr)) {
    ThrowRDE("Too many errors encountered. Giving up. First Error:\n%s",
             firstErr.c_str());
  }
}

} // namespace rawspeed
<commit_msg>PanasonicDecompressorV6: do check that width is a multiple of 11<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2019 LibRaw LLC (info@libraw.org)
    Copyright (C) 2020 Roman Lebedev

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "decompressors/PanasonicDecompressorV6.h" // for PanasonicDecompre...
#include "common/Array2DRef.h"                     // for Array2DRef
#include "common/Point.h"                          // for iPoint2D
#include "common/RawImage.h"                       // for RawImage, RawImag...
#include "decoders/RawDecoderException.h"          // for ThrowRDE
#include <algorithm>                               // for copy_n
#include <array>
#include <cstdint> // for uint16_t, uint32_t
#include <cstdlib> // for free, malloc

namespace rawspeed {

constexpr int PanasonicDecompressorV6::PixelsPerBlock;
constexpr int PanasonicDecompressorV6::BytesPerBlock;

namespace {
struct pana_cs6_page_decoder {
  std::array<uint16_t, 14> pixelbuffer;
  unsigned char current = 0;

  explicit pana_cs6_page_decoder(const ByteStream& bs) {
    pixelbuffer[0] = (bs.peekByte(15) << 6) | (bs.peekByte(14) >> 2); // 14 bit
    pixelbuffer[1] = (((bs.peekByte(14) & 0x3) << 12) | (bs.peekByte(13) << 4) |
                      (bs.peekByte(12) >> 4)) &
                     0x3fff;
    pixelbuffer[2] = (bs.peekByte(12) >> 2) & 0x3;
    pixelbuffer[3] = ((bs.peekByte(12) & 0x3) << 8) | bs.peekByte(11);
    pixelbuffer[4] = (bs.peekByte(10) << 2) | (bs.peekByte(9) >> 6);
    pixelbuffer[5] = ((bs.peekByte(9) & 0x3f) << 4) | (bs.peekByte(8) >> 4);
    pixelbuffer[6] = (bs.peekByte(8) >> 2) & 0x3;
    pixelbuffer[7] = ((bs.peekByte(8) & 0x3) << 8) | bs.peekByte(7);
    pixelbuffer[8] = ((bs.peekByte(6) << 2) & 0x3fc) | (bs.peekByte(5) >> 6);
    pixelbuffer[9] = ((bs.peekByte(5) << 4) | (bs.peekByte(4) >> 4)) & 0x3ff;
    pixelbuffer[10] = (bs.peekByte(4) >> 2) & 0x3;
    pixelbuffer[11] = ((bs.peekByte(4) & 0x3) << 8) | bs.peekByte(3);
    pixelbuffer[12] =
        (((bs.peekByte(2) << 2) & 0x3fc) | bs.peekByte(1) >> 6) & 0x3ff;
    pixelbuffer[13] = ((bs.peekByte(1) << 4) | (bs.peekByte(0) >> 4)) & 0x3ff;
  }

  uint16_t nextpixel() { return pixelbuffer[current++]; }
};
} // namespace

PanasonicDecompressorV6::PanasonicDecompressorV6(const RawImage& img,
                                                 ByteStream input_)
    : mRaw(img), input(std::move(input_)) {
  if (mRaw->getCpp() != 1 || mRaw->getDataType() != TYPE_USHORT16 ||
      mRaw->getBpp() != sizeof(uint16_t))
    ThrowRDE("Unexpected component count / data type");

  if (!mRaw->dim.hasPositiveArea() ||
      mRaw->dim.x % PanasonicDecompressorV6::PixelsPerBlock != 0) {
    ThrowRDE("Unexpected image dimensions found: (%i; %i)", mRaw->dim.x,
             mRaw->dim.y);
  }

  const int blocksperrow =
      mRaw->dim.x / PanasonicDecompressorV6::PixelsPerBlock;
  const int bytesPerRow = PanasonicDecompressorV6::BytesPerBlock * blocksperrow;
  const int bytesTotal = bytesPerRow * mRaw->dim.y;
  input = input_.peekStream(bytesTotal);
}

void PanasonicDecompressorV6::decompressBlock(ByteStream* rowInput, int row,
                                              int col) const {
  const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());

  pana_cs6_page_decoder page(
      rowInput->getStream(PanasonicDecompressorV6::BytesPerBlock));

  std::array<unsigned, 2> oddeven = {0, 0};
  std::array<unsigned, 2> nonzero = {0, 0};
  unsigned pmul = 0;
  unsigned pixel_base = 0;
  for (int pix = 0; pix < PanasonicDecompressorV6::PixelsPerBlock;
       pix++, col++) {
    if (pix % 3 == 2) {
      uint16_t base = page.nextpixel();
      if (base > 3)
        ThrowRDE("Invariant failure");
      if (base == 3)
        base = 4;
      pixel_base = 0x200 << base;
      pmul = 1 << base;
    }
    uint16_t epixel = page.nextpixel();
    if (oddeven[pix % 2]) {
      epixel *= pmul;
      if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base)
        epixel += nonzero[pix % 2] - pixel_base;
      nonzero[pix % 2] = epixel;
    } else {
      oddeven[pix % 2] = epixel;
      if (epixel)
        nonzero[pix % 2] = epixel;
      else
        epixel = nonzero[pix % 2];
    }
    auto spix = static_cast<unsigned>(static_cast<int>(epixel) - 0xf);
    if (spix <= 0xffff)
      out(row, col) = spix & 0xffff;
    else {
      epixel = static_cast<int>(epixel + 0x7ffffff1) >> 0x1f;
      out(row, col) = epixel & 0x3fff;
    }
  }
}

void PanasonicDecompressorV6::decompressRow(int row) const {
  assert(mRaw->dim.x % PanasonicDecompressorV6::PixelsPerBlock == 0);
  const int blocksperrow =
      mRaw->dim.x / PanasonicDecompressorV6::PixelsPerBlock;
  const int bytesPerRow = PanasonicDecompressorV6::BytesPerBlock * blocksperrow;

  ByteStream rowInput = input.getSubStream(bytesPerRow * row, bytesPerRow);
  for (int rblock = 0, col = 0; rblock < blocksperrow;
       rblock++, col += PanasonicDecompressorV6::PixelsPerBlock)
    decompressBlock(&rowInput, row, col);
}

void PanasonicDecompressorV6::decompress() const {
#ifdef HAVE_OPENMP
#pragma omp parallel for num_threads(rawspeed_get_number_of_processor_cores()) \
    schedule(static) default(none)
#endif
  for (int row = 0; row < mRaw->dim.y; ++row) {
    try {
      decompressRow(row);
    } catch (RawspeedException& err) {
      // Propagate the exception out of OpenMP magic.
      mRaw->setError(err.what());
    }
  }

  std::string firstErr;
  if (mRaw->isTooManyErrors(1, &firstErr)) {
    ThrowRDE("Too many errors encountered. Giving up. First Error:\n%s",
             firstErr.c_str());
  }
}

} // namespace rawspeed
<|endoftext|>


<commit_before>#ifdef _MSC_VER
#  pragma warning(push)
//because LLVM IR Builder code is broken: e.g. Instructions.h:521-527
#  pragma warning(disable:4244)
#  pragma warning(disable:4800)
#  pragma warning(disable:4267)
#endif

#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Metadata.h>
#include <llvm/IR/DebugInfo.h>
#include <llvm/Analysis/CaptureTracking.h>
#include <llvm/Transforms/Utils/BasicBlockUtils.h>
#include <llvm/Support/Host.h>

#ifdef _MSC_VER
#  pragma warning(pop)
#endif

#include <stdio.h>
#include "codegen.h"

using namespace llvm;

char* LLVMGetHostCPUName()
{
  return strdup(sys::getHostCPUName().str().c_str());
}

void LLVMSetUnsafeAlgebra(LLVMValueRef inst)
{
  unwrap<Instruction>(inst)->setHasUnsafeAlgebra(true);
}

void LLVMSetReturnNoAlias(LLVMValueRef fun)
{
  unwrap<Function>(fun)->setDoesNotAlias(0);
}

static void print_transform(compile_t* c, Instruction* inst, const char* s)
{
  if(!c->opt->print_stats)
    return;

  Instruction* i = inst;

  while(i->getDebugLoc().getLine() == 0)
  {
    BasicBlock::iterator iter = i;

    if(++iter == i->getParent()->end())
    {
      return;
      // i = inst;
      // break;
    }

    i = iter;
  }

  DebugLoc loc = i->getDebugLoc();
  DIScope scope = DIScope(loc.getScope());
  MDLocation* at = cast_or_null<MDLocation>(loc.getInlinedAt());

  if(at != NULL)
  {
    DIScope scope_at = DIScope((MDNode*)at->getScope());

    errorf(NULL, "[%s] %s:%u:%u@%s:%u:%u: %s",
      i->getParent()->getParent()->getName().str().c_str(),
      scope.getFilename().str().c_str(), loc.getLine(), loc.getCol(),
      scope_at.getFilename().str().c_str(), at->getLine(), at->getColumn(), s);
  } else {
    errorf(NULL, "[%s] %s:%u:%u: %s",
      i->getParent()->getParent()->getName().str().c_str(),
      scope.getFilename().str().c_str(), loc.getLine(), loc.getCol(), s);
  }
}

static LLVMValueRef stack_alloc_inst(compile_t* c, LLVMValueRef inst)
{
  CallInst* call = dyn_cast_or_null<CallInst>(unwrap(inst));

  if(call == NULL)
    return inst;

  Function* fun = call->getCalledFunction();

  if(fun == NULL)
    return inst;

  if(fun->getName().compare("pony_alloc") != 0)
    return inst;

  c->opt->check.stats.heap_alloc++;

  if(PointerMayBeCaptured(call, true, false))
  {
    print_transform(c, call, "captured allocation");
    return inst;
  }

  // TODO: what if it's not constant? could we still alloca?
  // https://github.com/ldc-developers/ldc/blob/master/gen/passes/
  // GarbageCollect2Stack.cpp
  Value* size = call->getArgOperand(0);
  ConstantInt* int_size = dyn_cast_or_null<ConstantInt>(size);

  if(int_size == NULL)
  {
    print_transform(c, call, "variable size allocation");
    return inst;
  }

  size_t alloc_size = int_size->getZExtValue();

  // Limit stack allocations to 1 kb each.
  if(alloc_size > 1024)
  {
    print_transform(c, call, "large allocation");
    return inst;
  }

  // All alloca should happen in the entry block of a function.
  LLVMBasicBlockRef block = LLVMGetInstructionParent(inst);
  LLVMValueRef func = LLVMGetBasicBlockParent(block);
  block = LLVMGetFirstBasicBlock(func);
  LLVMValueRef first_inst = LLVMGetFirstInstruction(block);
  LLVMPositionBuilderBefore(c->builder, first_inst);

  LLVMValueRef len = LLVMConstInt(c->i64, alloc_size, false);
  LLVMValueRef alloca = LLVMBuildArrayAlloca(c->builder, c->i8, len, "");

  Instruction* alloca_value = unwrap<Instruction>(alloca);
  alloca_value->setDebugLoc(call->getDebugLoc());

  BasicBlock::iterator iter(call);
  ReplaceInstWithValue(call->getParent()->getInstList(), iter, alloca_value);

  c->opt->check.stats.heap_alloc--;
  c->opt->check.stats.stack_alloc++;

  print_transform(c, alloca_value, "stack allocation");

  return wrap(alloca_value);
}

static void stack_alloc_block(compile_t* c, LLVMBasicBlockRef block)
{
  LLVMValueRef inst = LLVMGetFirstInstruction(block);

  while(inst != NULL)
  {
    inst = stack_alloc_inst(c, inst);
    inst = LLVMGetNextInstruction(inst);
  }
}

static void stack_alloc_fun(compile_t* c, LLVMValueRef fun)
{
  LLVMBasicBlockRef block = LLVMGetFirstBasicBlock(fun);

  while(block != NULL)
  {
    stack_alloc_block(c, block);
    block = LLVMGetNextBasicBlock(block);
  }
}

void stack_alloc(compile_t* c)
{
  LLVMValueRef fun = LLVMGetFirstFunction(c->module);

  while(fun != NULL)
  {
    stack_alloc_fun(c, fun);
    fun = LLVMGetNextFunction(fun);
  }
}
<commit_msg>DIScope on LLVM 3.7 takes an MDScope<commit_after>#ifdef _MSC_VER
#  pragma warning(push)
//because LLVM IR Builder code is broken: e.g. Instructions.h:521-527
#  pragma warning(disable:4244)
#  pragma warning(disable:4800)
#  pragma warning(disable:4267)
#endif

#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Metadata.h>
#include <llvm/IR/DebugInfo.h>
#include <llvm/Analysis/CaptureTracking.h>
#include <llvm/Transforms/Utils/BasicBlockUtils.h>
#include <llvm/Support/Host.h>

#ifdef _MSC_VER
#  pragma warning(pop)
#endif

#include <stdio.h>
#include "codegen.h"

using namespace llvm;

char* LLVMGetHostCPUName()
{
  return strdup(sys::getHostCPUName().str().c_str());
}

void LLVMSetUnsafeAlgebra(LLVMValueRef inst)
{
  unwrap<Instruction>(inst)->setHasUnsafeAlgebra(true);
}

void LLVMSetReturnNoAlias(LLVMValueRef fun)
{
  unwrap<Function>(fun)->setDoesNotAlias(0);
}

static void print_transform(compile_t* c, Instruction* inst, const char* s)
{
  if(!c->opt->print_stats)
    return;

  Instruction* i = inst;

  while(i->getDebugLoc().getLine() == 0)
  {
    BasicBlock::iterator iter = i;

    if(++iter == i->getParent()->end())
      return;

    i = iter;
  }

  DebugLoc loc = i->getDebugLoc();

#if LLVM_VERSION_MAJOR > 3 || \
  (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 6)
  DIScope scope = DIScope(cast_or_null<MDScope>(loc.getScope()));
#else
  DIScope scope = DIScope(loc.getScope());
#endif

  MDLocation* at = cast_or_null<MDLocation>(loc.getInlinedAt());

  if(at != NULL)
  {
#if LLVM_VERSION_MAJOR > 3 || \
  (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 6)
    DIScope scope_at = DIScope(cast_or_null<MDScope>(at->getScope()));
#else
    DIScope scope_at = DIScope(cast_or_null<MDNode>(at->getScope()));
#endif

    errorf(NULL, "[%s] %s:%u:%u@%s:%u:%u: %s",
      i->getParent()->getParent()->getName().str().c_str(),
      scope.getFilename().str().c_str(), loc.getLine(), loc.getCol(),
      scope_at.getFilename().str().c_str(), at->getLine(), at->getColumn(), s);
  } else {
    errorf(NULL, "[%s] %s:%u:%u: %s",
      i->getParent()->getParent()->getName().str().c_str(),
      scope.getFilename().str().c_str(), loc.getLine(), loc.getCol(), s);
  }
}

static LLVMValueRef stack_alloc_inst(compile_t* c, LLVMValueRef inst)
{
  CallInst* call = dyn_cast_or_null<CallInst>(unwrap(inst));

  if(call == NULL)
    return inst;

  Function* fun = call->getCalledFunction();

  if(fun == NULL)
    return inst;

  if(fun->getName().compare("pony_alloc") != 0)
    return inst;

  c->opt->check.stats.heap_alloc++;

  if(PointerMayBeCaptured(call, true, false))
  {
    print_transform(c, call, "captured allocation");
    return inst;
  }

  // TODO: what if it's not constant? could we still alloca?
  // https://github.com/ldc-developers/ldc/blob/master/gen/passes/
  // GarbageCollect2Stack.cpp
  Value* size = call->getArgOperand(0);
  ConstantInt* int_size = dyn_cast_or_null<ConstantInt>(size);

  if(int_size == NULL)
  {
    print_transform(c, call, "variable size allocation");
    return inst;
  }

  size_t alloc_size = int_size->getZExtValue();

  // Limit stack allocations to 1 kb each.
  if(alloc_size > 1024)
  {
    print_transform(c, call, "large allocation");
    return inst;
  }

  // All alloca should happen in the entry block of a function.
  LLVMBasicBlockRef block = LLVMGetInstructionParent(inst);
  LLVMValueRef func = LLVMGetBasicBlockParent(block);
  block = LLVMGetFirstBasicBlock(func);
  LLVMValueRef first_inst = LLVMGetFirstInstruction(block);
  LLVMPositionBuilderBefore(c->builder, first_inst);

  LLVMValueRef len = LLVMConstInt(c->i64, alloc_size, false);
  LLVMValueRef alloca = LLVMBuildArrayAlloca(c->builder, c->i8, len, "");

  Instruction* alloca_value = unwrap<Instruction>(alloca);
  alloca_value->setDebugLoc(call->getDebugLoc());

  BasicBlock::iterator iter(call);
  ReplaceInstWithValue(call->getParent()->getInstList(), iter, alloca_value);

  c->opt->check.stats.heap_alloc--;
  c->opt->check.stats.stack_alloc++;

  print_transform(c, alloca_value, "stack allocation");

  return wrap(alloca_value);
}

static void stack_alloc_block(compile_t* c, LLVMBasicBlockRef block)
{
  LLVMValueRef inst = LLVMGetFirstInstruction(block);

  while(inst != NULL)
  {
    inst = stack_alloc_inst(c, inst);
    inst = LLVMGetNextInstruction(inst);
  }
}

static void stack_alloc_fun(compile_t* c, LLVMValueRef fun)
{
  LLVMBasicBlockRef block = LLVMGetFirstBasicBlock(fun);

  while(block != NULL)
  {
    stack_alloc_block(c, block);
    block = LLVMGetNextBasicBlock(block);
  }
}

void stack_alloc(compile_t* c)
{
  LLVMValueRef fun = LLVMGetFirstFunction(c->module);

  while(fun != NULL)
  {
    stack_alloc_fun(c, fun);
    fun = LLVMGetNextFunction(fun);
  }
}
<|endoftext|>