<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p10/procedures/hwp/memory/p10_omi_init.C $   */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2021                        */
/* [+] 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 p10_omi_init.C
/// @brief Finalize the OMI
///
// *HWP HW Maintainer: Benjamin Gass <bgass@us.ibm.com>
// *HWP FW Maintainer: Ilya Smirnov <ismirno@us.ibm.com>
// *HWP Consumed by: HB

#include <p10_omi_init.H>
#include <p10_omi_init_scom.H>
#include <p10_scom_mcc_4.H>
#include <p10_scom_mcc_d.H>
#include <lib/fir/p10_fir.H>
#include <mss_generic_attribute_getters.H>
#include <generic/memory/lib/utils/find.H>
#include <generic/memory/lib/generic_attribute_accessors_manual.H>
#include <lib/inband/exp_fw_adapter_properties.H>

///
/// @brief Run initfile to enable templates and set pacing.
/// @param[in] i_target MCC target
/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode p10_omi_init_scominit(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    fapi2::ReturnCode l_rc;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;

    FAPI_EXEC_HWP(l_rc, p10_omi_init_scom, i_target, FAPI_SYSTEM);

    if (l_rc)
    {
        FAPI_ERR("Error from p10.omi_init.scom.initfile");
        fapi2::current_err = l_rc;
    }

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}

///
/// @brief Check and enable supported templates
/// @param[in] i_target MCC target
/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode p10_omi_init_enable_templates(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    fapi2::ATTR_PROC_ENABLE_DL_TMPL_1_Type l_enable_tmpl_1;
    fapi2::ATTR_PROC_ENABLE_DL_TMPL_4_Type l_enable_tmpl_4;
    fapi2::ATTR_PROC_ENABLE_DL_TMPL_7_Type l_enable_tmpl_7;
    fapi2::buffer<uint64_t> l_data;

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_ENABLE_DL_TMPL_1,
                           i_target,
                           l_enable_tmpl_1),
             "Error from FAPI_ATTR_GET (ATTR_PROC_ENABLE_DL_TMPL_1)");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_ENABLE_DL_TMPL_4,
                           i_target,
                           l_enable_tmpl_4),
             "Error from FAPI_ATTR_GET (ATTR_PROC_ENABLE_DL_TMPL_4)");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_ENABLE_DL_TMPL_7,
                           i_target,
                           l_enable_tmpl_7),
             "Error from FAPI_ATTR_GET (ATTR_PROC_ENABLE_DL_TMPL_7)");

    FAPI_ASSERT(l_enable_tmpl_1 != 0,
                fapi2::P10_DOWNSTREAM_TMPL1_REQUIRED_ERR()
                .set_TARGET(i_target),
                "Downstream template 1 is required.");

    FAPI_ASSERT(l_enable_tmpl_4 != 0 || l_enable_tmpl_7 != 0,
                fapi2::P10_DOWNSTREAM_TMPL4OR7_REQUIRED_ERR()
                .set_TARGET(i_target),
                "Downstream template 4 and/or 7 is required.");

    //Turn off temp0_only
    FAPI_TRY(scomt::mcc::GET_DSTL_DSTLCFG(i_target, l_data));
    scomt::mcc::CLEAR_DSTL_DSTLCFG_TMPL0_ONLY(l_data);
    FAPI_TRY(scomt::mcc::PUT_DSTL_DSTLCFG(i_target, l_data));

fapi_try_exit:

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}

///
/// @brief Enable ibm buffer chip low latency mode
///
/// @param[in] i_target                 p10 channel to work on
///
/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode p10_omi_init_enable_lol(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    fapi2::buffer<uint64_t> l_data;
    std::vector<fapi2::Target<fapi2::TARGET_TYPE_OMI>> l_omi_targets;
    fapi2::ATTR_CHIP_UNIT_POS_Type l_omi_pos;

    l_omi_targets = i_target.getChildren<fapi2::TARGET_TYPE_OMI>();

    FAPI_TRY(scomt::mcc::GET_USTL_USTLCFG(i_target, l_data));

    for (const auto l_omi_target : l_omi_targets)
    {
        FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS,
                                l_omi_target,
                                l_omi_pos));

        // Set for proper channel
        if ((l_omi_pos % 2) == 0)
        {
            scomt::mcc::SET_USTL_USTLCFG_IBM_BUFFER_CHIP_CHANA_ENABLE(l_data);
        }
        else
        {
            scomt::mcc::SET_USTL_USTLCFG_IBM_BUFFER_CHIP_CHANB_ENABLE(l_data);
        }
    }

    FAPI_TRY(scomt::mcc::PUT_USTL_USTLCFG(i_target, l_data));

fapi_try_exit:

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}

// Putting unmask function in mss::unmask for consistency with p9/EXPL/etc.
namespace mss
{
namespace unmask
{

///
/// @brief Initialize Axone DSTLFIR mask bits after p9a omi init
/// @param[in] i_target MCC target to find targets to initialize
/// @return fapi2:ReturnCode FAPI2_RC_SUCCESS if success, else error code
///
fapi2::ReturnCode after_p10_omi_init(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    // Unmask MC_OMI_FIR per FIR XML spec
    const auto& l_mc = mss::find_target<fapi2::TARGET_TYPE_MC>(i_target);
    FAPI_TRY(after_p10_omi_init_omi_fir_helper(l_mc));

    // Unmask MCC DSTLFIR per FIR XML spec
    FAPI_TRY(after_p10_omi_init_dstlfir_helper(i_target));

    // Unmask MCC USTLFIR per FIR XML spec
    FAPI_TRY(after_p10_omi_init_ustlfir_helper(i_target));

fapi_try_exit:

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}

} // end unmask ns
} // end mss ns

///
/// @brief Finalize the OMI
/// @param[in] i_target MCC target
/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode p10_omi_init(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    uint8_t l_enable_fir_unmasking = 0;
    uint8_t l_sim = 0;

    FAPI_TRY(p10_omi_init_scominit(i_target));
    FAPI_TRY(p10_omi_init_enable_templates(i_target));
    FAPI_TRY(p10_omi_init_enable_lol(i_target));
    FAPI_TRY(mss::attr::get_is_simulation(l_sim));

    // Perform fir unmasking if attribute is set to enabled, default disabled
    FAPI_TRY(mss::attr::get_enable_fir_unmasking(l_enable_fir_unmasking));

    if (l_enable_fir_unmasking == fapi2::ENUM_ATTR_ENABLE_FIR_UNMASKING_ENABLED)
    {
        FAPI_TRY(mss::unmask::after_p10_omi_init(i_target));
    }

#ifdef __HOSTBOOT_MODULE

    // NOTE: We're calling run_fw_adapter_properties_get here so we get the Explorer FW version into attributes
    // for use in the FFDC in the update_omi_firmware step. We cannot run this in Cronus here because we haven't yet
    // transitioned Explorer access to mmio/inband mode so our endianness attributes are not set correctly.
    if (!l_sim)
    {
        for (const auto& l_omi : mss::find_targets<fapi2::TARGET_TYPE_OMI>(i_target))
        {
            for (const auto& l_ocmb : mss::find_targets<fapi2::TARGET_TYPE_OCMB_CHIP>(l_omi))
            {
                bool l_image_a_good = true;
                bool l_image_b_good = true;
                bool l_mfg_thresholds = false;

                // Check MNFG THRESHOLDS Policy flag
                FAPI_TRY(mss::check_mfg_flag(fapi2::ENUM_ATTR_MFG_FLAGS_MNFG_THRESHOLDS, l_mfg_thresholds));

                // Print and record Explorer FW version info into attributes
                FAPI_INF("run_fw_adapter_properties_get %s", mss::c_str(l_ocmb));
                FAPI_TRY( mss::exp::ib::run_fw_adapter_properties_get(l_ocmb, l_image_a_good, l_image_b_good) );

                // Assert MNFG_SPI_FLASH_AUTHENTICATION_FAIL if fw_adapter_properties says one of the images is bad
                if (!l_image_a_good || !l_image_b_good)
                {
                    // Note: there is no way we could see both images bad here, because then we would not have booted this far
                    const uint8_t l_image_num = !l_image_a_good ? 0 : 1;

                    if (l_mfg_thresholds)
                    {
                        // In MFG test, this fail should call out and deconfigure the DIMM, and fail the procedure
                        FAPI_ASSERT(false,
                                    fapi2::EXP_SPI_FLASH_AUTH_FAIL_MFG().
                                    set_OCMB_TARGET(l_ocmb).
                                    set_IMAGE(l_image_num).
                                    set_EXP_ACTIVE_LOG_SIZE(4096),
                                    "%s Explorer SPI flash authentication failed for image %s in MFG test",
                                    mss::c_str(l_ocmb), (!l_image_a_good ? "A" : "B"));
                    }
                    else
                    {
                        // In normal IPL, this fail should produce a recovered log and pass the procedure
                        FAPI_ASSERT_NOEXIT(false,
                                           fapi2::EXP_SPI_FLASH_AUTH_FAIL(fapi2::FAPI2_ERRL_SEV_RECOVERED).
                                           set_OCMB_TARGET(l_ocmb).
                                           set_IMAGE(l_image_num).
                                           set_EXP_ACTIVE_LOG_SIZE(4096),
                                           "%s Explorer SPI flash authentication failed for image %s",
                                           mss::c_str(l_ocmb), (!l_image_a_good ? "A" : "B"));

                        // FAPI_ASSERT_NOEXIT already logs the error, so set current_err back to success so we pass the procedure
                        fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
                    }
                }
            }
        }
    }

#endif

fapi_try_exit:

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}
<commit_msg>Remove fw_adapter_properties call from p10_omi_init<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p10/procedures/hwp/memory/p10_omi_init.C $   */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2021                        */
/* [+] 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 p10_omi_init.C
/// @brief Finalize the OMI
///
// *HWP HW Maintainer: Benjamin Gass <bgass@us.ibm.com>
// *HWP FW Maintainer: Ilya Smirnov <ismirno@us.ibm.com>
// *HWP Consumed by: HB

#include <p10_omi_init.H>
#include <p10_omi_init_scom.H>
#include <p10_scom_mcc_4.H>
#include <p10_scom_mcc_d.H>
#include <lib/fir/p10_fir.H>
#include <mss_generic_attribute_getters.H>
#include <generic/memory/lib/utils/find.H>

///
/// @brief Run initfile to enable templates and set pacing.
/// @param[in] i_target MCC target
/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode p10_omi_init_scominit(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    fapi2::ReturnCode l_rc;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;

    FAPI_EXEC_HWP(l_rc, p10_omi_init_scom, i_target, FAPI_SYSTEM);

    if (l_rc)
    {
        FAPI_ERR("Error from p10.omi_init.scom.initfile");
        fapi2::current_err = l_rc;
    }

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}

///
/// @brief Check and enable supported templates
/// @param[in] i_target MCC target
/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode p10_omi_init_enable_templates(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    fapi2::ATTR_PROC_ENABLE_DL_TMPL_1_Type l_enable_tmpl_1;
    fapi2::ATTR_PROC_ENABLE_DL_TMPL_4_Type l_enable_tmpl_4;
    fapi2::ATTR_PROC_ENABLE_DL_TMPL_7_Type l_enable_tmpl_7;
    fapi2::buffer<uint64_t> l_data;

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_ENABLE_DL_TMPL_1,
                           i_target,
                           l_enable_tmpl_1),
             "Error from FAPI_ATTR_GET (ATTR_PROC_ENABLE_DL_TMPL_1)");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_ENABLE_DL_TMPL_4,
                           i_target,
                           l_enable_tmpl_4),
             "Error from FAPI_ATTR_GET (ATTR_PROC_ENABLE_DL_TMPL_4)");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_ENABLE_DL_TMPL_7,
                           i_target,
                           l_enable_tmpl_7),
             "Error from FAPI_ATTR_GET (ATTR_PROC_ENABLE_DL_TMPL_7)");

    FAPI_ASSERT(l_enable_tmpl_1 != 0,
                fapi2::P10_DOWNSTREAM_TMPL1_REQUIRED_ERR()
                .set_TARGET(i_target),
                "Downstream template 1 is required.");

    FAPI_ASSERT(l_enable_tmpl_4 != 0 || l_enable_tmpl_7 != 0,
                fapi2::P10_DOWNSTREAM_TMPL4OR7_REQUIRED_ERR()
                .set_TARGET(i_target),
                "Downstream template 4 and/or 7 is required.");

    //Turn off temp0_only
    FAPI_TRY(scomt::mcc::GET_DSTL_DSTLCFG(i_target, l_data));
    scomt::mcc::CLEAR_DSTL_DSTLCFG_TMPL0_ONLY(l_data);
    FAPI_TRY(scomt::mcc::PUT_DSTL_DSTLCFG(i_target, l_data));

fapi_try_exit:

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}

///
/// @brief Enable ibm buffer chip low latency mode
///
/// @param[in] i_target                 p10 channel to work on
///
/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode p10_omi_init_enable_lol(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    fapi2::buffer<uint64_t> l_data;
    std::vector<fapi2::Target<fapi2::TARGET_TYPE_OMI>> l_omi_targets;
    fapi2::ATTR_CHIP_UNIT_POS_Type l_omi_pos;

    l_omi_targets = i_target.getChildren<fapi2::TARGET_TYPE_OMI>();

    FAPI_TRY(scomt::mcc::GET_USTL_USTLCFG(i_target, l_data));

    for (const auto l_omi_target : l_omi_targets)
    {
        FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS,
                                l_omi_target,
                                l_omi_pos));

        // Set for proper channel
        if ((l_omi_pos % 2) == 0)
        {
            scomt::mcc::SET_USTL_USTLCFG_IBM_BUFFER_CHIP_CHANA_ENABLE(l_data);
        }
        else
        {
            scomt::mcc::SET_USTL_USTLCFG_IBM_BUFFER_CHIP_CHANB_ENABLE(l_data);
        }
    }

    FAPI_TRY(scomt::mcc::PUT_USTL_USTLCFG(i_target, l_data));

fapi_try_exit:

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}

// Putting unmask function in mss::unmask for consistency with p9/EXPL/etc.
namespace mss
{
namespace unmask
{

///
/// @brief Initialize Axone DSTLFIR mask bits after p9a omi init
/// @param[in] i_target MCC target to find targets to initialize
/// @return fapi2:ReturnCode FAPI2_RC_SUCCESS if success, else error code
///
fapi2::ReturnCode after_p10_omi_init(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    // Unmask MC_OMI_FIR per FIR XML spec
    const auto& l_mc = mss::find_target<fapi2::TARGET_TYPE_MC>(i_target);
    FAPI_TRY(after_p10_omi_init_omi_fir_helper(l_mc));

    // Unmask MCC DSTLFIR per FIR XML spec
    FAPI_TRY(after_p10_omi_init_dstlfir_helper(i_target));

    // Unmask MCC USTLFIR per FIR XML spec
    FAPI_TRY(after_p10_omi_init_ustlfir_helper(i_target));

fapi_try_exit:

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}

} // end unmask ns
} // end mss ns

///
/// @brief Finalize the OMI
/// @param[in] i_target MCC target
/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode p10_omi_init(const fapi2::Target<fapi2::TARGET_TYPE_MCC>& i_target)
{
    uint8_t l_enable_fir_unmasking = 0;

    FAPI_TRY(p10_omi_init_scominit(i_target));
    FAPI_TRY(p10_omi_init_enable_templates(i_target));
    FAPI_TRY(p10_omi_init_enable_lol(i_target));

    // Perform fir unmasking if attribute is set to enabled, default disabled
    FAPI_TRY(mss::attr::get_enable_fir_unmasking(l_enable_fir_unmasking));

    if (l_enable_fir_unmasking == fapi2::ENUM_ATTR_ENABLE_FIR_UNMASKING_ENABLED)
    {
        FAPI_TRY(mss::unmask::after_p10_omi_init(i_target));
    }

fapi_try_exit:

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    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/lib/freq/sync.H $   */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file synch.H
/// @brief Synchronous function implementations
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: HB:FSP

