Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright  2014 Advanced Micro Devices, Inc.
      3  * All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sub license, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     14  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     15  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     16  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
     17  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     20  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     21  *
     22  * The above copyright notice and this permission notice (including the
     23  * next paragraph) shall be included in all copies or substantial portions
     24  * of the Software.
     25  */
     26 
     27 /**
     28 ****************************************************************************************************
     29 * @file  addrcommon.h
     30 * @brief Contains the helper function and constants.
     31 ****************************************************************************************************
     32 */
     33 
     34 #ifndef __ADDR_COMMON_H__
     35 #define __ADDR_COMMON_H__
     36 
     37 #include "addrinterface.h"
     38 
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <assert.h>
     42 
     43 #if !defined(DEBUG)
     44 #ifdef NDEBUG
     45 #define DEBUG 0
     46 #else
     47 #define DEBUG 1
     48 #endif
     49 #endif
     50 
     51 ////////////////////////////////////////////////////////////////////////////////////////////////////
     52 // Platform specific debug break defines
     53 ////////////////////////////////////////////////////////////////////////////////////////////////////
     54 #if DEBUG
     55     #if defined(__GNUC__)
     56         #define ADDR_DBG_BREAK()    assert(false)
     57     #elif defined(__APPLE__)
     58         #define ADDR_DBG_BREAK()    { IOPanic("");}
     59     #else
     60         #define ADDR_DBG_BREAK()    { __debugbreak(); }
     61     #endif
     62 #else
     63     #define ADDR_DBG_BREAK()
     64 #endif
     65 ////////////////////////////////////////////////////////////////////////////////////////////////////
     66 
     67 ////////////////////////////////////////////////////////////////////////////////////////////////////
     68 // Debug assertions used in AddrLib
     69 ////////////////////////////////////////////////////////////////////////////////////////////////////
     70 #if defined(_WIN32) && (_MSC_VER >= 1400)
     71     #define ADDR_ANALYSIS_ASSUME(expr) __analysis_assume(expr)
     72 #else
     73     #define ADDR_ANALYSIS_ASSUME(expr) do { (void)(expr); } while (0)
     74 #endif
     75 
     76 #define ADDR_ASSERT(__e) assert(__e)
     77 #define ADDR_ASSERT_ALWAYS() ADDR_DBG_BREAK()
     78 #define ADDR_UNHANDLED_CASE() ADDR_ASSERT(!"Unhandled case")
     79 #define ADDR_NOT_IMPLEMENTED() ADDR_ASSERT(!"Not implemented");
     80 ////////////////////////////////////////////////////////////////////////////////////////////////////
     81 
     82 ////////////////////////////////////////////////////////////////////////////////////////////////////
     83 // Debug print macro from legacy address library
     84 ////////////////////////////////////////////////////////////////////////////////////////////////////
     85 #if DEBUG
     86 
     87 #define ADDR_PRNT(a)    Object::DebugPrint a
     88 
     89 /// @brief Macro for reporting informational messages
     90 /// @ingroup util
     91 ///
     92 /// This macro optionally prints an informational message to stdout.
     93 /// The first parameter is a condition -- if it is true, nothing is done.
     94 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
     95 /// starting with a string. This is passed to printf() or an equivalent
     96 /// in order to format the informational message. For example,
     97 /// ADDR_INFO(0, ("test %d",3) ); prints out "test 3".
     98 ///
     99 #define ADDR_INFO(cond, a)         \
    100 { if (!(cond)) { ADDR_PRNT(a); } }
    101 
    102 
    103 /// @brief Macro for reporting error warning messages
    104 /// @ingroup util
    105 ///
    106 /// This macro optionally prints an error warning message to stdout,
    107 /// followed by the file name and line number where the macro was called.
    108 /// The first parameter is a condition -- if it is true, nothing is done.
    109 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
    110 /// starting with a string. This is passed to printf() or an equivalent
    111 /// in order to format the informational message. For example,
    112 /// ADDR_WARN(0, ("test %d",3) ); prints out "test 3" followed by
    113 /// a second line with the file name and line number.
    114 ///
    115 #define ADDR_WARN(cond, a)         \
    116 { if (!(cond))                     \
    117   { ADDR_PRNT(a);                  \
    118     ADDR_PRNT(("  WARNING in file %s, line %d\n", __FILE__, __LINE__)); \
    119 } }
    120 
    121 
    122 /// @brief Macro for reporting fatal error conditions
    123 /// @ingroup util
    124 ///
    125 /// This macro optionally stops execution of the current routine
    126 /// after printing an error warning message to stdout,
    127 /// followed by the file name and line number where the macro was called.
    128 /// The first parameter is a condition -- if it is true, nothing is done.
    129 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
    130 /// starting with a string. This is passed to printf() or an equivalent
    131 /// in order to format the informational message. For example,
    132 /// ADDR_EXIT(0, ("test %d",3) ); prints out "test 3" followed by
    133 /// a second line with the file name and line number, then stops execution.
    134 ///
    135 #define ADDR_EXIT(cond, a)         \
    136 { if (!(cond))                     \
    137   { ADDR_PRNT(a); ADDR_DBG_BREAK();\
    138 } }
    139 
    140 #else // DEBUG
    141 
    142 #define ADDRDPF 1 ? (void)0 : (void)
    143 
    144 #define ADDR_PRNT(a)
    145 
    146 #define ADDR_DBG_BREAK()
    147 
    148 #define ADDR_INFO(cond, a)
    149 
    150 #define ADDR_WARN(cond, a)
    151 
    152 #define ADDR_EXIT(cond, a)
    153 
    154 #endif // DEBUG
    155 ////////////////////////////////////////////////////////////////////////////////////////////////////
    156 
    157 #define ADDR_C_ASSERT(__e) typedef char __ADDR_C_ASSERT__[(__e) ? 1 : -1]
    158 
    159 namespace Addr
    160 {
    161 
    162 namespace V1
    163 {
    164 ////////////////////////////////////////////////////////////////////////////////////////////////////
    165 // Common constants
    166 ////////////////////////////////////////////////////////////////////////////////////////////////////
    167 static const UINT_32 MicroTileWidth      = 8;       ///< Micro tile width, for 1D and 2D tiling
    168 static const UINT_32 MicroTileHeight     = 8;       ///< Micro tile height, for 1D and 2D tiling
    169 static const UINT_32 ThickTileThickness  = 4;       ///< Micro tile thickness, for THICK modes
    170 static const UINT_32 XThickTileThickness = 8;       ///< Extra thick tiling thickness
    171 static const UINT_32 PowerSaveTileBytes  = 64;      ///< Nuber of bytes per tile for power save 64
    172 static const UINT_32 CmaskCacheBits      = 1024;    ///< Number of bits for CMASK cache
    173 static const UINT_32 CmaskElemBits       = 4;       ///< Number of bits for CMASK element
    174 static const UINT_32 HtileCacheBits      = 16384;   ///< Number of bits for HTILE cache 512*32
    175 
    176 static const UINT_32 MicroTilePixels     = MicroTileWidth * MicroTileHeight;
    177 
    178 static const INT_32 TileIndexInvalid        = TILEINDEX_INVALID;
    179 static const INT_32 TileIndexLinearGeneral  = TILEINDEX_LINEAR_GENERAL;
    180 static const INT_32 TileIndexNoMacroIndex   = -3;
    181 
    182 } // V1
    183 
    184 namespace V2
    185 {
    186 ////////////////////////////////////////////////////////////////////////////////////////////////////
    187 // Common constants
    188 ////////////////////////////////////////////////////////////////////////////////////////////////////
    189 static const UINT_32 MaxSurfaceHeight = 16384;
    190 
    191 } // V2
    192 
    193 ////////////////////////////////////////////////////////////////////////////////////////////////////
    194 // Common macros
    195 ////////////////////////////////////////////////////////////////////////////////////////////////////
    196 #define BITS_PER_BYTE 8
    197 #define BITS_TO_BYTES(x) ( ((x) + (BITS_PER_BYTE-1)) / BITS_PER_BYTE )
    198 #define BYTES_TO_BITS(x) ( (x) * BITS_PER_BYTE )
    199 
    200 /// Helper macros to select a single bit from an int (undefined later in section)
    201 #define _BIT(v,b)      (((v) >> (b) ) & 1)
    202 
    203 /**
    204 ****************************************************************************************************
    205 * @brief Enums to identify AddrLib type
    206 ****************************************************************************************************
    207 */
    208 enum LibClass
    209 {
    210     BASE_ADDRLIB = 0x0,
    211     R600_ADDRLIB = 0x6,
    212     R800_ADDRLIB = 0x8,
    213     SI_ADDRLIB   = 0xa,
    214     CI_ADDRLIB   = 0xb,
    215     AI_ADDRLIB   = 0xd,
    216 };
    217 
    218 /**
    219 ****************************************************************************************************
    220 * ChipFamily
    221 *
    222 *   @brief
    223 *       Neutral enums that specifies chip family.
    224 *
    225 ****************************************************************************************************
    226 */
    227 enum ChipFamily
    228 {
    229     ADDR_CHIP_FAMILY_IVLD,    ///< Invalid family
    230     ADDR_CHIP_FAMILY_R6XX,
    231     ADDR_CHIP_FAMILY_R7XX,
    232     ADDR_CHIP_FAMILY_R8XX,
    233     ADDR_CHIP_FAMILY_NI,
    234     ADDR_CHIP_FAMILY_SI,
    235     ADDR_CHIP_FAMILY_CI,
    236     ADDR_CHIP_FAMILY_VI,
    237     ADDR_CHIP_FAMILY_AI,
    238 };
    239 
    240 /**
    241 ****************************************************************************************************
    242 * ConfigFlags
    243 *
    244 *   @brief
    245 *       This structure is used to set configuration flags.
    246 ****************************************************************************************************
    247 */
    248 union ConfigFlags
    249 {
    250     struct
    251     {
    252         /// These flags are set up internally thru AddrLib::Create() based on ADDR_CREATE_FLAGS
    253         UINT_32 optimalBankSwap        : 1;    ///< New bank tiling for RV770 only
    254         UINT_32 noCubeMipSlicesPad     : 1;    ///< Disables faces padding for cubemap mipmaps
    255         UINT_32 fillSizeFields         : 1;    ///< If clients fill size fields in all input and
    256                                                ///  output structure
    257         UINT_32 ignoreTileInfo         : 1;    ///< Don't use tile info structure
    258         UINT_32 useTileIndex           : 1;    ///< Make tileIndex field in input valid
    259         UINT_32 useCombinedSwizzle     : 1;    ///< Use combined swizzle
    260         UINT_32 checkLast2DLevel       : 1;    ///< Check the last 2D mip sub level
    261         UINT_32 useHtileSliceAlign     : 1;    ///< Do htile single slice alignment
    262         UINT_32 allowLargeThickTile    : 1;    ///< Allow 64*thickness*bytesPerPixel > rowSize
    263         UINT_32 disableLinearOpt       : 1;    ///< Disallow tile modes to be optimized to linear
    264         UINT_32 reserved               : 22;   ///< Reserved bits for future use
    265     };
    266 
    267     UINT_32 value;
    268 };
    269 
    270 ////////////////////////////////////////////////////////////////////////////////////////////////////
    271 // Misc helper functions
    272 ////////////////////////////////////////////////////////////////////////////////////////////////////
    273 
    274 /**
    275 ****************************************************************************************************
    276 *   AddrXorReduce
    277 *
    278 *   @brief
    279 *       Xor the right-side numberOfBits bits of x.
    280 ****************************************************************************************************
    281 */
    282 static inline UINT_32 XorReduce(
    283     UINT_32 x,
    284     UINT_32 numberOfBits)
    285 {
    286     UINT_32 i;
    287     UINT_32 result = x & 1;
    288 
    289     for (i=1; i<numberOfBits; i++)
    290     {
    291         result ^= ((x>>i) & 1);
    292     }
    293 
    294     return result;
    295 }
    296 
    297 /**
    298 ****************************************************************************************************
    299 *   IsPow2
    300 *
    301 *   @brief
    302 *       Check if the size (UINT_32) is pow 2
    303 ****************************************************************************************************
    304 */
    305 static inline UINT_32 IsPow2(
    306     UINT_32 dim)        ///< [in] dimension of miplevel
    307 {
    308     ADDR_ASSERT(dim > 0);
    309     return !(dim & (dim - 1));
    310 }
    311 
    312 /**
    313 ****************************************************************************************************
    314 *   IsPow2
    315 *
    316 *   @brief
    317 *       Check if the size (UINT_64) is pow 2
    318 ****************************************************************************************************
    319 */
    320 static inline UINT_64 IsPow2(
    321     UINT_64 dim)        ///< [in] dimension of miplevel
    322 {
    323     ADDR_ASSERT(dim > 0);
    324     return !(dim & (dim - 1));
    325 }
    326 
    327 /**
    328 ****************************************************************************************************
    329 *   ByteAlign
    330 *
    331 *   @brief
    332 *       Align UINT_32 "x" to "align" alignment, "align" should be power of 2
    333 ****************************************************************************************************
    334 */
    335 static inline UINT_32 PowTwoAlign(
    336     UINT_32 x,
    337     UINT_32 align)
    338 {
    339     //
    340     // Assert that x is a power of two.
    341     //
    342     ADDR_ASSERT(IsPow2(align));
    343     return (x + (align - 1)) & (~(align - 1));
    344 }
    345 
    346 /**
    347 ****************************************************************************************************
    348 *   ByteAlign
    349 *
    350 *   @brief
    351 *       Align UINT_64 "x" to "align" alignment, "align" should be power of 2
    352 ****************************************************************************************************
    353 */
    354 static inline UINT_64 PowTwoAlign(
    355     UINT_64 x,
    356     UINT_64 align)
    357 {
    358     //
    359     // Assert that x is a power of two.
    360     //
    361     ADDR_ASSERT(IsPow2(align));
    362     return (x + (align - 1)) & (~(align - 1));
    363 }
    364 
    365 /**
    366 ****************************************************************************************************
    367 *   Min
    368 *
    369 *   @brief
    370 *       Get the min value between two unsigned values
    371 ****************************************************************************************************
    372 */
    373 static inline UINT_32 Min(
    374     UINT_32 value1,
    375     UINT_32 value2)
    376 {
    377     return ((value1 < (value2)) ? (value1) : value2);
    378 }
    379 
    380 /**
    381 ****************************************************************************************************
    382 *   Min
    383 *
    384 *   @brief
    385 *       Get the min value between two signed values
    386 ****************************************************************************************************
    387 */
    388 static inline INT_32 Min(
    389     INT_32 value1,
    390     INT_32 value2)
    391 {
    392     return ((value1 < (value2)) ? (value1) : value2);
    393 }
    394 
    395 /**
    396 ****************************************************************************************************
    397 *   Max
    398 *
    399 *   @brief
    400 *       Get the max value between two unsigned values
    401 ****************************************************************************************************
    402 */
    403 static inline UINT_32 Max(
    404     UINT_32 value1,
    405     UINT_32 value2)
    406 {
    407     return ((value1 > (value2)) ? (value1) : value2);
    408 }
    409 
    410 /**
    411 ****************************************************************************************************
    412 *   Max
    413 *
    414 *   @brief
    415 *       Get the max value between two signed values
    416 ****************************************************************************************************
    417 */
    418 static inline INT_32 Max(
    419     INT_32 value1,
    420     INT_32 value2)
    421 {
    422     return ((value1 > (value2)) ? (value1) : value2);
    423 }
    424 
    425 /**
    426 ****************************************************************************************************
    427 *   NextPow2
    428 *
    429 *   @brief
    430 *       Compute the mipmap's next level dim size
    431 ****************************************************************************************************
    432 */
    433 static inline UINT_32 NextPow2(
    434     UINT_32 dim)        ///< [in] dimension of miplevel
    435 {
    436     UINT_32 newDim = 1;
    437 
    438     if (dim > 0x7fffffff)
    439     {
    440         ADDR_ASSERT_ALWAYS();
    441         newDim = 0x80000000;
    442     }
    443     else
    444     {
    445         while (newDim < dim)
    446         {
    447             newDim <<= 1;
    448         }
    449     }
    450 
    451     return newDim;
    452 }
    453 
    454 /**
    455 ****************************************************************************************************
    456 *   Log2NonPow2
    457 *
    458 *   @brief
    459 *       Compute log of base 2 no matter the target is power of 2 or not
    460 ****************************************************************************************************
    461 */
    462 static inline UINT_32 Log2NonPow2(
    463     UINT_32 x)      ///< [in] the value should calculate log based 2
    464 {
    465     UINT_32 y;
    466 
    467     y = 0;
    468     while (x > 1)
    469     {
    470         x >>= 1;
    471         y++;
    472     }
    473 
    474     return y;
    475 }
    476 
    477 /**
    478 ****************************************************************************************************
    479 *   Log2
    480 *
    481 *   @brief
    482 *       Compute log of base 2
    483 ****************************************************************************************************
    484 */
    485 static inline UINT_32 Log2(
    486     UINT_32 x)      ///< [in] the value should calculate log based 2
    487 {
    488     // Assert that x is a power of two.
    489     ADDR_ASSERT(IsPow2(x));
    490 
    491     return Log2NonPow2(x);
    492 }
    493 
    494 /**
    495 ****************************************************************************************************
    496 *   QLog2
    497 *
    498 *   @brief
    499 *       Compute log of base 2 quickly (<= 16)
    500 ****************************************************************************************************
    501 */
    502 static inline UINT_32 QLog2(
    503     UINT_32 x)      ///< [in] the value should calculate log based 2
    504 {
    505     ADDR_ASSERT(x <= 16);
    506 
    507     UINT_32 y = 0;
    508 
    509     switch (x)
    510     {
    511         case 1:
    512             y = 0;
    513             break;
    514         case 2:
    515             y = 1;
    516             break;
    517         case 4:
    518             y = 2;
    519             break;
    520         case 8:
    521             y = 3;
    522             break;
    523         case 16:
    524             y = 4;
    525             break;
    526         default:
    527             ADDR_ASSERT_ALWAYS();
    528     }
    529 
    530     return y;
    531 }
    532 
    533 /**
    534 ****************************************************************************************************
    535 *   SafeAssign
    536 *
    537 *   @brief
    538 *       NULL pointer safe assignment
    539 ****************************************************************************************************
    540 */
    541 static inline VOID SafeAssign(
    542     UINT_32*    pLVal,  ///< [in] Pointer to left val
    543     UINT_32     rVal)   ///< [in] Right value
    544 {
    545     if (pLVal)
    546     {
    547         *pLVal = rVal;
    548     }
    549 }
    550 
    551 /**
    552 ****************************************************************************************************
    553 *   SafeAssign
    554 *
    555 *   @brief
    556 *       NULL pointer safe assignment for 64bit values
    557 ****************************************************************************************************
    558 */
    559 static inline VOID SafeAssign(
    560     UINT_64*    pLVal,  ///< [in] Pointer to left val
    561     UINT_64     rVal)   ///< [in] Right value
    562 {
    563     if (pLVal)
    564     {
    565         *pLVal = rVal;
    566     }
    567 }
    568 
    569 /**
    570 ****************************************************************************************************
    571 *   SafeAssign
    572 *
    573 *   @brief
    574 *       NULL pointer safe assignment for AddrTileMode
    575 ****************************************************************************************************
    576 */
    577 static inline VOID SafeAssign(
    578     AddrTileMode*    pLVal, ///< [in] Pointer to left val
    579     AddrTileMode     rVal)  ///< [in] Right value
    580 {
    581     if (pLVal)
    582     {
    583         *pLVal = rVal;
    584     }
    585 }
    586 
    587 /**
    588 ****************************************************************************************************
    589 *   RoundHalf
    590 *
    591 *   @brief
    592 *       return (x + 1) / 2
    593 ****************************************************************************************************
    594 */
    595 static inline UINT_32 RoundHalf(
    596     UINT_32     x)     ///< [in] input value
    597 {
    598     ADDR_ASSERT(x != 0);
    599 
    600 #if 1
    601     return (x >> 1) + (x & 1);
    602 #else
    603     return (x + 1) >> 1;
    604 #endif
    605 }
    606 
    607 /**
    608 ****************************************************************************************************
    609 *   SumGeo
    610 *
    611 *   @brief
    612 *       Calculate sum of a geometric progression whose ratio is 1/2
    613 ****************************************************************************************************
    614 */
    615 static inline UINT_32 SumGeo(
    616     UINT_32     base,   ///< [in] First term in the geometric progression
    617     UINT_32     num)    ///< [in] Number of terms to be added into sum
    618 {
    619     ADDR_ASSERT(base > 0);
    620 
    621     UINT_32 sum = 0;
    622     UINT_32 i = 0;
    623     for (; (i < num) && (base > 1); i++)
    624     {
    625         sum += base;
    626         base = RoundHalf(base);
    627     }
    628     sum += num - i;
    629 
    630     return sum;
    631 }
    632 
    633 /**
    634 ****************************************************************************************************
    635 *   GetBit
    636 *
    637 *   @brief
    638 *       Extract bit N value (0 or 1) of a UINT32 value.
    639 ****************************************************************************************************
    640 */
    641 static inline UINT_32 GetBit(
    642     UINT_32     u32,   ///< [in] UINT32 value
    643     UINT_32     pos)   ///< [in] bit position from LSB, valid range is [0..31]
    644 {
    645     ADDR_ASSERT(pos <= 31);
    646 
    647     return (u32 >> pos) & 0x1;
    648 }
    649 
    650 /**
    651 ****************************************************************************************************
    652 *   GetBits
    653 *
    654 *   @brief
    655 *       Copy 'bitsNum' bits from src start from srcStartPos into destination from dstStartPos
    656 *       srcStartPos: 0~31 for UINT_32
    657 *       bitsNum    : 1~32 for UINT_32
    658 *       srcStartPos: 0~31 for UINT_32
    659 *                                                                 src start position
    660 *                                                                          |
    661 *       src : b[31] b[30] b[29] ... ... ... ... ... ... ... ... b[end]..b[beg] ... b[1] b[0]
    662 *                                   || Bits num || copy length  || Bits num ||
    663 *       dst : b[31] b[30] b[29] ... b[end]..b[beg] ... ... ... ... ... ... ... ... b[1] b[0]
    664 *                                              |
    665 *                                     dst start position
    666 ****************************************************************************************************
    667 */
    668 static inline UINT_32 GetBits(
    669     UINT_32 src,
    670     UINT_32 srcStartPos,
    671     UINT_32 bitsNum,
    672     UINT_32 dstStartPos)
    673 {
    674     ADDR_ASSERT((srcStartPos < 32) && (dstStartPos < 32) && (bitsNum > 0));
    675     ADDR_ASSERT((bitsNum + dstStartPos <= 32) && (bitsNum + srcStartPos <= 32));
    676 
    677     return ((src >> srcStartPos) << (32 - bitsNum)) >> (32 - bitsNum - dstStartPos);
    678 }
    679 
    680 /**
    681 ****************************************************************************************************
    682 *   MortonGen2d
    683 *
    684 *   @brief
    685 *       Generate 2D Morton interleave code with num lowest bits in each channel
    686 ****************************************************************************************************
    687 */
    688 static inline UINT_32 MortonGen2d(
    689     UINT_32     x,     ///< [in] First channel
    690     UINT_32     y,     ///< [in] Second channel
    691     UINT_32     num)   ///< [in] Number of bits extracted from each channel
    692 {
    693     UINT_32 mort = 0;
    694 
    695     for (UINT_32 i = 0; i < num; i++)
    696     {
    697         mort |= (GetBit(y, i) << (2 * i));
    698         mort |= (GetBit(x, i) << (2 * i + 1));
    699     }
    700 
    701     return mort;
    702 }
    703 
    704 /**
    705 ****************************************************************************************************
    706 *   MortonGen3d
    707 *
    708 *   @brief
    709 *       Generate 3D Morton interleave code with num lowest bits in each channel
    710 ****************************************************************************************************
    711 */
    712 static inline UINT_32 MortonGen3d(
    713     UINT_32     x,     ///< [in] First channel
    714     UINT_32     y,     ///< [in] Second channel
    715     UINT_32     z,     ///< [in] Third channel
    716     UINT_32     num)   ///< [in] Number of bits extracted from each channel
    717 {
    718     UINT_32 mort = 0;
    719 
    720     for (UINT_32 i = 0; i < num; i++)
    721     {
    722         mort |= (GetBit(z, i) << (3 * i));
    723         mort |= (GetBit(y, i) << (3 * i + 1));
    724         mort |= (GetBit(x, i) << (3 * i + 2));
    725     }
    726 
    727     return mort;
    728 }
    729 
    730 /**
    731 ****************************************************************************************************
    732 *   ReverseBitVector
    733 *
    734 *   @brief
    735 *       Return reversed lowest num bits of v: v[0]v[1]...v[num-2]v[num-1]
    736 ****************************************************************************************************
    737 */
    738 static inline UINT_32 ReverseBitVector(
    739     UINT_32     v,     ///< [in] Reverse operation base value
    740     UINT_32     num)   ///< [in] Number of bits used in reverse operation
    741 {
    742     UINT_32 reverse = 0;
    743 
    744     for (UINT_32 i = 0; i < num; i++)
    745     {
    746         reverse |= (GetBit(v, num - 1 - i) << i);
    747     }
    748 
    749     return reverse;
    750 }
    751 
    752 /**
    753 ****************************************************************************************************
    754 *   FoldXor2d
    755 *
    756 *   @brief
    757 *       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]
    758 ****************************************************************************************************
    759 */
    760 static inline UINT_32 FoldXor2d(
    761     UINT_32     v,     ///< [in] Xor operation base value
    762     UINT_32     num)   ///< [in] Number of bits used in fold xor operation
    763 {
    764     return (v & ((1 << num) - 1)) ^ ReverseBitVector(v >> num, num);
    765 }
    766 
    767 /**
    768 ****************************************************************************************************
    769 *   DeMort
    770 *
    771 *   @brief
    772 *       Return v[0] | v[2] | v[4] | v[6]... | v[2*num - 2]
    773 ****************************************************************************************************
    774 */
    775 static inline UINT_32 DeMort(
    776     UINT_32     v,     ///< [in] DeMort operation base value
    777     UINT_32     num)   ///< [in] Number of bits used in fold DeMort operation
    778 {
    779     UINT_32 d = 0;
    780 
    781     for (UINT_32 i = 0; i < num; i++)
    782     {
    783         d |= ((v & (1 << (i << 1))) >> i);
    784     }
    785 
    786     return d;
    787 }
    788 
    789 /**
    790 ****************************************************************************************************
    791 *   FoldXor3d
    792 *
    793 *   @brief
    794 *       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]
    795 ****************************************************************************************************
    796 */
    797 static inline UINT_32 FoldXor3d(
    798     UINT_32     v,     ///< [in] Xor operation base value
    799     UINT_32     num)   ///< [in] Number of bits used in fold xor operation
    800 {
    801     UINT_32 t = v & ((1 << num) - 1);
    802     t ^= ReverseBitVector(DeMort(v >> num, num), num);
    803     t ^= ReverseBitVector(DeMort(v >> (num + 1), num), num);
    804 
    805     return t;
    806 }
    807 
    808 /**
    809 ****************************************************************************************************
    810 *   InitChannel
    811 *
    812 *   @brief
    813 *       Set channel initialization value via a return value
    814 ****************************************************************************************************
    815 */
    816 static inline ADDR_CHANNEL_SETTING InitChannel(
    817     UINT_32     valid,     ///< [in] valid setting
    818     UINT_32     channel,   ///< [in] channel setting
    819     UINT_32     index)     ///< [in] index setting
    820 {
    821     ADDR_CHANNEL_SETTING t;
    822     t.valid = valid;
    823     t.channel = channel;
    824     t.index = index;
    825 
    826     return t;
    827 }
    828 
    829 /**
    830 ****************************************************************************************************
    831 *   InitChannel
    832 *
    833 *   @brief
    834 *       Set channel initialization value via channel pointer
    835 ****************************************************************************************************
    836 */
    837 static inline VOID InitChannel(
    838     UINT_32     valid,              ///< [in] valid setting
    839     UINT_32     channel,            ///< [in] channel setting
    840     UINT_32     index,              ///< [in] index setting
    841     ADDR_CHANNEL_SETTING *pChanSet) ///< [out] channel setting to be initialized
    842 {
    843     pChanSet->valid = valid;
    844     pChanSet->channel = channel;
    845     pChanSet->index = index;
    846 }
    847 
    848 
    849 /**
    850 ****************************************************************************************************
    851 *   InitChannel
    852 *
    853 *   @brief
    854 *       Set channel initialization value via another channel
    855 ****************************************************************************************************
    856 */
    857 static inline VOID InitChannel(
    858     ADDR_CHANNEL_SETTING *pChanDst, ///< [in] channel setting to be copied from
    859     ADDR_CHANNEL_SETTING *pChanSrc) ///< [out] channel setting to be initialized
    860 {
    861     pChanDst->valid = pChanSrc->valid;
    862     pChanDst->channel = pChanSrc->channel;
    863     pChanDst->index = pChanSrc->index;
    864 }
    865 
    866 /**
    867 ****************************************************************************************************
    868 *   GetMaxValidChannelIndex
    869 *
    870 *   @brief
    871 *       Get max valid index for a specific channel
    872 ****************************************************************************************************
    873 */
    874 static inline UINT_32 GetMaxValidChannelIndex(
    875     const ADDR_CHANNEL_SETTING *pChanSet,   ///< [in] channel setting to be initialized
    876     UINT_32                     searchCount,///< [in] number of channel setting to be searched
    877     UINT_32                     channel)    ///< [in] channel to be searched
    878 {
    879     UINT_32 index = 0;
    880 
    881     for (UINT_32 i = 0; i < searchCount; i++)
    882     {
    883         if (pChanSet[i].valid && (pChanSet[i].channel == channel))
    884         {
    885             index = Max(index, static_cast<UINT_32>(pChanSet[i].index));
    886         }
    887     }
    888 
    889     return index;
    890 }
    891 
    892 /**
    893 ****************************************************************************************************
    894 *   GetCoordActiveMask
    895 *
    896 *   @brief
    897 *       Get bit mask which indicates which positions in the equation match the target coord
    898 ****************************************************************************************************
    899 */
    900 static inline UINT_32 GetCoordActiveMask(
    901     const ADDR_CHANNEL_SETTING *pChanSet,   ///< [in] channel setting to be initialized
    902     UINT_32                     searchCount,///< [in] number of channel setting to be searched
    903     UINT_32                     channel,    ///< [in] channel to be searched
    904     UINT_32                     index)      ///< [in] index to be searched
    905 {
    906     UINT_32 mask = 0;
    907 
    908     for (UINT_32 i = 0; i < searchCount; i++)
    909     {
    910         if ((pChanSet[i].valid   == TRUE)    &&
    911             (pChanSet[i].channel == channel) &&
    912             (pChanSet[i].index   == index))
    913         {
    914             mask |= (1 << i);
    915         }
    916     }
    917 
    918     return mask;
    919 }
    920 
    921 } // Addr
    922 
    923 #endif // __ADDR_COMMON_H__
    924 
    925