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