#ifndef _MSS_SYNC_H_
#define _MSS_SYNC_H_

#include <map>
#include <vector>

#include <fapi2.H>

namespace mss
{

enum class speed_equality : uint8_t
{
    NOT_EQUAL_DIMM_SPEEDS = 0, ///< denotes all DIMMs don't have the same speed
    EQUAL_DIMM_SPEEDS = 1, ///< denotes all DIMMs have the same speed
};

// DDR4 speed NIMBUS supports
static const std::vector<uint32_t> NIMBUS_SUPPORTED_FREQS =
{
    fapi2::ENUM_ATTR_MSS_FREQ_MT1866,
    fapi2::ENUM_ATTR_MSS_FREQ_MT2133,
    fapi2::ENUM_ATTR_MSS_FREQ_MT2400,
    fapi2::ENUM_ATTR_MSS_FREQ_MT2666,
};

///
/// @brief Checks to see if a passed in value could be a valid nest frequency
/// @param[in] i_proposed_freq a frequency value that is to be checked
/// @return boolean true, false whether the value is a valid nest frequency
///
inline bool is_nest_freq_valid (const uint64_t i_proposed_freq)
{
    std::vector<uint64_t> l_nest_freqs_supported = { fapi2::ENUM_ATTR_FREQ_PB_MHZ_1600,
                                                     fapi2::ENUM_ATTR_FREQ_PB_MHZ_1866,
                                                     fapi2::ENUM_ATTR_FREQ_PB_MHZ_2000,
                                                     fapi2::ENUM_ATTR_FREQ_PB_MHZ_2133,
                                                     fapi2::ENUM_ATTR_FREQ_PB_MHZ_2400
                                                   };

    std::sort(l_nest_freqs_supported.begin(), l_nest_freqs_supported.end());
    return ( std::binary_search(l_nest_freqs_supported.begin(), l_nest_freqs_supported.end(), i_proposed_freq) );
}

///
/// @brief Retrieves a mapping of MSS frequency values per mcbist target
/// @param[in] i_targets vector of controller targets
/// @param[out] o_freq_map dimm speed map <key, value> = (mcbist target, frequency)
/// @param[out] o_is_speed_equal holds whether map dimm speed is equal
/// @return FAPI2_RC_SUCCESS iff successful
///
fapi2::ReturnCode dimm_speed_map(const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCBIST> >& i_targets,
                                 std::map< fapi2::Target<fapi2::TARGET_TYPE_MCBIST>, uint64_t >& o_freq_map,
                                 speed_equality& o_is_speed_equal);

///
/// @brief Helper function to deconfigure MCS targets connected to MCBIST
/// @param[in] i_target the controller target
/// @param[in] i_dimm_speed dimm speed in MT/s
/// @param[in] i_nest_freq nest freq in MHz
/// @return true if hardware was deconfigured
///
bool deconfigure(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                 const uint64_t i_dimm_speed,
                 const uint32_t i_nest_freq);

///
/// @brief Selects synchronous mode and performs requirements enforced by ATTR_REQUIRED_SYNCH_MODE
/// @param[in] i_freq_map dimm speed mapping
/// @param[in] i_equal_dimm_speed tracks whether map has equal dimm speeds
/// @param[in] i_nest_freq nest frequency
/// @param[in] i_required_sync_mode system policy to enforce synchronous mode
/// @param[out] o_selected_sync_mode final synchronous mode
/// @param[out] o_selected_freq final freq selected, only valid if final sync mode is in-sync
/// @return FAPI2_RC_SUCCESS iff successful
///
fapi2::ReturnCode select_sync_mode(const std::map< fapi2::Target<fapi2::TARGET_TYPE_MCBIST>, uint64_t >& i_freq_map,
                                   const speed_equality i_equal_dimm_speed,
                                   const uint32_t i_nest_freq,
                                   const uint8_t i_required_sync_mode,
                                   uint8_t& o_selected_sync_mode,
                                   uint64_t& o_selected_freq);

///
/// @brief Return whether a given freq is supported
/// @param[in] a freq to check for
/// @param[in] reference to a std::vector of supported freqs (sorted)
/// @return bool true iff input freq is supported
///
bool is_freq_supported(const uint32_t i_freq, const std::vector<uint32_t>& i_freqs);

/// @brief Create a vector of support freq based on VPD config
/// @param[in] MCBIST target for which to get the DIMM configs
/// @param[out] reference to a std::vector of supported VPD frequencies
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                                       std::vector<uint32_t>& o_vpd_supported_freqs);

