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