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