///
/// @brief Removes frequencies unsupported by SPD from a sorted list of supported freqs -- helper function for testing
/// @param[in] i_target the MCBIST target
/// @param[in] i_highest_freq largest SPD supported freq
/// @param[in,out] io_freqs std::vector of VPD supported freqs (sorted)
///
void rm_unsupported_spd_freqs(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                              const uint32_t l_current_freq,
                              std::vector<uint32_t>& io_freqs);

///
/// @brief Retrieves largest supported frequency the MC supports due to DIMM SPD
/// @param[in] i_target the MCBIST target
/// @param[out] o_highest_freq the largest SPD supported freq
/// @return FAPI2_RC_SUCCESS iff okay
///
fapi2::ReturnCode largest_spd_supported_freq(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
        uint32_t& o_highest_freq);

///
/// @brief Create and sort a vector of supported MT/s (freq)
/// @param[in] i_target MCA target for which to get the DIMM configs
/// @param[out] o_freqs reference to a std::vector to put the sorted vector
/// @return FAPI2_RC_SUCCESS iff ok
/// @note Taken from VPD supported freqs. The result is sorted so such that the min
/// supported freq is std::vector<>.begin and the max is std::vector<>.end - 1. You can
/// search the resulting vector for valid frequencies as it is sorted.
///
fapi2::ReturnCode supported_freqs(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                                  std::vector<uint32_t>& o_freqs);

///
/// @brief Create and sort a vector of supported MT/s (freq) - helper for testing purposes
/// @param[in] MCA target for which to get the DIMM configs
/// @param[in] vector of VPD freqs
/// @param[in] vector of max allowed freqs
/// @param[in] bool whether or not we're forced into sync mode
/// @param[out] reference to a std::vector to put the sorted vector
/// @return FAPI2_RC_SUCCESS iff ok
/// @note the attributes which drive this are read-only so they're hard to change when
/// testing. So this helper allows us to use the attributes for the main path but
/// have a path for testing (DFT I think the cool kids call it.)
///
fapi2::ReturnCode supported_freqs_helper(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
        const std::vector<uint32_t>& i_vpd_freqs,
        const std::vector<uint32_t>& i_max_freqs,
        const bool i_req_sync_mode,
        std::vector<uint32_t>& o_freqs);
}// mss

#endif
<commit_msg>Change mss_freq algorithm to deconfigure ports to achieve common DIMM freq<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.H $   */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file synch.H
/// @brief Synchronous function implementations
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: HB:FSP

#ifndef _MSS_SYNC_H_
#define _MSS_SYNC_H_

#include <map>
#include <vector>

#include <fapi2.H>

namespace mss
{

enum class speed_equality : uint8_t
{
    NOT_EQUAL_DIMM_SPEEDS = 0, ///< denotes all DIMMs don't have the same speed
    EQUAL_DIMM_SPEEDS = 1, ///< denotes all DIMMs have the same speed
};

// DDR4 speed NIMBUS supports
static const std::vector<uint32_t> NIMBUS_SUPPORTED_FREQS =
{
    fapi2::ENUM_ATTR_MSS_FREQ_MT1866,
    fapi2::ENUM_ATTR_MSS_FREQ_MT2133,
    fapi2::ENUM_ATTR_MSS_FREQ_MT2400,
    fapi2::ENUM_ATTR_MSS_FREQ_MT2666,
};

///
/// @brief Checks to see if a passed in value could be a valid nest frequency
/// @param[in] i_proposed_freq a frequency value that is to be checked
/// @return boolean true, false whether the value is a valid nest frequency
///
inline bool is_nest_freq_valid (const uint64_t i_proposed_freq)
{
    std::vector<uint64_t> l_nest_freqs_supported = { fapi2::ENUM_ATTR_FREQ_PB_MHZ_1600,
                                                     fapi2::ENUM_ATTR_FREQ_PB_MHZ_1866,
                                                     fapi2::ENUM_ATTR_FREQ_PB_MHZ_2000,
                                                     fapi2::ENUM_ATTR_FREQ_PB_MHZ_2133,
                                                     fapi2::ENUM_ATTR_FREQ_PB_MHZ_2400
                                                   };

    std::sort(l_nest_freqs_supported.begin(), l_nest_freqs_supported.end());
    return ( std::binary_search(l_nest_freqs_supported.begin(), l_nest_freqs_supported.end(), i_proposed_freq) );
}

///
/// @class freq_scoreboard
/// @brief class that encapsulates MCA supported frequencies
///
class freq_scoreboard
{
    public:
        ///
        /// @brief Create a new frequency scoreboard
        ///
        freq_scoreboard()
        {
            iv_freq_mca_supported = std::vector<std::vector<bool>>(PORTS_PER_MCBIST,
                                    std::vector<bool>(NIMBUS_SUPPORTED_FREQS.size(), true));
        }

        ///
        /// @brief default destructor
        ///
        ~freq_scoreboard() = default;

        ///
        /// @brief Remove frequencies above a limit from the scoreboard
        /// @param[in] i_port_pos position index of port within parent MCBIST
        /// @param[in] i_freq_limit upper limit for frequency
        /// @return FAPI2_RC_SUCCESS if successful
        ///
        fapi2::ReturnCode remove_freqs_above_limit(const uint64_t i_port_pos,
                const uint32_t i_freq_limit);

        ///
        /// @brief Remove frequencies above a limit from the scoreboard
        /// @param[in] i_port_pos position index of port within parent MCBIST
        /// @param[in] i_freq_limits reference to vector of upper limits for frequency per port
        /// @return FAPI2_RC_SUCCESS if successful
        ///
        fapi2::ReturnCode remove_freqs_above_limit(const uint64_t i_port_pos,
                const std::vector<uint32_t> i_freq_limits);

