C++程序  |  925行  |  28.73 KB

/*
 * Copyright © 2014 Advanced Micro Devices, Inc.
 * All Rights Reserved.
 *
 * 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, sub license, 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 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
 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
 * AND/OR ITS SUPPLIERS 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.
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 */

/**
****************************************************************************************************
* @file  addrcommon.h
* @brief Contains the helper function and constants.
****************************************************************************************************
*/

#ifndef __ADDR_COMMON_H__
#define __ADDR_COMMON_H__

#include "addrinterface.h"

#include <stdlib.h>
#include <string.h>
#include <assert.h>

#if !defined(DEBUG)
#ifdef NDEBUG
#define DEBUG 0
#else
#define DEBUG 1
#endif
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// Platform specific debug break defines
////////////////////////////////////////////////////////////////////////////////////////////////////
#if DEBUG
    #if defined(__GNUC__)
        #define ADDR_DBG_BREAK()    assert(false)
    #elif defined(__APPLE__)
        #define ADDR_DBG_BREAK()    { IOPanic("");}
    #else
        #define ADDR_DBG_BREAK()    { __debugbreak(); }
    #endif
#else
    #define ADDR_DBG_BREAK()
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////
// Debug assertions used in AddrLib
////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined(_WIN32) && (_MSC_VER >= 1400)
    #define ADDR_ANALYSIS_ASSUME(expr) __analysis_assume(expr)
#else
    #define ADDR_ANALYSIS_ASSUME(expr) do { (void)(expr); } while (0)
#endif

#define ADDR_ASSERT(__e) assert(__e)
#define ADDR_ASSERT_ALWAYS() ADDR_DBG_BREAK()
#define ADDR_UNHANDLED_CASE() ADDR_ASSERT(!"Unhandled case")
#define ADDR_NOT_IMPLEMENTED() ADDR_ASSERT(!"Not implemented");
////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////
// Debug print macro from legacy address library
////////////////////////////////////////////////////////////////////////////////////////////////////
#if DEBUG

#define ADDR_PRNT(a)    Object::DebugPrint a

/// @brief Macro for reporting informational messages
/// @ingroup util
///
/// This macro optionally prints an informational message to stdout.
/// The first parameter is a condition -- if it is true, nothing is done.
/// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
/// starting with a string. This is passed to printf() or an equivalent
/// in order to format the informational message. For example,
/// ADDR_INFO(0, ("test %d",3) ); prints out "test 3".
///
#define ADDR_INFO(cond, a)         \
{ if (!(cond)) { ADDR_PRNT(a); } }


/// @brief Macro for reporting error warning messages
/// @ingroup util
///
/// This macro optionally prints an error warning message to stdout,
/// followed by the file name and line number where the macro was called.
/// The first parameter is a condition -- if it is true, nothing is done.
/// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
/// starting with a string. This is passed to printf() or an equivalent
/// in order to format the informational message. For example,
/// ADDR_WARN(0, ("test %d",3) ); prints out "test 3" followed by
/// a second line with the file name and line number.
///
#define ADDR_WARN(cond, a)         \
{ if (!(cond))                     \
  { ADDR_PRNT(a);                  \
    ADDR_PRNT(("  WARNING in file %s, line %d\n", __FILE__, __LINE__)); \
} }


/// @brief Macro for reporting fatal error conditions
/// @ingroup util
///
/// This macro optionally stops execution of the current routine
/// after printing an error warning message to stdout,
/// followed by the file name and line number where the macro was called.
/// The first parameter is a condition -- if it is true, nothing is done.
/// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
/// starting with a string. This is passed to printf() or an equivalent
/// in order to format the informational message. For example,
/// ADDR_EXIT(0, ("test %d",3) ); prints out "test 3" followed by
/// a second line with the file name and line number, then stops execution.
///
#define ADDR_EXIT(cond, a)         \
{ if (!(cond))                     \
  { ADDR_PRNT(a); ADDR_DBG_BREAK();\
} }

#else // DEBUG

#define ADDRDPF 1 ? (void)0 : (void)

#define ADDR_PRNT(a)

#define ADDR_DBG_BREAK()

#define ADDR_INFO(cond, a)

#define ADDR_WARN(cond, a)

#define ADDR_EXIT(cond, a)

