mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-23 10:48:08 +02:00
Signed-off-by: Eric Engestrom <eric.engestrom@imgtec.com> Reviewed-by: Marek Olšák <marek.olsak@amd.com>
924 lines
29 KiB
C++
924 lines
29 KiB
C++
/*
|
|
* 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__
|
|
|