        ///
        /// @brief Remove frequencies not on a given list from the scoreboard
        /// @param[in] i_port_pos position index of port within parent MCBIST
        /// @param[in] i_freq_list vector of supported frequencies
        /// @return FAPI2_RC_SUCCESS if successful
        ///
        fapi2::ReturnCode remove_freqs_not_on_list(const uint64_t i_port_pos,
                const std::vector<uint32_t>& i_freq_list);

        ///
        /// @brief Return the maximum supported frequency for a given port
        /// @param[in] i_port_pos position index of port within parent MCBIST
        /// @param[out] o_freq max supported frequency
        /// @return FAPI2_RC_SUCCESS if successful
        ///
        fapi2::ReturnCode max_supported_freq(const uint64_t i_port_pos,
                                             uint32_t& o_freq) const;

        ///
        /// @brief Return a list of supported frequencies for a given port
        /// @param[in] i_port_pos position index of port within parent MCBIST
        /// @param[out] o_freq vector of supported frequencies
        /// @return FAPI2_RC_SUCCESS if successful
        ///
        fapi2::ReturnCode supported_freqs(const uint64_t i_port_pos,
                                          std::vector<uint32_t>& o_freqs) const;

        ///
        /// @brief Resolve frequency scoreboard by deconfiguring any non-conforming ports
        /// and return a list of the supported frequencies
        /// @param[in] i_target MCBIST target
        /// @param[in] i_req_sync_mode bool whether or not we're forced into sync mode
        /// @param[in] i_vpd_supported_freqs vector of hardware supported freqs -- from VPD
        /// @param[out] o_deconfigured vector of port positions that were deconfigured by this function
        /// @param[out] o_freqs vector of frequencies supported by all ports
        /// @return FAPI2_RC_SUCCESS if successful
        ///
        fapi2::ReturnCode resolve(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                                  const bool i_req_sync_mode,
                                  const std::vector<std::vector<uint32_t>>& i_vpd_supported_freqs,
                                  std::vector<uint8_t>& o_deconfigured,
                                  std::vector<uint32_t>& o_freqs);

    private:
        std::vector<std::vector<bool>> iv_freq_mca_supported;

};

///
/// @brief Retrieves a mapping of MSS frequency values per mcbist target
/// @param[in] i_targets vector of controller targets
/// @param[out] o_freq_map dimm speed map <key, value> = (mcbist target, frequency)
/// @param[out] o_is_speed_equal holds whether map dimm speed is equal
/// @return FAPI2_RC_SUCCESS iff successful
///
fapi2::ReturnCode dimm_speed_map(const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCBIST> >& i_targets,
                                 std::map< fapi2::Target<fapi2::TARGET_TYPE_MCBIST>, uint64_t >& o_freq_map,
                                 speed_equality& o_is_speed_equal);

///
/// @brief Helper function to deconfigure MCS targets connected to MCBIST
/// @param[in] i_target the controller target
/// @param[in] i_dimm_speed dimm speed in MT/s
/// @param[in] i_nest_freq nest freq in MHz
/// @return true if hardware was deconfigured
///
bool deconfigure(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                 const uint64_t i_dimm_speed,
                 const uint32_t i_nest_freq);

///
/// @brief Selects synchronous mode and performs requirements enforced by ATTR_REQUIRED_SYNCH_MODE
/// @param[in] i_freq_map dimm speed mapping
/// @param[in] i_equal_dimm_speed tracks whether map has equal dimm speeds
/// @param[in] i_nest_freq nest frequency
/// @param[in] i_required_sync_mode system policy to enforce synchronous mode
/// @param[out] o_selected_sync_mode final synchronous mode
/// @param[out] o_selected_freq final freq selected, only valid if final sync mode is in-sync
/// @return FAPI2_RC_SUCCESS iff successful
///
fapi2::ReturnCode select_sync_mode(const std::map< fapi2::Target<fapi2::TARGET_TYPE_MCBIST>, uint64_t >& i_freq_map,
                                   const speed_equality i_equal_dimm_speed,
                                   const uint32_t i_nest_freq,
                                   const uint8_t i_required_sync_mode,
                                   uint8_t& o_selected_sync_mode,
                                   uint64_t& o_selected_freq);

///
/// @brief Create a vector of support freq based on VPD config
/// @param[in] i_target MCBIST target for which to get the DIMM configs
/// @param[out] reference to a 2 dimensional std::vector of supported VPD frequencies for each MCA
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                                       std::vector<std::vector<uint32_t>>& o_vpd_supported_freqs);

///
/// @brief Retrieves max frequency each port supports due to DIMM SPD
/// @param[in] i_target the MCBIST target
/// @param[out] o_supported_freqs reference to vector of max SPD supported freq for each port
/// @return FAPI2_RC_SUCCESS iff okay
///
fapi2::ReturnCode spd_supported_freq(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                                     std::vector<uint32_t>& o_supported_freqs);

///
/// @brief Create and sort a vector of supported MT/s (freq)
/// @param[in] i_target MCA target for which to get the DIMM configs
/// @param[out] o_freqs reference to a std::vector to put the sorted vector
/// @return FAPI2_RC_SUCCESS iff ok
/// @note Taken from VPD supported freqs. The result is sorted so such that the min
/// supported freq is std::vector<>.begin and the max is std::vector<>.end - 1. You can
/// search the resulting vector for valid frequencies as it is sorted.
///
fapi2::ReturnCode supported_freqs(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                                  std::vector<uint32_t>& o_freqs);

///
/// @brief Update supported frequency scoreboard according to MRW/config limits
/// @param[in] i_target MCBIST target for which to get the DIMM configs
/// @param[in] i_max_mrw_freqs vector of max allowed freqs
/// @param[in,out] io_scoreboard scoreboard of MCA targets supporting each frequency
/// @return FAPI2_RC_SUCCESS iff ok
/// @note the attributes which drive this are read-only so they're hard to change when
/// testing. So this helper allows us to use the attributes for the main path but
/// have a path for testing
///
fapi2::ReturnCode limit_freq_by_mrw(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                                    const std::vector<uint32_t>& i_max_mrw_freqs,
                                    freq_scoreboard& io_scoreboard);

///
/// @brief Update supported frequency scoreboard according to VPD limits
/// @param[in] i_target MCBIST target for which to get the DIMM configs
/// @param[in] i_hw_freqs vector of hardware supported freqs -- from VPD
/// @param[in,out] io_scoreboard scoreboard of MCA targets supporting each frequency
/// @return FAPI2_RC_SUCCESS iff ok
/// @note the attributes which drive this are read-only so they're hard to change when
/// testing. So this helper allows us to use the attributes for the main path but
/// have a path for testing
///
fapi2::ReturnCode limit_freq_by_vpd(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                                    const std::vector<std::vector<uint32_t>>& i_hw_freqs,
                                    freq_scoreboard& io_scoreboard);

///
/// @brief Update supported frequency scoreboard according to SPD limits
/// @param[in] i_target MCBIST target for which to get the DIMM configs
/// @param[in] i_hw_freqs vector of hardware supported freqs -- from SPD
/// @param[in,out] io_scoreboard scoreboard of MCA targets supporting each frequency
/// @return FAPI2_RC_SUCCESS iff ok
/// @note the attributes which drive this are read-only so they're hard to change when
/// testing. So this helper allows us to use the attributes for the main path but
/// have a path for testing
///
fapi2::ReturnCode limit_freq_by_spd(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
                                    const std::vector<uint32_t>& i_hw_freqs,
                                    freq_scoreboard& io_scoreboard);

}// mss

#endif
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_switch_cfsim.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_switch_cfsim.C
///
/// @brief Switch the FSI bus control back to the FSP
//------------------------------------------------------------------------------
// *HWP HW Owner        : Anusha Reddy Rangareddygari <anusrang@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           : 1
// *HWP Consumed by     : HB
//------------------------------------------------------------------------------

//## auto_generated
#include "p9_switch_cfsim.H"

fapi2::ReturnCode p9_switch_cfsim(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chiplet)
{
    FAPI_DBG("Entering ...");

    FAPI_DBG("Exiting ...");

    return fapi2::FAPI2_RC_SUCCESS;

}
<commit_msg>Update hardware procedure metadata<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_switch_cfsim.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_switch_cfsim.C
///
/// @brief Switch the FSI bus control back to the FSP
//------------------------------------------------------------------------------
// *HWP HW Owner        : Anusha Reddy Rangareddygari <anusrang@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           : 3
// *HWP Consumed by     : HB
//------------------------------------------------------------------------------