#endif // DEBUG
////////////////////////////////////////////////////////////////////////////////////////////////////

#define ADDR_C_ASSERT(__e) typedef char __ADDR_C_ASSERT__[(__e) ? 1 : -1]

namespace Addr
{

namespace V1
{
////////////////////////////////////////////////////////////////////////////////////////////////////
// Common constants
////////////////////////////////////////////////////////////////////////////////////////////////////
static const UINT_32 MicroTileWidth      = 8;       ///< Micro tile width, for 1D and 2D tiling
static const UINT_32 MicroTileHeight     = 8;       ///< Micro tile height, for 1D and 2D tiling
static const UINT_32 ThickTileThickness  = 4;       ///< Micro tile thickness, for THICK modes
static const UINT_32 XThickTileThickness = 8;       ///< Extra thick tiling thickness
static const UINT_32 PowerSaveTileBytes  = 64;      ///< Nuber of bytes per tile for power save 64
static const UINT_32 CmaskCacheBits      = 1024;    ///< Number of bits for CMASK cache
static const UINT_32 CmaskElemBits       = 4;       ///< Number of bits for CMASK element
static const UINT_32 HtileCacheBits      = 16384;   ///< Number of bits for HTILE cache 512*32

static const UINT_32 MicroTilePixels     = MicroTileWidth * MicroTileHeight;

static const INT_32 TileIndexInvalid        = TILEINDEX_INVALID;
static const INT_32 TileIndexLinearGeneral  = TILEINDEX_LINEAR_GENERAL;
static const INT_32 TileIndexNoMacroIndex   = -3;

} // V1

namespace V2
{
////////////////////////////////////////////////////////////////////////////////////////////////////
// Common constants
////////////////////////////////////////////////////////////////////////////////////////////////////
static const UINT_32 MaxSurfaceHeight = 16384;

} // V2

////////////////////////////////////////////////////////////////////////////////////////////////////
// Common macros
////////////////////////////////////////////////////////////////////////////////////////////////////
#define BITS_PER_BYTE 8
#define BITS_TO_BYTES(x) ( ((x) + (BITS_PER_BYTE-1)) / BITS_PER_BYTE )
#define BYTES_TO_BITS(x) ( (x) * BITS_PER_BYTE )

/// Helper macros to select a single bit from an int (undefined later in section)
#define _BIT(v,b)      (((v) >> (b) ) & 1)

/**
****************************************************************************************************
* @brief Enums to identify AddrLib type
****************************************************************************************************
*/
enum LibClass
{
    BASE_ADDRLIB = 0x0,
    R600_ADDRLIB = 0x6,
    R800_ADDRLIB = 0x8,
    SI_ADDRLIB   = 0xa,
    CI_ADDRLIB   = 0xb,
    AI_ADDRLIB   = 0xd,
};

/**
****************************************************************************************************
* ChipFamily
*
*   @brief
*       Neutral enums that specifies chip family.
*
****************************************************************************************************
*/
enum ChipFamily
{
    ADDR_CHIP_FAMILY_IVLD,    ///< Invalid family
    ADDR_CHIP_FAMILY_R6XX,
    ADDR_CHIP_FAMILY_R7XX,
    ADDR_CHIP_FAMILY_R8XX,
    ADDR_CHIP_FAMILY_NI,
    ADDR_CHIP_FAMILY_SI,
    ADDR_CHIP_FAMILY_CI,
    ADDR_CHIP_FAMILY_VI,
    ADDR_CHIP_FAMILY_AI,
};

/**
****************************************************************************************************
* ConfigFlags
*
*   @brief
*       This structure is used to set configuration flags.
****************************************************************************************************
*/
union ConfigFlags
{
    struct
    {
        /// These flags are set up internally thru AddrLib::Create() based on ADDR_CREATE_FLAGS
        UINT_32 optimalBankSwap        : 1;    ///< New bank tiling for RV770 only
        UINT_32 noCubeMipSlicesPad     : 1;    ///< Disables faces padding for cubemap mipmaps
        UINT_32 fillSizeFields         : 1;    ///< If clients fill size fields in all input and
                                               ///  output structure
        UINT_32 ignoreTileInfo         : 1;    ///< Don't use tile info structure
        UINT_32 useTileIndex           : 1;    ///< Make tileIndex field in input valid
        UINT_32 useCombinedSwizzle     : 1;    ///< Use combined swizzle
        UINT_32 checkLast2DLevel       : 1;    ///< Check the last 2D mip sub level
        UINT_32 useHtileSliceAlign     : 1;    ///< Do htile single slice alignment
        UINT_32 allowLargeThickTile    : 1;    ///< Allow 64*thickness*bytesPerPixel > rowSize
        UINT_32 disableLinearOpt       : 1;    ///< Disallow tile modes to be optimized to linear
        UINT_32 reserved               : 22;   ///< Reserved bits for future use
    };

