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