//## auto_generated
#include "p9_switch_cfsim.H"

fapi2::ReturnCode p9_switch_cfsim(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chiplet)
{
    FAPI_DBG("Entering ...");

    FAPI_DBG("Exiting ...");

    return fapi2::FAPI2_RC_SUCCESS;

}
<|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 "rawspeedconfig.h" // for HAVE_OPENMP
#include "decompressors/PanasonicDecompressorV6.h"
#include "common/Array2DRef.h"            // for Array2DRef
#include "common/Common.h"                // for rawspeed_get_number_of_pro...
#include "common/Point.h"                 // for iPoint2D
#include "common/RawImage.h"              // for RawImageData, RawImage
#include "common/RawspeedException.h"     // for RawspeedException
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include <array>                          // for array
#include <cassert>                        // for assert
#include <cstdint>                        // for uint16_t
#include <string>                         // for string
#include <utility>                        // for move

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) {
    // The bit packing scheme here is actually just 128-bit little-endian int,
    // that we consume from the high bits to low bits, with no padding.
    // It is really tempting to refactor this using proper BitPump, but so far
    // that results in disappointing performance, especially because those
    // '2 bit' pixels aren't the 2-bit pixels we look for when `pix % 3 == 2`.

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

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

PanasonicDecompressorV6::PanasonicDecompressorV6(const RawImage& img,
                                                 const ByteStream& input_)
    : mRaw(img) {
  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);
  }

  // How many blocks are needed for the given image size?
  const auto numBlocks = mRaw->dim.area() / PixelsPerBlock;

  // How many full blocks does the input contain? This is truncating division.
  const auto haveBlocks = input_.getRemainSize() / BytesPerBlock;

  // Does the input contain enough blocks?
  if (haveBlocks < numBlocks)
    ThrowRDE("Insufficient count of input blocks for a given image");

  // We only want those blocks we need, no extras.
  input = input_.peekStream(numBlocks, BytesPerBlock);
}

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
<commit_msg>PanasonicDecompressorV6: drop misleading comment<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 "rawspeedconfig.h" // for HAVE_OPENMP
#include "decompressors/PanasonicDecompressorV6.h"
#include "common/Array2DRef.h"            // for Array2DRef
#include "common/Common.h"                // for rawspeed_get_number_of_pro...
#include "common/Point.h"                 // for iPoint2D
#include "common/RawImage.h"              // for RawImageData, RawImage
#include "common/RawspeedException.h"     // for RawspeedException
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include <array>                          // for array
#include <cassert>                        // for assert
#include <cstdint>                        // for uint16_t
#include <string>                         // for string
#include <utility>                        // for move

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) {
    // The bit packing scheme here is actually just 128-bit little-endian int,
    // that we consume from the high bits to low bits, with no padding.
    // It is really tempting to refactor this using proper BitPump, but so far
    // that results in disappointing performance.

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

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

PanasonicDecompressorV6::PanasonicDecompressorV6(const RawImage& img,
                                                 const ByteStream& input_)
    : mRaw(img) {
  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);
  }

  // How many blocks are needed for the given image size?
  const auto numBlocks = mRaw->dim.area() / PixelsPerBlock;

  // How many full blocks does the input contain? This is truncating division.
  const auto haveBlocks = input_.getRemainSize() / BytesPerBlock;

  // Does the input contain enough blocks?
  if (haveBlocks < numBlocks)
    ThrowRDE("Insufficient count of input blocks for a given image");

  // We only want those blocks we need, no extras.
  input = input_.peekStream(numBlocks, BytesPerBlock);
}

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>#include <iostream>
#include <stdlib.h>

#include <vector>
#include <queue>

#include <google/protobuf/descriptor.h>

#include <boost/asio.hpp>
#include <boost/chrono.hpp>

#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>

#include <boost/thread/condition_variable.hpp>

#include "vtrc-server/vtrc-application.h"
#include "vtrc-server/vtrc-endpoint-iface.h"
#include "vtrc-server/vtrc-endpoint-tcp.h"

#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-thread-pool.h"
#include "vtrc-common/vtrc-sizepack-policy.h"
#include "vtrc-common/vtrc-exception.h"

#include "vtrc-common/vtrc-hash-iface.h"

#include "vtrc-common/vtrc-data-queue.h"
#include "vtrc-common/vtrc-condition-queues.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"
#include "vtrc-common/vtrc-protocol-layer.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-connection-iface.h"

#include "protocol/vtrc-errors.pb.h"
#include "protocol/vtrc-auth.pb.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"
#include "protocol/vtrc-service.pb.h"

#include "vtrc-memory.h"
#include "vtrc-chrono.h"

#include "vtrc-server/vtrc-unicast-channels.h"

namespace ba = boost::asio;

using namespace vtrc;

struct work_time {
    typedef boost::chrono::high_resolution_clock::time_point time_point;
    time_point start_;
    work_time( )
        :start_(boost::chrono::high_resolution_clock::now( ))
    {}
    ~work_time( )
    {
        time_point stop(boost::chrono::high_resolution_clock::now( ));
        std::cout << "call time: " << stop - start_ << "\n";
    }
};

void test_send( common::connection_iface *connection )
{
    vtrc::shared_ptr<google::protobuf::RpcChannel> ev(
                vtrc::server
                ::channels::unicast
                ::create_event_channel(connection->shared_from_this( ),
                                       true));

//    const vtrc_rpc_lowlevel::lowlevel_unit *llu =
//            connection->get_protocol( ).
//            get_call_context( )->get_lowlevel_message( );

//    vtrc_rpc_lowlevel::lowlevel_unit llu;
//    connection->get_protocol( ).send_message( llu );

    vtrc_service::internal::Stub ping( ev.get( ));
    vtrc_service::ping_req preq;
    vtrc_service::pong_res pres;

    try {
        for( ;; ) {
            ping.ping( NULL, &preq, &pres, NULL );
            //boost::this_thread::sleep_for( vtrc::chrono::milliseconds(10) );

        }
    } catch( ... ) { }

}

class teat_impl: public vtrc_service::test_rpc {

    common::connection_iface *connection_;
    unsigned id_;

public:

    teat_impl(common::connection_iface *c )
        :connection_(c)
        ,id_(0)
    { }

    void test(::google::protobuf::RpcController* controller,
              const ::vtrc_rpc_lowlevel::message_info* request,
              ::vtrc_rpc_lowlevel::message_info* response,
              ::google::protobuf::Closure* done)
    {
//        std::cout << "test was called :] context: \n"
//                  << connection_->get_protocol( )
//                     .get_call_context( )
//                     ->get_lowlevel_message( )
//                     ->DebugString( );
        //boost::this_thread::sleep_for( vtrc::chrono::milliseconds(900) );

        response->set_message_type( id_++ );
        if( (id_ % 100) == 0 )
            throw std::runtime_error( "oops 10 =)" );

        static boost::thread tr(test_send, connection_);
        if( tr.joinable( ) ) tr.detach( );

        if( done ) done->Run( );
    }
};

class main_app: public vtrc::server::application
{

public:

    main_app( )
    { }

private:

    void on_endpoint_started( vtrc::server::endpoint_iface *ep )
    {
        std::cout << "Start endpoint: " << ep->string( ) << "\n";
    }

    void on_endpoint_stopped( vtrc::server::endpoint_iface *ep )
    {
        std::cout << "Stop endpoint: " << ep->string( ) << "\n";
    }

    void on_endpoint_exception( vtrc::server::endpoint_iface *ep )
    {
        try {
            throw;
        } catch( const std::exception &ex ) {
            std::cout << "Endpoint exception '" << ep->string( )
                      << "': " << ex.what( ) << "\n";
        } catch( ... ) {
            throw;
        }
    }

    void on_new_connection_accepted(
                    vtrc::common::connection_iface* connection )
    {
        std::cout << "connection accepted\n";
    }

    void on_new_connection_ready(
                            vtrc::common::connection_iface* connection )
    {
        std::cout << "connection ready\n";
    }

    void on_connection_die( vtrc::common::connection_iface* connection )
    {
        std::cout << "connection die\n";
    }

    google::protobuf::Service *create_service(
            const std::string &name, vtrc::common::connection_iface* connection)
    {
        return NULL;
    }

    vtrc::common::rpc_service_wrapper_sptr get_service_by_name(
                                    vtrc::common::connection_iface *connection,
                                    const std::string &service_name)
    {
        if( service_name == teat_impl::descriptor( )->full_name( ) ) {
            return common::rpc_service_wrapper_sptr(
                        new common::rpc_service_wrapper(
                                new teat_impl(connection) ) );
        }

        return common::rpc_service_wrapper_sptr( );
    }

};

