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