amdgpu/addrlib: add ADDR_ANALYSIS_ASSUME
[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
40 // ADDR_LNX_KERNEL_BUILD is for internal build
41 // Moved from addrinterface.h so __KERNEL__ is not needed any more
42 #if ADDR_LNX_KERNEL_BUILD // || (defined(__GNUC__) && defined(__KERNEL__))
43 #include "lnx_common_defs.h" // ported from cmmqs
44 #elif !defined(__APPLE__)
45 #include <stdlib.h>
46 #include <string.h>
47 #endif
48
49 ///////////////////////////////////////////////////////////////////////////////////////////////////
50 // Common constants
51 ///////////////////////////////////////////////////////////////////////////////////////////////////
52 static const UINT_32 MicroTileWidth = 8; ///< Micro tile width, for 1D and 2D tiling
53 static const UINT_32 MicroTileHeight = 8; ///< Micro tile height, for 1D and 2D tiling
54 static const UINT_32 ThickTileThickness = 4; ///< Micro tile thickness, for THICK modes
55 static const UINT_32 XThickTileThickness = 8; ///< Extra thick tiling thickness
56 static const UINT_32 PowerSaveTileBytes = 64; ///< Nuber of bytes per tile for power save 64
57 static const UINT_32 CmaskCacheBits = 1024; ///< Number of bits for CMASK cache
58 static const UINT_32 CmaskElemBits = 4; ///< Number of bits for CMASK element
59 static const UINT_32 HtileCacheBits = 16384; ///< Number of bits for HTILE cache 512*32
60
61 static const UINT_32 MicroTilePixels = MicroTileWidth * MicroTileHeight;
62
63 static const INT_32 TileIndexInvalid = TILEINDEX_INVALID;
64 static const INT_32 TileIndexLinearGeneral = TILEINDEX_LINEAR_GENERAL;
65 static const INT_32 TileIndexNoMacroIndex = -3;
66
67 ///////////////////////////////////////////////////////////////////////////////////////////////////
68 // Common macros
69 ///////////////////////////////////////////////////////////////////////////////////////////////////
70 #define BITS_PER_BYTE 8
71 #define BITS_TO_BYTES(x) ( ((x) + (BITS_PER_BYTE-1)) / BITS_PER_BYTE )
72 #define BYTES_TO_BITS(x) ( (x) * BITS_PER_BYTE )
73
74 /// Helper macros to select a single bit from an int (undefined later in section)
75 #define _BIT(v,b) (((v) >> (b) ) & 1)
76
77 /**
78 ***************************************************************************************************
79 * @brief Enums to identify AddrLib type
80 ***************************************************************************************************
81 */
82 enum AddrLibClass
83 {
84 BASE_ADDRLIB = 0x0,
85 R600_ADDRLIB = 0x6,
86 R800_ADDRLIB = 0x8,
87 SI_ADDRLIB = 0xa,
88 CI_ADDRLIB = 0xb,
89 };
90
91 /**
92 ***************************************************************************************************
93 * AddrChipFamily
94 *
95 * @brief
96 * Neutral enums that specifies chip family.
97 *
98 ***************************************************************************************************
99 */
100 enum AddrChipFamily
101 {
102 ADDR_CHIP_FAMILY_IVLD, ///< Invalid family
103 ADDR_CHIP_FAMILY_R6XX,
104 ADDR_CHIP_FAMILY_R7XX,
105 ADDR_CHIP_FAMILY_R8XX,
106 ADDR_CHIP_FAMILY_NI,
107 ADDR_CHIP_FAMILY_SI,
108 ADDR_CHIP_FAMILY_CI,
109 ADDR_CHIP_FAMILY_VI,
110 };
111
112 /**
113 ***************************************************************************************************
114 * ADDR_CONFIG_FLAGS
115 *
116 * @brief
117 * This structure is used to set addr configuration flags.
118 ***************************************************************************************************
119 */
120 union ADDR_CONFIG_FLAGS
121 {
122 struct
123 {
124 /// Clients do not need to set these flags except forceLinearAligned.
125 /// There flags are set up by AddrLib inside thru AddrInitGlobalParamsFromRegister
126 UINT_32 optimalBankSwap : 1; ///< New bank tiling for RV770 only
127 UINT_32 noCubeMipSlicesPad : 1; ///< Disables faces padding for cubemap mipmaps
128 UINT_32 fillSizeFields : 1; ///< If clients fill size fields in all input and
129 /// output structure
130 UINT_32 ignoreTileInfo : 1; ///< Don't use tile info structure
131 UINT_32 useTileIndex : 1; ///< Make tileIndex field in input valid
132 UINT_32 useCombinedSwizzle : 1; ///< Use combined swizzle
133 UINT_32 checkLast2DLevel : 1; ///< Check the last 2D mip sub level
134 UINT_32 useHtileSliceAlign : 1; ///< Do htile single slice alignment
135 UINT_32 allowLargeThickTile : 1; ///< Allow 64*thickness*bytesPerPixel > rowSize
136 UINT_32 disableLinearOpt : 1; ///< Disallow tile modes to be optimized to linear
137 UINT_32 reserved : 22; ///< Reserved bits for future use
138 };
139
140 UINT_32 value;
141 };
142
143 ///////////////////////////////////////////////////////////////////////////////////////////////////
144 // Platform specific debug break defines
145 ///////////////////////////////////////////////////////////////////////////////////////////////////
146 #if DEBUG
147 #if defined(__GNUC__)
148 #define ADDR_DBG_BREAK()
149 #elif defined(__APPLE__)
150 #define ADDR_DBG_BREAK() { IOPanic("");}
151 #else
152 #define ADDR_DBG_BREAK() { __debugbreak(); }
153 #endif
154 #else
155 #define ADDR_DBG_BREAK()
156 #endif
157 ///////////////////////////////////////////////////////////////////////////////////////////////////
158
159 ///////////////////////////////////////////////////////////////////////////////////////////////////
160 // Debug assertions used in AddrLib
161 ///////////////////////////////////////////////////////////////////////////////////////////////////
162 #if defined(_WIN32) && (_MSC_VER >= 1400)
163 #define ADDR_ANALYSIS_ASSUME(expr) __analysis_assume(expr)
164 #else
165 #define ADDR_ANALYSIS_ASSUME(expr) do { } while (0)
166 #endif
167
168 #if DEBUG
169 #define ADDR_ASSERT(__e) \
170 do { \
171 ADDR_ANALYSIS_ASSUME(__e); \
172 if ( !((__e) ? TRUE : FALSE)) { ADDR_DBG_BREAK(); } \
173 } while (0)
174 #define ADDR_ASSERT_ALWAYS() ADDR_DBG_BREAK()
175 #define ADDR_UNHANDLED_CASE() ADDR_ASSERT(!"Unhandled case")
176 #define ADDR_NOT_IMPLEMENTED() ADDR_ASSERT(!"Not implemented");
177 #else //DEBUG
178 #define ADDR_ASSERT(__e) ADDR_ANALYSIS_ASSUME(__e)
179 #define ADDR_ASSERT_ALWAYS()
180 #define ADDR_UNHANDLED_CASE()
181 #define ADDR_NOT_IMPLEMENTED()
182 #endif //DEBUG
183 ///////////////////////////////////////////////////////////////////////////////////////////////////
184
185 ///////////////////////////////////////////////////////////////////////////////////////////////////
186 // Debug print macro from legacy address library
187 ///////////////////////////////////////////////////////////////////////////////////////////////////
188 #if DEBUG
189
190 #define ADDR_PRNT(a) AddrObject::DebugPrint a
191
192 /// @brief Macro for reporting informational messages
193 /// @ingroup util
194 ///
195 /// This macro optionally prints an informational message to stdout.
196 /// The first parameter is a condition -- if it is true, nothing is done.
197 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
198 /// starting with a string. This is passed to printf() or an equivalent
199 /// in order to format the informational message. For example,
200 /// ADDR_INFO(0, ("test %d",3) ); prints out "test 3".
201 ///
202 #define ADDR_INFO(cond, a) \
203 { if (!(cond)) { ADDR_PRNT(a); } }
204
205
206 /// @brief Macro for reporting error warning messages
207 /// @ingroup util
208 ///
209 /// This macro optionally prints an error warning message to stdout,
210 /// followed by the file name and line number where the macro was called.
211 /// The first parameter is a condition -- if it is true, nothing is done.
212 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
213 /// starting with a string. This is passed to printf() or an equivalent
214 /// in order to format the informational message. For example,
215 /// ADDR_WARN(0, ("test %d",3) ); prints out "test 3" followed by
216 /// a second line with the file name and line number.
217 ///
218 #define ADDR_WARN(cond, a) \
219 { if (!(cond)) \
220 { ADDR_PRNT(a); \
221 ADDR_PRNT((" WARNING in file %s, line %d\n", __FILE__, __LINE__)); \
222 } }
223
224
225 /// @brief Macro for reporting fatal error conditions
226 /// @ingroup util
227 ///
228 /// This macro optionally stops execution of the current routine
229 /// after printing an error warning message to stdout,
230 /// followed by the file name and line number where the macro was called.
231 /// The first parameter is a condition -- if it is true, nothing is done.
232 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
233 /// starting with a string. This is passed to printf() or an equivalent
234 /// in order to format the informational message. For example,
235 /// ADDR_EXIT(0, ("test %d",3) ); prints out "test 3" followed by
236 /// a second line with the file name and line number, then stops execution.
237 ///
238 #define ADDR_EXIT(cond, a) \
239 { if (!(cond)) \
240 { ADDR_PRNT(a); ADDR_DBG_BREAK();\
241 } }
242
243 #else // DEBUG
244
245 #define ADDRDPF 1 ? (void)0 : (void)
246
247 #define ADDR_PRNT(a)
248
249 #define ADDR_DBG_BREAK()
250
251 #define ADDR_INFO(cond, a)
252
253 #define ADDR_WARN(cond, a)
254
255 #define ADDR_EXIT(cond, a)
256
257 #endif // DEBUG
258 ///////////////////////////////////////////////////////////////////////////////////////////////////
259
260 ///////////////////////////////////////////////////////////////////////////////////////////////////
261 // Misc helper functions
262 ////////////////////////////////////////////////////////////////////////////////////////////////////
263
264 /**
265 ***************************************************************************************************
266 * AddrXorReduce
267 *
268 * @brief
269 * Xor the right-side numberOfBits bits of x.
270 ***************************************************************************************************
271 */
272 static inline UINT_32 XorReduce(
273 UINT_32 x,
274 UINT_32 numberOfBits)
275 {
276 UINT_32 i;
277 UINT_32 result = x & 1;
278
279 for (i=1; i<numberOfBits; i++)
280 {
281 result ^= ((x>>i) & 1);
282 }
283
284 return result;
285 }
286
287 /**
288 ***************************************************************************************************
289 * IsPow2
290 *
291 * @brief
292 * Check if the size (UINT_32) is pow 2
293 ***************************************************************************************************
294 */
295 static inline UINT_32 IsPow2(
296 UINT_32 dim) ///< [in] dimension of miplevel
297 {
298 ADDR_ASSERT(dim > 0);
299 return !(dim & (dim - 1));
300 }
301
302 /**
303 ***************************************************************************************************
304 * IsPow2
305 *
306 * @brief
307 * Check if the size (UINT_64) is pow 2
308 ***************************************************************************************************
309 */
310 static inline UINT_64 IsPow2(
311 UINT_64 dim) ///< [in] dimension of miplevel
312 {
313 ADDR_ASSERT(dim > 0);
314 return !(dim & (dim - 1));
315 }
316
317 /**
318 ***************************************************************************************************
319 * ByteAlign
320 *
321 * @brief
322 * Align UINT_32 "x" to "align" alignment, "align" should be power of 2
323 ***************************************************************************************************
324 */
325 static inline UINT_32 PowTwoAlign(
326 UINT_32 x,
327 UINT_32 align)
328 {
329 //
330 // Assert that x is a power of two.
331 //
332 ADDR_ASSERT(IsPow2(align));
333 return (x + (align - 1)) & (~(align - 1));
334 }
335
336 /**
337 ***************************************************************************************************
338 * ByteAlign
339 *
340 * @brief
341 * Align UINT_64 "x" to "align" alignment, "align" should be power of 2
342 ***************************************************************************************************
343 */
344 static inline UINT_64 PowTwoAlign(
345 UINT_64 x,
346 UINT_64 align)
347 {
348 //
349 // Assert that x is a power of two.
350 //
351 ADDR_ASSERT(IsPow2(align));
352 return (x + (align - 1)) & (~(align - 1));
353 }
354
355 /**
356 ***************************************************************************************************
357 * Min
358 *
359 * @brief
360 * Get the min value between two unsigned values
361 ***************************************************************************************************
362 */
363 static inline UINT_32 Min(
364 UINT_32 value1,
365 UINT_32 value2)
366 {
367 return ((value1 < (value2)) ? (value1) : value2);
368 }
369
370 /**
371 ***************************************************************************************************
372 * Min
373 *
374 * @brief
375 * Get the min value between two signed values
376 ***************************************************************************************************
377 */
378 static inline INT_32 Min(
379 INT_32 value1,
380 INT_32 value2)
381 {
382 return ((value1 < (value2)) ? (value1) : value2);
383 }
384
385 /**
386 ***************************************************************************************************
387 * Max
388 *
389 * @brief
390 * Get the max value between two unsigned values
391 ***************************************************************************************************
392 */
393 static inline UINT_32 Max(
394 UINT_32 value1,
395 UINT_32 value2)
396 {
397 return ((value1 > (value2)) ? (value1) : value2);
398 }
399
400 /**
401 ***************************************************************************************************
402 * Max
403 *
404 * @brief
405 * Get the max value between two signed values
406 ***************************************************************************************************
407 */
408 static inline INT_32 Max(
409 INT_32 value1,
410 INT_32 value2)
411 {
412 return ((value1 > (value2)) ? (value1) : value2);
413 }
414
415 /**
416 ***************************************************************************************************
417 * NextPow2
418 *
419 * @brief
420 * Compute the mipmap's next level dim size
421 ***************************************************************************************************
422 */
423 static inline UINT_32 NextPow2(
424 UINT_32 dim) ///< [in] dimension of miplevel
425 {
426 UINT_32 newDim;
427
428 newDim = 1;
429
430 if (dim > 0x7fffffff)
431 {
432 ADDR_ASSERT_ALWAYS();
433 newDim = 0x80000000;
434 }
435 else
436 {
437 while (newDim < dim)
438 {
439 newDim <<= 1;
440 }
441 }
442
443 return newDim;
444 }
445
446 /**
447 ***************************************************************************************************
448 * Log2
449 *
450 * @brief
451 * Compute log of base 2
452 ***************************************************************************************************
453 */
454 static inline UINT_32 Log2(
455 UINT_32 x) ///< [in] the value should calculate log based 2
456 {
457 UINT_32 y;
458
459 //
460 // Assert that x is a power of two.
461 //
462 ADDR_ASSERT(IsPow2(x));
463
464 y = 0;
465 while (x > 1)
466 {
467 x >>= 1;
468 y++;
469 }
470
471 return y;
472 }
473
474 /**
475 ***************************************************************************************************
476 * QLog2
477 *
478 * @brief
479 * Compute log of base 2 quickly (<= 16)
480 ***************************************************************************************************
481 */
482 static inline UINT_32 QLog2(
483 UINT_32 x) ///< [in] the value should calculate log based 2
484 {
485 ADDR_ASSERT(x <= 16);
486
487 UINT_32 y = 0;
488
489 switch (x)
490 {
491 case 1:
492 y = 0;
493 break;
494 case 2:
495 y = 1;
496 break;
497 case 4:
498 y = 2;
499 break;
500 case 8:
501 y = 3;
502 break;
503 case 16:
504 y = 4;
505 break;
506 default:
507 ADDR_ASSERT_ALWAYS();
508 }
509
510 return y;
511 }
512
513 /**
514 ***************************************************************************************************
515 * SafeAssign
516 *
517 * @brief
518 * NULL pointer safe assignment
519 ***************************************************************************************************
520 */
521 static inline VOID SafeAssign(
522 UINT_32* pLVal, ///< [in] Pointer to left val
523 UINT_32 rVal) ///< [in] Right value
524 {
525 if (pLVal)
526 {
527 *pLVal = rVal;
528 }
529 }
530
531 /**
532 ***************************************************************************************************
533 * SafeAssign
534 *
535 * @brief
536 * NULL pointer safe assignment for 64bit values
537 ***************************************************************************************************
538 */
539 static inline VOID SafeAssign(
540 UINT_64* pLVal, ///< [in] Pointer to left val
541 UINT_64 rVal) ///< [in] Right value
542 {
543 if (pLVal)
544 {
545 *pLVal = rVal;
546 }
547 }
548
549 /**
550 ***************************************************************************************************
551 * SafeAssign
552 *
553 * @brief
554 * NULL pointer safe assignment for AddrTileMode
555 ***************************************************************************************************
556 */
557 static inline VOID SafeAssign(
558 AddrTileMode* pLVal, ///< [in] Pointer to left val
559 AddrTileMode rVal) ///< [in] Right value
560 {
561 if (pLVal)
562 {
563 *pLVal = rVal;
564 }
565 }
566
567 #endif // __ADDR_COMMON_H__
568