int main( ) try {

    main_app app;
    vtrc::common::thread_pool poll(app.get_io_service( ), 4);

    vtrc::shared_ptr<vtrc::server::endpoint_iface> tcp_ep
            (vtrc::server::endpoints::tcp::create(app, "0.0.0.0", 44667));

    tcp_ep->start( );

    boost::this_thread::sleep_for( vtrc::chrono::milliseconds(12000) );

    std::cout << "Stoppped. Wait ... \n";

    tcp_ep->stop( );

    poll.stop( );
    poll.join_all( );

    return 0;

} catch( ... ) {

    return 0;
}
<commit_msg>protocol<commit_after>#include <iostream>
#include <stdlib.h>

#include <vector>
#include <queue>

#include <google/protobuf/descriptor.h>

#include <boost/asio.hpp>
#include <boost/chrono.hpp>

#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>

#include <boost/thread/condition_variable.hpp>

#include "vtrc-server/vtrc-application.h"
#include "vtrc-server/vtrc-endpoint-iface.h"
#include "vtrc-server/vtrc-endpoint-tcp.h"

#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-thread-pool.h"
#include "vtrc-common/vtrc-sizepack-policy.h"
#include "vtrc-common/vtrc-exception.h"

#include "vtrc-common/vtrc-hash-iface.h"

#include "vtrc-common/vtrc-data-queue.h"
#include "vtrc-common/vtrc-condition-queues.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"
#include "vtrc-common/vtrc-protocol-layer.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-connection-iface.h"

#include "protocol/vtrc-errors.pb.h"
#include "protocol/vtrc-auth.pb.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"
#include "protocol/vtrc-service.pb.h"

#include "vtrc-memory.h"
#include "vtrc-chrono.h"

#include "vtrc-server/vtrc-unicast-channels.h"

namespace ba = boost::asio;

using namespace vtrc;

struct work_time {
    typedef boost::chrono::high_resolution_clock::time_point time_point;
    time_point start_;
    work_time( )
        :start_(boost::chrono::high_resolution_clock::now( ))
    {}
    ~work_time( )
    {
        time_point stop(boost::chrono::high_resolution_clock::now( ));
        std::cout << "call time: " << stop - start_ << "\n";
    }
};

void test_send( common::connection_iface *connection )
{

    common::connection_iface_sptr s(connection->shared_from_this());
    vtrc::shared_ptr<google::protobuf::RpcChannel> ev(
                vtrc::server
                ::channels::unicast
                ::create_event_channel(connection->shared_from_this( ),
                                       true));

//    const vtrc_rpc_lowlevel::lowlevel_unit *llu =
//            connection->get_protocol( ).
//            get_call_context( )->get_lowlevel_message( );

//    vtrc_rpc_lowlevel::lowlevel_unit llu;
//    connection->get_protocol( ).send_message( llu );

    vtrc_service::internal::Stub ping( ev.get( ));
    vtrc_service::ping_req preq;
    vtrc_service::pong_res pres;

    try {
        for( ;; ) {
            ping.ping( NULL, &preq, &pres, NULL );
            //boost::this_thread::sleep_for( vtrc::chrono::milliseconds(10) );

        }
    } catch( ... ) { }

}

class teat_impl: public vtrc_service::test_rpc {

    common::connection_iface *connection_;
    unsigned id_;

public:

    teat_impl(common::connection_iface *c )
        :connection_(c)
        ,id_(0)
    { }

    void test(::google::protobuf::RpcController* controller,
              const ::vtrc_rpc_lowlevel::message_info* request,
              ::vtrc_rpc_lowlevel::message_info* response,
              ::google::protobuf::Closure* done)
    {
//        std::cout << "test was called :] context: \n"
//                  << connection_->get_protocol( )
//                     .get_call_context( )
//                     ->get_lowlevel_message( )
//                     ->DebugString( );
        //boost::this_thread::sleep_for( vtrc::chrono::milliseconds(900) );

        response->set_message_type( id_++ );
        if( (id_ % 100) == 0 )
            throw std::runtime_error( "oops 10 =)" );

        static boost::thread tr(test_send, connection_);
        if( tr.joinable( ) ) tr.detach( );

        if( done ) done->Run( );
    }
};

class main_app: public vtrc::server::application
{

public:

    main_app( )
    { }

private:

    void on_endpoint_started( vtrc::server::endpoint_iface *ep )
    {
        std::cout << "Start endpoint: " << ep->string( ) << "\n";
    }

    void on_endpoint_stopped( vtrc::server::endpoint_iface *ep )
    {
        std::cout << "Stop endpoint: " << ep->string( ) << "\n";
    }

    void on_endpoint_exception( vtrc::server::endpoint_iface *ep )
    {
        try {
            throw;
        } catch( const std::exception &ex ) {
            std::cout << "Endpoint exception '" << ep->string( )
                      << "': " << ex.what( ) << "\n";
        } catch( ... ) {
            throw;
        }
    }

    void on_new_connection_accepted(
                    vtrc::common::connection_iface* connection )
    {
        std::cout << "connection accepted\n";
    }

    void on_new_connection_ready(
                            vtrc::common::connection_iface* connection )
    {
        std::cout << "connection ready\n";
    }

    void on_connection_die( vtrc::common::connection_iface* connection )
    {
        std::cout << "connection die\n";
    }

    google::protobuf::Service *create_service(
            const std::string &name, vtrc::common::connection_iface* connection)
    {
        return NULL;
    }

    vtrc::common::rpc_service_wrapper_sptr get_service_by_name(
                                    vtrc::common::connection_iface *connection,
                                    const std::string &service_name)
    {
        if( service_name == teat_impl::descriptor( )->full_name( ) ) {
            return common::rpc_service_wrapper_sptr(
                        new common::rpc_service_wrapper(
                                new teat_impl(connection) ) );
        }

        return common::rpc_service_wrapper_sptr( );
    }

};

int main( ) try {

    main_app app;
    vtrc::common::thread_pool poll(app.get_io_service( ), 4);

    vtrc::shared_ptr<vtrc::server::endpoint_iface> tcp_ep
            (vtrc::server::endpoints::tcp::create(app, "0.0.0.0", 44667));

    tcp_ep->start( );

    boost::this_thread::sleep_for( vtrc::chrono::milliseconds(12000) );

    std::cout << "Stoppped. Wait ... \n";

    tcp_ep->stop( );

    poll.stop( );
    poll.join_all( );

    return 0;

} catch( ... ) {

    return 0;
}
<|endoftext|>


<commit_before>#include <shogun/features/Labels.h>
#include <shogun/features/SimpleFeatures.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/machine/MulticlassLibSVM.h>
#include <shogun/base/init.h>

using namespace shogun;

void print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

int main(int argc, char** argv)
{
	init_shogun(&print_message);
	index_t num_vec=3;
	index_t num_feat=2;
	index_t num_class=2;

	// create some data
	SGMatrix<float64_t> matrix(num_feat, num_vec);
	CMath::range_fill_vector(matrix.matrix, num_feat*num_vec);

	// create vectors
	// shogun will now own the matrix created
	CSimpleFeatures<float64_t>* features=new CSimpleFeatures<float64_t>(matrix);

	// create three labels
	CLabels* labels=new CLabels(num_vec);
	for (index_t i=0; i<num_vec; ++i)
		labels->set_label(i, i%num_class);

	// create gaussian kernel with cache 10MB, width 0.5
	CGaussianKernel* kernel = new CGaussianKernel(10, 0.5);
	kernel->init(features, features);

	// create libsvm with C=10 and train
	CLibSVMMulticlass* svm = new CLibSVMMulticlass(10, kernel, labels);
	svm->train();

	// classify on training examples
	CLabels* output=svm->apply();
	CMath::display_vector(output->get_labels().vector, output->get_num_labels(),
			"batch output");

	/* assert that batch apply and apply(index_t) give same result */
	for (index_t i=0; i<output->get_num_labels(); ++i)
	{
		float64_t label=svm->apply(i);
		SG_SPRINT("single output[%d]=%f\n", i, label);
		ASSERT(output->get_label(i)==label);
	}
	SG_UNREF(output);

	// free up memory
	SG_UNREF(svm);

	exit_shogun();
	return 0;
}

<commit_msg>Finally fixed multiclasslibsvm example<commit_after>#include <shogun/features/Labels.h>
#include <shogun/features/SimpleFeatures.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/multiclass/MulticlassLibSVM.h>
#include <shogun/base/init.h>

using namespace shogun;

void print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

