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