    UINT_32 value;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Misc helper functions
////////////////////////////////////////////////////////////////////////////////////////////////////

/**
****************************************************************************************************
*   AddrXorReduce
*
*   @brief
*       Xor the right-side numberOfBits bits of x.
****************************************************************************************************
*/
static inline UINT_32 XorReduce(
    UINT_32 x,
    UINT_32 numberOfBits)
{
    UINT_32 i;
    UINT_32 result = x & 1;

    for (i=1; i<numberOfBits; i++)
    {
        result ^= ((x>>i) & 1);
    }

    return result;
}

/**
****************************************************************************************************
*   IsPow2
*
*   @brief
*       Check if the size (UINT_32) is pow 2
****************************************************************************************************
*/
static inline UINT_32 IsPow2(
    UINT_32 dim)        ///< [in] dimension of miplevel
{
    ADDR_ASSERT(dim > 0);
    return !(dim & (dim - 1));
}

/**
****************************************************************************************************
*   IsPow2
*
*   @brief
*       Check if the size (UINT_64) is pow 2
****************************************************************************************************
*/
static inline UINT_64 IsPow2(
    UINT_64 dim)        ///< [in] dimension of miplevel
{
    ADDR_ASSERT(dim > 0);
    return !(dim & (dim - 1));
}

/**
****************************************************************************************************
*   ByteAlign
*
*   @brief
*       Align UINT_32 "x" to "align" alignment, "align" should be power of 2
****************************************************************************************************
*/
static inline UINT_32 PowTwoAlign(
    UINT_32 x,
    UINT_32 align)
{
    //
    // Assert that x is a power of two.
    //
    ADDR_ASSERT(IsPow2(align));
    return (x + (align - 1)) & (~(align - 1));
}

/**
****************************************************************************************************
*   ByteAlign
*
*   @brief
*       Align UINT_64 "x" to "align" alignment, "align" should be power of 2
****************************************************************************************************
*/
static inline UINT_64 PowTwoAlign(
    UINT_64 x,
    UINT_64 align)
{
    //
    // Assert that x is a power of two.
    //
    ADDR_ASSERT(IsPow2(align));
    return (x + (align - 1)) & (~(align - 1));
}

/**
****************************************************************************************************
*   Min
*
*   @brief
*       Get the min value between two unsigned values
****************************************************************************************************
*/
static inline UINT_32 Min(
    UINT_32 value1,
    UINT_32 value2)
{
    return ((value1 < (value2)) ? (value1) : value2);
}

/**
****************************************************************************************************
*   Min
*
*   @brief
*       Get the min value between two signed values
****************************************************************************************************
*/
static inline INT_32 Min(
    INT_32 value1,
    INT_32 value2)
{
    return ((value1 < (value2)) ? (value1) : value2);
}

/**
****************************************************************************************************
*   Max
*
*   @brief
*       Get the max value between two unsigned values
****************************************************************************************************
*/
static inline UINT_32 Max(
    UINT_32 value1,
    UINT_32 value2)
{
    return ((value1 > (value2)) ? (value1) : value2);
}

/**
****************************************************************************************************
*   Max
*
*   @brief
*       Get the max value between two signed values
****************************************************************************************************
*/
static inline INT_32 Max(
    INT_32 value1,
    INT_32 value2)
{
    return ((value1 > (value2)) ? (value1) : value2);
}

/**
****************************************************************************************************
*   NextPow2
*
*   @brief
*       Compute the mipmap's next level dim size
****************************************************************************************************
*/
static inline UINT_32 NextPow2(
    UINT_32 dim)        ///< [in] dimension of miplevel
{
    UINT_32 newDim = 1;

    if (dim > 0x7fffffff)
    {
        ADDR_ASSERT_ALWAYS();
        newDim = 0x80000000;
    }
    else
    {
        while (newDim < dim)
        {
            newDim <<= 1;
        }
    }

    return newDim;
}

/**
****************************************************************************************************
*   Log2NonPow2
*
*   @brief
*       Compute log of base 2 no matter the target is power of 2 or not
****************************************************************************************************
*/
static inline UINT_32 Log2NonPow2(
    UINT_32 x)      ///< [in] the value should calculate log based 2
{
    UINT_32 y;

    y = 0;
    while (x > 1)
    {
        x >>= 1;
        y++;
    }

    return y;
}

/**
****************************************************************************************************
*   Log2
*
*   @brief
*       Compute log of base 2
****************************************************************************************************
*/
static inline UINT_32 Log2(
    UINT_32 x)      ///< [in] the value should calculate log based 2
{
    // Assert that x is a power of two.
    ADDR_ASSERT(IsPow2(x));

    return Log2NonPow2(x);
}

/**
****************************************************************************************************
*   QLog2
*
*   @brief
*       Compute log of base 2 quickly (<= 16)
****************************************************************************************************
*/
static inline UINT_32 QLog2(
    UINT_32 x)      ///< [in] the value should calculate log based 2
{
    ADDR_ASSERT(x <= 16);

    UINT_32 y = 0;

    switch (x)
    {
        case 1:
            y = 0;
            break;
        case 2:
            y = 1;
            break;
        case 4:
            y = 2;
            break;
        case 8:
            y = 3;
            break;
        case 16:
            y = 4;
            break;
        default:
            ADDR_ASSERT_ALWAYS();
    }

    return y;
}

/**
****************************************************************************************************
*   SafeAssign
*
*   @brief
*       NULL pointer safe assignment
****************************************************************************************************
*/
static inline VOID SafeAssign(
    UINT_32*    pLVal,  ///< [in] Pointer to left val
    UINT_32     rVal)   ///< [in] Right value
{
    if (pLVal)
    {
        *pLVal = rVal;
    }
}

/**
****************************************************************************************************
*   SafeAssign
*
*   @brief
*       NULL pointer safe assignment for 64bit values
****************************************************************************************************
*/
static inline VOID SafeAssign(
    UINT_64*    pLVal,  ///< [in] Pointer to left val
    UINT_64     rVal)   ///< [in] Right value
{
    if (pLVal)
    {
        *pLVal = rVal;
    }
}

/**
****************************************************************************************************
*   SafeAssign
*
*   @brief
*       NULL pointer safe assignment for AddrTileMode
****************************************************************************************************
*/
static inline VOID SafeAssign(
    AddrTileMode*    pLVal, ///< [in] Pointer to left val
    AddrTileMode     rVal)  ///< [in] Right value
{
    if (pLVal)
    {
        *pLVal = rVal;
    }
}

/**
****************************************************************************************************
*   RoundHalf
*
*   @brief
*       return (x + 1) / 2
****************************************************************************************************
*/
static inline UINT_32 RoundHalf(
    UINT_32     x)     ///< [in] input value
{
    ADDR_ASSERT(x != 0);

#if 1
    return (x >> 1) + (x & 1);
#else
    return (x + 1) >> 1;
#endif
}

/**
****************************************************************************************************
*   SumGeo
*
*   @brief
*       Calculate sum of a geometric progression whose ratio is 1/2
****************************************************************************************************
*/
static inline UINT_32 SumGeo(
    UINT_32     base,   ///< [in] First term in the geometric progression
    UINT_32     num)    ///< [in] Number of terms to be added into sum
{
    ADDR_ASSERT(base > 0);

    UINT_32 sum = 0;
    UINT_32 i = 0;
    for (; (i < num) && (base > 1); i++)
    {
        sum += base;
        base = RoundHalf(base);
    }
    sum += num - i;

    return sum;
}

/**
****************************************************************************************************
*   GetBit
*
*   @brief
*       Extract bit N value (0 or 1) of a UINT32 value.
****************************************************************************************************
*/
static inline UINT_32 GetBit(
    UINT_32     u32,   ///< [in] UINT32 value
    UINT_32     pos)   ///< [in] bit position from LSB, valid range is [0..31]
{
    ADDR_ASSERT(pos <= 31);

    return (u32 >> pos) & 0x1;
}

/**
****************************************************************************************************
*   GetBits
*
*   @brief
*       Copy 'bitsNum' bits from src start from srcStartPos into destination from dstStartPos
*       srcStartPos: 0~31 for UINT_32
*       bitsNum    : 1~32 for UINT_32
*       srcStartPos: 0~31 for UINT_32
*                                                                 src start position
*                                                                          |
*       src : b[31] b[30] b[29] ... ... ... ... ... ... ... ... b[end]..b[beg] ... b[1] b[0]
*                                   || Bits num || copy length  || Bits num ||
*       dst : b[31] b[30] b[29] ... b[end]..b[beg] ... ... ... ... ... ... ... ... b[1] b[0]
*                                              |
*                                     dst start position
****************************************************************************************************
*/
static inline UINT_32 GetBits(
    UINT_32 src,
    UINT_32 srcStartPos,
    UINT_32 bitsNum,
    UINT_32 dstStartPos)
{
    ADDR_ASSERT((srcStartPos < 32) && (dstStartPos < 32) && (bitsNum > 0));
    ADDR_ASSERT((bitsNum + dstStartPos <= 32) && (bitsNum + srcStartPos <= 32));

    return ((src >> srcStartPos) << (32 - bitsNum)) >> (32 - bitsNum - dstStartPos);
}

/**
****************************************************************************************************
*   MortonGen2d
*
*   @brief
*       Generate 2D Morton interleave code with num lowest bits in each channel
****************************************************************************************************
*/
static inline UINT_32 MortonGen2d(
    UINT_32     x,     ///< [in] First channel
    UINT_32     y,     ///< [in] Second channel
    UINT_32     num)   ///< [in] Number of bits extracted from each channel
{
    UINT_32 mort = 0;

    for (UINT_32 i = 0; i < num; i++)
    {
        mort |= (GetBit(y, i) << (2 * i));
        mort |= (GetBit(x, i) << (2 * i + 1));
    }

    return mort;
}

/**
****************************************************************************************************
*   MortonGen3d
*
*   @brief
*       Generate 3D Morton interleave code with num lowest bits in each channel
****************************************************************************************************
*/
static inline UINT_32 MortonGen3d(
    UINT_32     x,     ///< [in] First channel
    UINT_32     y,     ///< [in] Second channel
    UINT_32     z,     ///< [in] Third channel
    UINT_32     num)   ///< [in] Number of bits extracted from each channel
{
    UINT_32 mort = 0;

    for (UINT_32 i = 0; i < num; i++)
    {
        mort |= (GetBit(z, i) << (3 * i));
        mort |= (GetBit(y, i) << (3 * i + 1));
        mort |= (GetBit(x, i) << (3 * i + 2));
    }

    return mort;
}

/**
****************************************************************************************************
*   ReverseBitVector
*
*   @brief
*       Return reversed lowest num bits of v: v[0]v[1]...v[num-2]v[num-1]
****************************************************************************************************
*/
static inline UINT_32 ReverseBitVector(
    UINT_32     v,     ///< [in] Reverse operation base value
    UINT_32     num)   ///< [in] Number of bits used in reverse operation
{
    UINT_32 reverse = 0;

    for (UINT_32 i = 0; i < num; i++)
    {
        reverse |= (GetBit(v, num - 1 - i) << i);
    }

    return reverse;
}

/**
****************************************************************************************************
*   FoldXor2d
*
*   @brief
*       Xor bit vector v[num-1]v[num-2]...v[1]v[0] with v[num]v[num+1]...v[2*num-2]v[2*num-1]
****************************************************************************************************
*/
static inline UINT_32 FoldXor2d(
    UINT_32     v,     ///< [in] Xor operation base value
    UINT_32     num)   ///< [in] Number of bits used in fold xor operation
{
    return (v & ((1 << num) - 1)) ^ ReverseBitVector(v >> num, num);
}

/**
****************************************************************************************************
*   DeMort
*
*   @brief
*       Return v[0] | v[2] | v[4] | v[6]... | v[2*num - 2]
****************************************************************************************************
*/
static inline UINT_32 DeMort(
    UINT_32     v,     ///< [in] DeMort operation base value
    UINT_32     num)   ///< [in] Number of bits used in fold DeMort operation
{
    UINT_32 d = 0;

    for (UINT_32 i = 0; i < num; i++)
    {
        d |= ((v & (1 << (i << 1))) >> i);
    }

    return d;
}

/**
****************************************************************************************************
*   FoldXor3d
*
*   @brief
*       v[0]...v[num-1] ^ v[3*num-1]v[3*num-3]...v[num+2]v[num] ^ v[3*num-2]...v[num+1]v[num-1]
****************************************************************************************************
*/
static inline UINT_32 FoldXor3d(
    UINT_32     v,     ///< [in] Xor operation base value
    UINT_32     num)   ///< [in] Number of bits used in fold xor operation
{
    UINT_32 t = v & ((1 << num) - 1);
    t ^= ReverseBitVector(DeMort(v >> num, num), num);
    t ^= ReverseBitVector(DeMort(v >> (num + 1), num), num);

    return t;
}

/**
****************************************************************************************************
*   InitChannel
*
*   @brief
*       Set channel initialization value via a return value
****************************************************************************************************
*/
static inline ADDR_CHANNEL_SETTING InitChannel(
    UINT_32     valid,     ///< [in] valid setting
    UINT_32     channel,   ///< [in] channel setting
    UINT_32     index)     ///< [in] index setting
{
    ADDR_CHANNEL_SETTING t;
    t.valid = valid;
    t.channel = channel;
    t.index = index;

    return t;
}

/**
****************************************************************************************************
*   InitChannel
*
*   @brief
*       Set channel initialization value via channel pointer
****************************************************************************************************
*/
static inline VOID InitChannel(
    UINT_32     valid,              ///< [in] valid setting
    UINT_32     channel,            ///< [in] channel setting
    UINT_32     index,              ///< [in] index setting
    ADDR_CHANNEL_SETTING *pChanSet) ///< [out] channel setting to be initialized
{
    pChanSet->valid = valid;
    pChanSet->channel = channel;
    pChanSet->index = index;
}


/**
****************************************************************************************************
*   InitChannel
*
*   @brief
*       Set channel initialization value via another channel
****************************************************************************************************
*/
static inline VOID InitChannel(
    ADDR_CHANNEL_SETTING *pChanDst, ///< [in] channel setting to be copied from
    ADDR_CHANNEL_SETTING *pChanSrc) ///< [out] channel setting to be initialized
{
    pChanDst->valid = pChanSrc->valid;
    pChanDst->channel = pChanSrc->channel;
    pChanDst->index = pChanSrc->index;
}

/**
****************************************************************************************************
*   GetMaxValidChannelIndex
*
*   @brief
*       Get max valid index for a specific channel
****************************************************************************************************
*/
static inline UINT_32 GetMaxValidChannelIndex(
    const ADDR_CHANNEL_SETTING *pChanSet,   ///< [in] channel setting to be initialized
    UINT_32                     searchCount,///< [in] number of channel setting to be searched
    UINT_32                     channel)    ///< [in] channel to be searched
{
    UINT_32 index = 0;

    for (UINT_32 i = 0; i < searchCount; i++)
    {
        if (pChanSet[i].valid && (pChanSet[i].channel == channel))
        {
            index = Max(index, static_cast<UINT_32>(pChanSet[i].index));
        }
    }

    return index;
}

/**
****************************************************************************************************
*   GetCoordActiveMask
*
*   @brief
*       Get bit mask which indicates which positions in the equation match the target coord
****************************************************************************************************
*/
static inline UINT_32 GetCoordActiveMask(
    const ADDR_CHANNEL_SETTING *pChanSet,   ///< [in] channel setting to be initialized
    UINT_32                     searchCount,///< [in] number of channel setting to be searched
    UINT_32                     channel,    ///< [in] channel to be searched
    UINT_32                     index)      ///< [in] index to be searched
{
    UINT_32 mask = 0;

    for (UINT_32 i = 0; i < searchCount; i++)
    {
        if ((pChanSet[i].valid   == TRUE)    &&
            (pChanSet[i].channel == channel) &&
            (pChanSet[i].index   == index))
        {
            mask |= (1 << i);
        }
    }

    return mask;
}

} // Addr

#endif // __ADDR_COMMON_H__