int main(int argc, char** argv)
{
	init_shogun(&print_message);
	index_t num_vec=3;
	index_t num_feat=2;
	index_t num_class=2;

	// create some data
	SGMatrix<float64_t> matrix(num_feat, num_vec);
	CMath::range_fill_vector(matrix.matrix, num_feat*num_vec);

	// create vectors
	// shogun will now own the matrix created
	CSimpleFeatures<float64_t>* features=new CSimpleFeatures<float64_t>(matrix);

	// create three labels
	CLabels* labels=new CLabels(num_vec);
	for (index_t i=0; i<num_vec; ++i)
		labels->set_label(i, i%num_class);

	// create gaussian kernel with cache 10MB, width 0.5
	CGaussianKernel* kernel = new CGaussianKernel(10, 0.5);
	kernel->init(features, features);

	// create libsvm with C=10 and train
	CMulticlassLibSVM* svm = new CMulticlassLibSVM(10, kernel, labels);
	svm->train();

	// classify on training examples
	CLabels* output=svm->apply();
	CMath::display_vector(output->get_labels().vector, output->get_num_labels(),
			"batch output");

	/* assert that batch apply and apply(index_t) give same result */
	for (index_t i=0; i<output->get_num_labels(); ++i)
	{
		float64_t label=svm->apply(i);
		SG_SPRINT("single output[%d]=%f\n", i, label);
		ASSERT(output->get_label(i)==label);
	}
	SG_UNREF(output);

	// free up memory
	SG_UNREF(svm);

	exit_shogun();
	return 0;
}

<|endoftext|>


<commit_before>// Copyright 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ozone/wayland/input/keyboard.h"

#include <sys/mman.h>

#include "ozone/wayland/dispatcher.h"
#include "ui/events/event.h"

namespace ozonewayland {

WaylandKeyboard::WaylandKeyboard() : input_keyboard_(NULL),
    keyboard_modifiers_(0),
    dispatcher_(NULL) {
  xkb_.context = NULL;
  xkb_.keymap = NULL;
  xkb_.state = NULL;
}

WaylandKeyboard::~WaylandKeyboard() {
  FiniXKB();
  if (input_keyboard_) {
    wl_keyboard_destroy(input_keyboard_);
    input_keyboard_ = NULL;
  }
}

void WaylandKeyboard::OnSeatCapabilities(wl_seat *seat, uint32_t caps) {
  static const struct wl_keyboard_listener kInputKeyboardListener = {
    WaylandKeyboard::OnKeyboardKeymap,
    WaylandKeyboard::OnKeyboardEnter,
    WaylandKeyboard::OnKeyboardLeave,
    WaylandKeyboard::OnKeyNotify,
    WaylandKeyboard::OnKeyModifiers,
  };

  dispatcher_ = WaylandDispatcher::GetInstance();

  if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input_keyboard_) {
    InitXKB();
    input_keyboard_ = wl_seat_get_keyboard(seat);
    wl_keyboard_add_listener(input_keyboard_, &kInputKeyboardListener,
        this);
  } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input_keyboard_) {
    FiniXKB();
    wl_keyboard_destroy(input_keyboard_);
    input_keyboard_ = NULL;
  }
}

void WaylandKeyboard::OnKeyNotify(void* data,
                                  wl_keyboard* input_keyboard,
                                  uint32_t serial,
                                  uint32_t time,
                                  uint32_t key,
                                  uint32_t state) {
  WaylandKeyboard* device = static_cast<WaylandKeyboard*>(data);
  const xkb_keysym_t *syms;
  xkb_keysym_t sym;
  unsigned currentState = 0;
  uint32_t code = key + 8;
  uint32_t num_syms = xkb_key_get_syms(device->xkb_.state, code, &syms);
  if (num_syms == 1)
    sym = syms[0];
  else
    sym = XKB_KEY_NoSymbol;

  WaylandDisplay::GetInstance()->SetSerial(serial);

  if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
    currentState = 1;
  else
    currentState = 0;

  device->dispatcher_->KeyNotify(currentState,
                                 sym,
                                 device->keyboard_modifiers_);

}

void WaylandKeyboard::OnKeyboardKeymap(void *data,
                                       struct wl_keyboard *keyboard,
                                       uint32_t format,
                                       int fd,
                                       uint32_t size) {
  WaylandKeyboard* device = static_cast<WaylandKeyboard*>(data);
  char *map_str;

  if (!data) {
    close(fd);
    return;
  }

  if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
    close(fd);
    return;
  }

  map_str =
      reinterpret_cast<char*>(mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0));
  if (map_str == MAP_FAILED) {
    close(fd);
    return;
  }

  device->xkb_.keymap = xkb_map_new_from_string(device->xkb_.context,
                                                map_str,
                                                XKB_KEYMAP_FORMAT_TEXT_V1,
                                                (xkb_map_compile_flags)0);
  munmap(map_str, size);
  close(fd);
  if (!device->xkb_.keymap) {
    return;
  }

  device->xkb_.state = xkb_state_new(device->xkb_.keymap);
  if (!device->xkb_.state) {
    xkb_map_unref(device->xkb_.keymap);
    device->xkb_.keymap = NULL;
    return;
  }
}

void WaylandKeyboard::OnKeyboardEnter(void* data,
                                      wl_keyboard* input_keyboard,
                                      uint32_t serial,
                                      wl_surface* surface,
                                      wl_array* keys) {
  WaylandDisplay::GetInstance()->SetSerial(serial);
}

void WaylandKeyboard::OnKeyboardLeave(void* data,
                                      wl_keyboard* input_keyboard,
                                      uint32_t serial,
                                      wl_surface* surface) {
  WaylandDisplay::GetInstance()->SetSerial(serial);
}

void WaylandKeyboard::OnKeyModifiers(void *data,
                                     wl_keyboard *keyboard,
                                     uint32_t serial,
                                     uint32_t mods_depressed,
                                     uint32_t mods_latched,
                                     uint32_t mods_locked,
                                     uint32_t group) {
  WaylandKeyboard* device = static_cast<WaylandKeyboard*>(data);
  if (!device->xkb_.state)
    return;

  xkb_state_update_mask(device->xkb_.state,
                        mods_depressed,
                        mods_latched,
                        mods_locked,
                        0,
                        0,
                        group);

  device->keyboard_modifiers_ = 0;
  if (xkb_state_mod_name_is_active(
      device->xkb_.state, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_EFFECTIVE))
    device->keyboard_modifiers_ |= ui::EF_SHIFT_DOWN;

  if (xkb_state_mod_name_is_active(
      device->xkb_.state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE))
    device->keyboard_modifiers_ |= ui::EF_CONTROL_DOWN;

  if (xkb_state_mod_name_is_active(
      device->xkb_.state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE))
    device->keyboard_modifiers_ |= ui::EF_ALT_DOWN;
}

void WaylandKeyboard::InitXKB() {
  if (xkb_.context) {
    return;
  }

  xkb_.context = xkb_context_new((xkb_context_flags)0);
}

void WaylandKeyboard::FiniXKB() {
  if (xkb_.state) {
    xkb_state_unref(xkb_.state);
    xkb_.state = NULL;
  }

  if (xkb_.keymap) {
    xkb_map_unref(xkb_.keymap);
    xkb_.keymap = NULL;
  }

  if (xkb_.context) {
    xkb_context_unref(xkb_.context);
    xkb_.context = NULL;
  }
}

}  // namespace ozonewayland
<commit_msg>Keyboard: Add support for CapsLock.<commit_after>// Copyright 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ozone/wayland/input/keyboard.h"

#include <sys/mman.h>

#include "ozone/wayland/dispatcher.h"
#include "ui/events/event.h"

namespace ozonewayland {

WaylandKeyboard::WaylandKeyboard() : input_keyboard_(NULL),
    keyboard_modifiers_(0),
    dispatcher_(NULL) {
  xkb_.context = NULL;
  xkb_.keymap = NULL;
  xkb_.state = NULL;
}

WaylandKeyboard::~WaylandKeyboard() {
  FiniXKB();
  if (input_keyboard_) {
    wl_keyboard_destroy(input_keyboard_);
    input_keyboard_ = NULL;
  }
}

void WaylandKeyboard::OnSeatCapabilities(wl_seat *seat, uint32_t caps) {
  static const struct wl_keyboard_listener kInputKeyboardListener = {
    WaylandKeyboard::OnKeyboardKeymap,
    WaylandKeyboard::OnKeyboardEnter,
    WaylandKeyboard::OnKeyboardLeave,
    WaylandKeyboard::OnKeyNotify,
    WaylandKeyboard::OnKeyModifiers,
  };

  dispatcher_ = WaylandDispatcher::GetInstance();

  if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input_keyboard_) {
    InitXKB();
    input_keyboard_ = wl_seat_get_keyboard(seat);
    wl_keyboard_add_listener(input_keyboard_, &kInputKeyboardListener,
        this);
  } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input_keyboard_) {
    FiniXKB();
    wl_keyboard_destroy(input_keyboard_);
    input_keyboard_ = NULL;
  }
}

