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