void WaylandKeyboard::OnKeyNotify(void* data,
                                  wl_keyboard* input_keyboard,
                                  uint32_t serial,
                                  uint32_t time,
                                  uint32_t key,
                                  uint32_t state) {
  WaylandKeyboard* device = static_cast<WaylandKeyboard*>(data);
  const xkb_keysym_t *syms;
  xkb_keysym_t sym;
  unsigned currentState = 0;
  uint32_t code = key + 8;
  uint32_t num_syms = xkb_key_get_syms(device->xkb_.state, code, &syms);
  if (num_syms == 1)
    sym = syms[0];
  else
    sym = XKB_KEY_NoSymbol;

  WaylandDisplay::GetInstance()->SetSerial(serial);

  if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
    currentState = 1;
  else
    currentState = 0;

  device->dispatcher_->KeyNotify(currentState,
                                 sym,
                                 device->keyboard_modifiers_);

}

void WaylandKeyboard::OnKeyboardKeymap(void *data,
                                       struct wl_keyboard *keyboard,
                                       uint32_t format,
                                       int fd,
                                       uint32_t size) {
  WaylandKeyboard* device = static_cast<WaylandKeyboard*>(data);
  char *map_str;

  if (!data) {
    close(fd);
    return;
  }

  if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
    close(fd);
    return;
  }

  map_str =
      reinterpret_cast<char*>(mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0));
  if (map_str == MAP_FAILED) {
    close(fd);
    return;
  }

  device->xkb_.keymap = xkb_map_new_from_string(device->xkb_.context,
                                                map_str,
                                                XKB_KEYMAP_FORMAT_TEXT_V1,
                                                (xkb_map_compile_flags)0);
  munmap(map_str, size);
  close(fd);
  if (!device->xkb_.keymap) {
    return;
  }

  device->xkb_.state = xkb_state_new(device->xkb_.keymap);
  if (!device->xkb_.state) {
    xkb_map_unref(device->xkb_.keymap);
    device->xkb_.keymap = NULL;
    return;
  }
}

void WaylandKeyboard::OnKeyboardEnter(void* data,
                                      wl_keyboard* input_keyboard,
                                      uint32_t serial,
                                      wl_surface* surface,
                                      wl_array* keys) {
  WaylandDisplay::GetInstance()->SetSerial(serial);
}

void WaylandKeyboard::OnKeyboardLeave(void* data,
                                      wl_keyboard* input_keyboard,
                                      uint32_t serial,
                                      wl_surface* surface) {
  WaylandDisplay::GetInstance()->SetSerial(serial);
}

void WaylandKeyboard::OnKeyModifiers(void *data,
                                     wl_keyboard *keyboard,
                                     uint32_t serial,
                                     uint32_t mods_depressed,
                                     uint32_t mods_latched,
                                     uint32_t mods_locked,
                                     uint32_t group) {
  WaylandKeyboard* device = static_cast<WaylandKeyboard*>(data);
  if (!device->xkb_.state)
    return;

  xkb_state_update_mask(device->xkb_.state,
                        mods_depressed,
                        mods_latched,
                        mods_locked,
                        0,
                        0,
                        group);

  device->keyboard_modifiers_ = 0;
  if (xkb_state_mod_name_is_active(
      device->xkb_.state, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_EFFECTIVE))
    device->keyboard_modifiers_ |= ui::EF_SHIFT_DOWN;

  if (xkb_state_mod_name_is_active(
      device->xkb_.state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE))
    device->keyboard_modifiers_ |= ui::EF_CONTROL_DOWN;

  if (xkb_state_mod_name_is_active(
      device->xkb_.state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE))
    device->keyboard_modifiers_ |= ui::EF_ALT_DOWN;

  if (xkb_state_mod_name_is_active(
      device->xkb_.state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_EFFECTIVE))
    device->keyboard_modifiers_ |= ui::EF_CAPS_LOCK_DOWN;
}

void WaylandKeyboard::InitXKB() {
  if (xkb_.context) {
    return;
  }

  xkb_.context = xkb_context_new((xkb_context_flags)0);
}

void WaylandKeyboard::FiniXKB() {
  if (xkb_.state) {
    xkb_state_unref(xkb_.state);
    xkb_.state = NULL;
  }

  if (xkb_.keymap) {
    xkb_map_unref(xkb_.keymap);
    xkb_.keymap = NULL;
  }

  if (xkb_.context) {
    xkb_context_unref(xkb_.context);
    xkb_.context = NULL;
  }
}

}  // namespace ozonewayland
<|endoftext|>


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

#include "brw_fs.h"
#include "brw_fs_live_variables.h"
#include "brw_cfg.h"

/** @file brw_fs_saturate_propagation.cpp
 */

static bool
opt_saturate_propagation_local(fs_visitor *v, bblock_t *block)
{
   bool progress = false;
   int ip = block->start_ip - 1;

   foreach_inst_in_block(fs_inst, inst, block) {
      ip++;

      if (inst->opcode != BRW_OPCODE_MOV ||
          inst->dst.file != GRF ||
          inst->src[0].file != GRF ||
          inst->src[0].abs ||
          inst->src[0].negate ||
          !inst->saturate)
         continue;

      int src_var = v->live_intervals->var_from_reg(&inst->src[0]);
      int src_end_ip = v->live_intervals->end[src_var];

      bool interfered = false;
      foreach_inst_in_block_reverse_starting_from(fs_inst, scan_inst, inst, block) {
         if (scan_inst->dst.file == GRF &&
             scan_inst->dst.reg == inst->src[0].reg &&
             scan_inst->dst.reg_offset == inst->src[0].reg_offset &&
             !scan_inst->is_partial_write()) {
            if (scan_inst->saturate) {
               inst->saturate = false;
               progress = true;
            } else if (src_end_ip <= ip || inst->dst.equals(inst->src[0])) {
               if (scan_inst->can_do_saturate()) {
                  scan_inst->saturate = true;
                  inst->saturate = false;
                  progress = true;
               }
            }
            break;
         }
         for (int i = 0; i < scan_inst->sources; i++) {
            if (scan_inst->src[i].file == GRF &&
                scan_inst->src[i].reg == inst->src[0].reg &&
                scan_inst->src[i].reg_offset == inst->src[0].reg_offset) {
               interfered = true;
               break;
            }
         }

         if (interfered)
            break;
      }
   }

   return progress;
}

bool
fs_visitor::opt_saturate_propagation()
{
   bool progress = false;

   calculate_live_intervals();

   foreach_block (block, cfg) {
      progress = opt_saturate_propagation_local(this, block) || progress;
   }

   if (progress)
      invalidate_live_intervals();

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

#include "brw_fs.h"
#include "brw_fs_live_variables.h"
#include "brw_cfg.h"

/** @file brw_fs_saturate_propagation.cpp
 */

static bool
opt_saturate_propagation_local(fs_visitor *v, bblock_t *block)
{
   bool progress = false;
   int ip = block->end_ip + 1;

   foreach_inst_in_block_reverse(fs_inst, inst, block) {
      ip--;

      if (inst->opcode != BRW_OPCODE_MOV ||
          inst->dst.file != GRF ||
          inst->src[0].file != GRF ||
          inst->src[0].abs ||
          inst->src[0].negate ||
          !inst->saturate)
         continue;

      int src_var = v->live_intervals->var_from_reg(&inst->src[0]);
      int src_end_ip = v->live_intervals->end[src_var];

      bool interfered = false;
      foreach_inst_in_block_reverse_starting_from(fs_inst, scan_inst, inst, block) {
         if (scan_inst->dst.file == GRF &&
             scan_inst->dst.reg == inst->src[0].reg &&
             scan_inst->dst.reg_offset == inst->src[0].reg_offset &&
             !scan_inst->is_partial_write()) {
            if (scan_inst->saturate) {
               inst->saturate = false;
               progress = true;
            } else if (src_end_ip <= ip || inst->dst.equals(inst->src[0])) {
               if (scan_inst->can_do_saturate()) {
                  scan_inst->saturate = true;
                  inst->saturate = false;
                  progress = true;
               }
            }
            break;
         }
         for (int i = 0; i < scan_inst->sources; i++) {
            if (scan_inst->src[i].file == GRF &&
                scan_inst->src[i].reg == inst->src[0].reg &&
                scan_inst->src[i].reg_offset == inst->src[0].reg_offset) {
               interfered = true;
               break;
            }
         }

         if (interfered)
            break;
      }
   }

   return progress;
}

bool
fs_visitor::opt_saturate_propagation()
{
   bool progress = false;

   calculate_live_intervals();

   foreach_block (block, cfg) {
      progress = opt_saturate_propagation_local(this, block) || progress;
   }

   if (progress)
      invalidate_live_intervals();

   return progress;
}
<|endoftext|>