1#!/usr/bin/env python3
2
3import sys, io, re, json
4from canonicalize import json_canonicalize
5
6######### BEGIN HARDCODED CONFIGURATION
7
8gfx_levels = {
9    'gfx6': [
10        [],
11        'asic_reg/gca/gfx_6_0_d.h',
12        'asic_reg/gca/gfx_6_0_sh_mask.h',
13        'asic_reg/gca/gfx_7_2_enum.h' # the file for gfx6 doesn't exist
14    ],
15    'gfx7': [
16        [],
17        'asic_reg/gca/gfx_7_2_d.h',
18        'asic_reg/gca/gfx_7_2_sh_mask.h',
19        'asic_reg/gca/gfx_7_2_enum.h'
20    ],
21    'gfx8': [
22        [],
23        'asic_reg/gca/gfx_8_0_d.h',
24        'asic_reg/gca/gfx_8_0_sh_mask.h',
25        'asic_reg/gca/gfx_8_0_enum.h',
26    ],
27    'gfx81': [
28        [],
29        'asic_reg/gca/gfx_8_1_d.h',
30        'asic_reg/gca/gfx_8_1_sh_mask.h',
31        'asic_reg/gca/gfx_8_1_enum.h',
32    ],
33    'gfx9': [
34        [0x00002000, 0x0000A000, 0, 0, 0], # IP_BASE GC_BASE
35        'asic_reg/gc/gc_9_2_1_offset.h',
36        'asic_reg/gc/gc_9_2_1_sh_mask.h',
37        'vega10_enum.h',
38    ],
39    'gfx10': [
40        [0x00001260, 0x0000A000, 0x02402C00, 0, 0], # IP_BASE GC_BASE
41        'asic_reg/gc/gc_10_1_0_offset.h',
42        'asic_reg/gc/gc_10_1_0_sh_mask.h',
43        'navi10_enum.h',
44    ],
45    'gfx103': [
46        [0x00001260, 0x0000A000, 0x0001C000, 0x02402C00, 0], # IP_BASE GC_BASE
47        'asic_reg/gc/gc_10_3_0_offset.h',
48        'asic_reg/gc/gc_10_3_0_sh_mask.h',
49        'navi10_enum.h', # the file for gfx10.3 doesn't exist
50    ],
51    'gfx11': [
52        [0x00001260, 0x0000A000, 0x0001C000, 0x02402C00, 0, 0], # IP_BASE GC_BASE
53        'asic_reg/gc/gc_11_0_0_offset.h',
54        'asic_reg/gc/gc_11_0_0_sh_mask.h',
55        'soc21_enum.h',
56    ],
57}
58
59# match: #define mmSDMA0_DEC_START                              0x0000
60# match: #define ixSDMA0_DEC_START                              0x0000
61# match: #define regSDMA0_DEC_START                              0x0000
62re_offset = re.compile(r'^#define (?P<mm>(mm|ix|reg))(?P<name>\w+)\s+(?P<value>\w+)\n')
63
64# match: #define SDMA0_DEC_START__START__SHIFT                  0x0
65re_shift = re.compile(r'^#define (?P<name>\w+)__(?P<field>\w+)__SHIFT\s+(?P<value>\w+)\n')
66
67# match: #define SDMA0_DEC_START__START_MASK                    0xFFFFFFFFL
68# match: #define SDMA0_DEC_START__START_MASK                    0xFFFFFFFF
69re_mask = re.compile(r'^#define (?P<name>\w+)__(?P<field>\w+)_MASK\s+(?P<value>[0-9a-fA-Fx]+)L?\n')
70
71def register_filter(gfx_level, name, offset, already_added):
72    # Only accept writeable registers and debug registers
73    return ((offset // 0x1000 in [0xB, 0x28, 0x30, 0x31, 0x34, 0x35, 0x36, 0x37] or
74             # Add SQ_WAVE registers for trap handlers
75             name.startswith('SQ_WAVE_') or
76             # Add registers in the 0x8000 range used by all generations
77             (offset // 0x1000 == 0x8 and
78              (name.startswith('SQ_IMG_') or
79               name.startswith('SQ_BUF_') or
80               name.startswith('SQ_THREAD') or
81               name.startswith('GRBM_STATUS') or
82               name.startswith('CP_CP'))) or
83             # Add all registers in the 0x8000 range for gfx6
84             (gfx_level == 'gfx6' and offset // 0x1000 == 0x8) or
85             # Add registers in the 0x9000 range
86             (offset // 0x1000 == 0x9 and
87              (name in ['TA_CS_BC_BASE_ADDR', 'GB_ADDR_CONFIG', 'SPI_CONFIG_CNTL'] or
88               (name.startswith('GB') and 'TILE_MODE' in name)))) and
89            # Remove SQ compiler definitions
90            offset // 4 not in (0x23B0, 0x23B1, 0x237F) and
91            # Remove conflicts (multiple definitions for the same offset)
92            not already_added and
93            'PREF_PRI_ACCUM' not in name)
94
95# Mapping from field names to enum types
96enum_map = {
97    # Format:
98    #    field: [type1]                          - all registers use the same enum
99    # OR:
100    #    field: [type1, reg1, type2, reg2, ...]  - apply different enums to different registers
101    "ALPHA_COMB_FCN": ["CombFunc", "CB_BLEND0_CONTROL", "SX_OPT_COMB_FCN", "SX_MRT0_BLEND_OPT"],
102    "ALPHA_DESTBLEND": ["BlendOp"],
103    "ALPHA_DST_OPT": ["SX_BLEND_OPT"],
104    "ALPHA_SRCBLEND": ["BlendOp"],
105    "ALPHA_SRC_OPT": ["SX_BLEND_OPT"],
106    "ARRAY_MODE": ["ArrayMode"],
107    "BANK_HEIGHT": ["BankHeight"],
108    "BANK_WIDTH": ["BankWidth"],
109    "BC_SWIZZLE": ["SQ_IMG_RSRC_WORD4__BC_SWIZZLE"],
110    "BIN_MAPPING_MODE": ["BinMapMode"],
111    "BINNING_MODE": ["BinningMode"],
112    "BIN_SIZE_X_EXTEND": ["BinSizeExtend"],
113    "BIN_SIZE_Y_EXTEND": ["BinSizeExtend"],
114    "BLEND_OPT_DISCARD_PIXEL": ["BlendOpt"],
115    "BLEND_OPT_DONT_RD_DST": ["BlendOpt"],
116    "BORDER_COLOR_TYPE": ["SQ_TEX_BORDER_COLOR"],
117    "BUF_TYPE": ["VGT_DMA_BUF_TYPE"],
118    "CLAMP_X": ["SQ_TEX_CLAMP"],
119    "CLAMP_Y": ["SQ_TEX_CLAMP"],
120    "CLAMP_Z": ["SQ_TEX_CLAMP"],
121    "CLEAR_FILTER_SEL": ["CBPerfClearFilterSel"],
122    "CLIP_RULE": ["CLIP_RULE"],
123    "CMASK_ADDR_TYPE": ["CmaskAddr"],
124    "CMASK_RD_POLICY": ["ReadPolicy"],
125    "CMASK_WR_POLICY": ["WritePolicy"],
126    "COL0_EXPORT_FORMAT": ["SPI_SHADER_EX_FORMAT"],
127    "COL1_EXPORT_FORMAT": ["SPI_SHADER_EX_FORMAT"],
128    "COL2_EXPORT_FORMAT": ["SPI_SHADER_EX_FORMAT"],
129    "COL3_EXPORT_FORMAT": ["SPI_SHADER_EX_FORMAT"],
130    "COL4_EXPORT_FORMAT": ["SPI_SHADER_EX_FORMAT"],
131    "COL5_EXPORT_FORMAT": ["SPI_SHADER_EX_FORMAT"],
132    "COL6_EXPORT_FORMAT": ["SPI_SHADER_EX_FORMAT"],
133    "COL7_EXPORT_FORMAT": ["SPI_SHADER_EX_FORMAT"],
134    "COLOR_COMB_FCN": ["CombFunc", "CB_BLEND0_CONTROL", "SX_OPT_COMB_FCN", "SX_MRT0_BLEND_OPT"],
135    "COLOR_DESTBLEND": ["BlendOp"],
136    "COLOR_DST_OPT": ["SX_BLEND_OPT"],
137    "COLOR_RD_POLICY": ["ReadPolicy"],
138    "COLOR_SRCBLEND": ["BlendOp"],
139    "COLOR_SRC_OPT": ["SX_BLEND_OPT"],
140    "COLOR_WR_POLICY": ["WritePolicy"],
141    "COMPAREFUNC0": ["CompareFrag"],
142    "COMPAREFUNC1": ["CompareFrag"],
143    "COMP_SWAP": ["SurfaceSwap"],
144    "CONSERVATIVE_Z_EXPORT": ["ConservativeZExport"],
145    "COVERAGE_TO_SHADER_SELECT": ["CovToShaderSel"],
146    "CUT_MODE": ["VGT_GS_CUT_MODE"],
147    "DATA_FORMAT": ["BUF_DATA_FORMAT", "SQ_BUF_RSRC_WORD3", "IMG_DATA_FORMAT", "SQ_IMG_RSRC_WORD1"],
148    "DCC_RD_POLICY": ["ReadPolicy"],
149    "DCC_WR_POLICY": ["WritePolicy"],
150    "DEPTH_COMPARE_FUNC": ["SQ_TEX_DEPTH_COMPARE"],
151    "DETECT_ONE": ["VGT_DETECT_ONE"],
152    "DETECT_ZERO": ["VGT_DETECT_ZERO"],
153    "DISTRIBUTION_MODE": ["VGT_DIST_MODE"],
154    "DST_SEL_W": ["SQ_SEL_XYZW01"],
155    "DST_SEL_X": ["SQ_SEL_XYZW01"],
156    "DST_SEL_Y": ["SQ_SEL_XYZW01"],
157    "DST_SEL_Z": ["SQ_SEL_XYZW01"],
158    "ENDIAN": ["SurfaceEndian"],
159    "ES_EN": ["VGT_STAGES_ES_EN"],
160    "EVENT_TYPE": ["VGT_EVENT_TYPE"],
161    "EXCP": ["EXCP_EN"],
162    "EXCP_EN": ["EXCP_EN"],
163    "FAULT_BEHAVIOR": ["DbPRTFaultBehavior"],
164    "FILTER_MODE": ["SQ_IMG_FILTER_TYPE"],
165    "FLOAT_MODE": ["FLOAT_MODE"],
166    "FMASK_RD_POLICY": ["ReadPolicy"],
167    "FMASK_WR_POLICY": ["WritePolicy"],
168    "FORCE_FULL_Z_RANGE": ["ForceControl"],
169    "FORCE_HIS_ENABLE0": ["ForceControl"],
170    "FORCE_HIS_ENABLE1": ["ForceControl"],
171    "FORCE_HIZ_ENABLE": ["ForceControl"],
172    "FORCE_Z_LIMIT_SUMM": ["ZLimitSumm"],
173    "FORMAT": ["ColorFormat", "CB_COLOR0_INFO", "StencilFormat", "DB_STENCIL_INFO", "ZFormat", "DB_Z_INFO"],
174    "GS_EN": ["VGT_STAGES_GS_EN"],
175    "HIZ_ZFUNC": ["CompareFrag"],
176    "HS_EN": ["VGT_STAGES_HS_EN"],
177    "HTILE_RD_POLICY": ["ReadPolicy"],
178    "HTILE_WR_POLICY": ["WritePolicy"],
179    "IDX0_EXPORT_FORMAT": ["SPI_SHADER_FORMAT"],
180    "INDEX_TYPE": ["VGT_INDEX_TYPE_MODE"],
181    "LS_EN": ["VGT_STAGES_LS_EN"],
182    "MACRO_TILE_ASPECT": ["MacroTileAspect"],
183    "MAJOR_MODE": ["VGT_DI_MAJOR_MODE_SELECT"],
184    "MAX_UNCOMPRESSED_BLOCK_SIZE": ["CB_COLOR_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE"],
185    "MICRO_TILE_MODE": ["GB_TILE_MODE0__MICRO_TILE_MODE"],
186    "MICRO_TILE_MODE_NEW": ["MicroTileMode"],
187    "MIN_COMPRESSED_BLOCK_SIZE": ["CB_COLOR_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE"],
188    "MIP_FILTER": ["SQ_TEX_MIP_FILTER"],
189    "MODE": ["CBMode", "CB_COLOR_CONTROL", "VGT_GS_MODE_TYPE", "VGT_GS_MODE"],
190    "MRT0_EPSILON": ["SX_BLEND_OPT_EPSILON__MRT0_EPSILON"],
191    "MRT0": ["SX_DOWNCONVERT_FORMAT"],
192    "MRT1": ["SX_DOWNCONVERT_FORMAT"],
193    "MRT2": ["SX_DOWNCONVERT_FORMAT"],
194    "MRT3": ["SX_DOWNCONVERT_FORMAT"],
195    "MRT4": ["SX_DOWNCONVERT_FORMAT"],
196    "MRT5": ["SX_DOWNCONVERT_FORMAT"],
197    "MRT6": ["SX_DOWNCONVERT_FORMAT"],
198    "MRT7": ["SX_DOWNCONVERT_FORMAT"],
199    "NUM_BANKS": ["NumBanks"],
200    "NUM_FORMAT": ["BUF_NUM_FORMAT", "SQ_BUF_RSRC_WORD3", "IMG_NUM_FORMAT", "SQ_IMG_RSRC_WORD1"],
201    "NUMBER_TYPE": ["SurfaceNumber"],
202    "OFFCHIP_GRANULARITY": ["VGT_HS_OFFCHIP_PARAM__OFFCHIP_GRANULARITY"],
203    "OP_FILTER_SEL": ["CBPerfOpFilterSel"],
204    "OREO_MODE": ["OreoMode"],
205    "OUTPRIM_TYPE_1": ["VGT_GS_OUTPRIM_TYPE"],
206    "OUTPRIM_TYPE_2": ["VGT_GS_OUTPRIM_TYPE"],
207    "OUTPRIM_TYPE_3": ["VGT_GS_OUTPRIM_TYPE"],
208    "OUTPRIM_TYPE": ["VGT_GS_OUTPRIM_TYPE"],
209    "PARTIAL_SQUAD_LAUNCH_CONTROL": ["DbPSLControl"],
210    "PARTITIONING": ["VGT_TESS_PARTITION"],
211    "PERFMON_ENABLE_MODE": ["CP_PERFMON_ENABLE_MODE"],
212    "PERFMON_STATE": ["CP_PERFMON_STATE"],
213    "PIPE_CONFIG": ["PipeConfig"],
214    "PKR_MAP": ["PkrMap"],
215    "PKR_XSEL2": ["PkrXsel2"],
216    "PKR_XSEL": ["PkrXsel"],
217    "PKR_YSEL": ["PkrYsel"],
218    "PNT_SPRITE_OVRD_W": ["SPI_PNT_SPRITE_OVERRIDE"],
219    "PNT_SPRITE_OVRD_X": ["SPI_PNT_SPRITE_OVERRIDE"],
220    "PNT_SPRITE_OVRD_Y": ["SPI_PNT_SPRITE_OVERRIDE"],
221    "PNT_SPRITE_OVRD_Z": ["SPI_PNT_SPRITE_OVERRIDE"],
222    "POLYMODE_BACK_PTYPE": ["PA_SU_SC_MODE_CNTL__POLYMODE_FRONT_PTYPE"],
223    "POLYMODE_FRONT_PTYPE": ["PA_SU_SC_MODE_CNTL__POLYMODE_FRONT_PTYPE"],
224    "POLY_MODE": ["PA_SU_SC_MODE_CNTL__POLY_MODE"],
225    "POS0_EXPORT_FORMAT": ["SPI_SHADER_FORMAT"],
226    "POS1_EXPORT_FORMAT": ["SPI_SHADER_FORMAT"],
227    "POS2_EXPORT_FORMAT": ["SPI_SHADER_FORMAT"],
228    "POS3_EXPORT_FORMAT": ["SPI_SHADER_FORMAT"],
229    "POS4_EXPORT_FORMAT": ["SPI_SHADER_FORMAT"],
230    "PRIM_TYPE": ["VGT_DI_PRIM_TYPE"],
231    "PUNCHOUT_MODE": ["DB_DFSM_CONTROL__PUNCHOUT_MODE"],
232    "QUANT_MODE": ["QUANT_MODE"],
233    "RB_MAP_PKR0": ["RbMap"],
234    "RB_MAP_PKR1": ["RbMap"],
235    "RB_XSEL2": ["RbXsel2"],
236    "RB_XSEL": ["RbXsel"],
237    "RB_YSEL": ["RbYsel"],
238    "ROP3": ["ROP3"],
239    "RDREQ_POLICY": ["VGT_RDREQ_POLICY"],
240    "REG_INCLUDE": ["ThreadTraceRegInclude"],
241    "ROUND_MODE": ["PA_SU_VTX_CNTL__ROUND_MODE", "PA_SU_VTX_CNTL"],
242    "SC_MAP": ["ScMap"],
243    "SC_XSEL": ["ScXsel"],
244    "SC_YSEL": ["ScYsel"],
245    "SE_MAP": ["SeMap"],
246    "SE_PAIR_MAP": ["SePairMap"],
247    "SE_PAIR_XSEL": ["SePairXsel"],
248    "SE_PAIR_YSEL": ["SePairYsel"],
249    "SE_XSEL": ["SeXsel"],
250    "SE_YSEL": ["SeYsel"],
251    "SOURCE_SELECT": ["VGT_DI_SOURCE_SELECT"],
252    "SPM_PERFMON_STATE": ["SPM_PERFMON_STATE"],
253    "S_RD_POLICY": ["ReadPolicy"],
254    "STENCILFAIL_BF": ["StencilOp"],
255    "STENCILFAIL": ["StencilOp"],
256    "STENCILFUNC_BF": ["CompareFrag"],
257    "STENCILFUNC": ["CompareFrag"],
258    "STENCILZFAIL_BF": ["StencilOp"],
259    "STENCILZFAIL": ["StencilOp"],
260    "STENCILZPASS_BF": ["StencilOp"],
261    "STENCILZPASS": ["StencilOp"],
262    "SWAP_MODE": ["VGT_DMA_SWAP_MODE"],
263    "S_WR_POLICY": ["WritePolicy"],
264    "TILE_SPLIT": ["TileSplit"],
265    "TOKEN_EXCLUDE": ["ThreadTraceTokenExclude"],
266    "TOPOLOGY": ["VGT_TESS_TOPOLOGY"],
267    "TYPE": ["SQ_RSRC_BUF_TYPE", "SQ_BUF_RSRC_WORD3", "SQ_RSRC_IMG_TYPE", "SQ_IMG_RSRC_WORD3", "VGT_TESS_TYPE", "VGT_TF_PARAM"],
268    "UNCERTAINTY_REGION_MODE": ["ScUncertaintyRegionMode"],
269    "VRS_HTILE_ENCODING": ["VRSHtileEncoding"],
270    "VRS_RATE": ["VRSrate"],
271    "VS_EN": ["VGT_STAGES_VS_EN"],
272    "XY_MAG_FILTER": ["SQ_TEX_XY_FILTER"],
273    "XY_MIN_FILTER": ["SQ_TEX_XY_FILTER"],
274    "Z_EXPORT_FORMAT": ["SPI_SHADER_EX_FORMAT"],
275    "Z_FILTER": ["SQ_TEX_Z_FILTER"],
276    "ZFUNC": ["CompareFrag"],
277    "Z_ORDER": ["ZOrder"],
278    "ZPCPSD_WR_POLICY": ["WritePolicy"],
279    "Z_RD_POLICY": ["ReadPolicy"],
280    "Z_WR_POLICY": ["WritePolicy"],
281
282    "VERTEX_RATE_COMBINER_MODE": ["VRSCombinerModeSC"],
283    "PRIMITIVE_RATE_COMBINER_MODE": ["VRSCombinerModeSC"],
284    "HTILE_RATE_COMBINER_MODE": ["VRSCombinerModeSC"],
285    "SAMPLE_ITER_COMBINER_MODE": ["VRSCombinerModeSC"],
286    "VRS_OVERRIDE_RATE_COMBINER_MODE": ["VRSCombinerModeSC"],
287}
288
289# Enum definitions that are incomplete or missing in kernel headers
290DB_DFSM_CONTROL__PUNCHOUT_MODE = {
291 "entries": [
292  {"name": "AUTO", "value": 0},
293  {"name": "FORCE_ON", "value": 1},
294  {"name": "FORCE_OFF", "value": 2},
295  {"name": "RESERVED", "value": 3}
296 ]
297}
298
299ColorFormat = {
300 "entries": [
301  {"name": "COLOR_INVALID", "value": 0},
302  {"name": "COLOR_8", "value": 1},
303  {"name": "COLOR_16", "value": 2},
304  {"name": "COLOR_8_8", "value": 3},
305  {"name": "COLOR_32", "value": 4},
306  {"name": "COLOR_16_16", "value": 5},
307  {"name": "COLOR_10_11_11", "value": 6},
308  {"name": "COLOR_11_11_10", "value": 7},
309  {"name": "COLOR_10_10_10_2", "value": 8},
310  {"name": "COLOR_2_10_10_10", "value": 9},
311  {"name": "COLOR_8_8_8_8", "value": 10},
312  {"name": "COLOR_32_32", "value": 11},
313  {"name": "COLOR_16_16_16_16", "value": 12},
314  {"name": "COLOR_32_32_32_32", "value": 14},
315  {"name": "COLOR_5_6_5", "value": 16},
316  {"name": "COLOR_1_5_5_5", "value": 17},
317  {"name": "COLOR_5_5_5_1", "value": 18},
318  {"name": "COLOR_4_4_4_4", "value": 19},
319  {"name": "COLOR_8_24", "value": 20},
320  {"name": "COLOR_24_8", "value": 21},
321  {"name": "COLOR_X24_8_32_FLOAT", "value": 22},
322  {"name": "COLOR_5_9_9_9", "value": 24}
323 ]
324}
325
326SQ_IMG_RSRC_WORD4__BC_SWIZZLE = {
327 "entries": [
328  {"name": "BC_SWIZZLE_XYZW", "value": 0},
329  {"name": "BC_SWIZZLE_XWYZ", "value": 1},
330  {"name": "BC_SWIZZLE_WZYX", "value": 2},
331  {"name": "BC_SWIZZLE_WXYZ", "value": 3},
332  {"name": "BC_SWIZZLE_ZYXW", "value": 4},
333  {"name": "BC_SWIZZLE_YXWZ", "value": 5}
334 ]
335}
336
337SX_DOWNCONVERT_FORMAT = {
338 "entries": [
339  {"name": "SX_RT_EXPORT_NO_CONVERSION", "value": 0},
340  {"name": "SX_RT_EXPORT_32_R", "value": 1},
341  {"name": "SX_RT_EXPORT_32_A", "value": 2},
342  {"name": "SX_RT_EXPORT_10_11_11", "value": 3},
343  {"name": "SX_RT_EXPORT_2_10_10_10", "value": 4},
344  {"name": "SX_RT_EXPORT_8_8_8_8", "value": 5},
345  {"name": "SX_RT_EXPORT_5_6_5", "value": 6},
346  {"name": "SX_RT_EXPORT_1_5_5_5", "value": 7},
347  {"name": "SX_RT_EXPORT_4_4_4_4", "value": 8},
348  {"name": "SX_RT_EXPORT_16_16_GR", "value": 9},
349  {"name": "SX_RT_EXPORT_16_16_AR", "value": 10},
350  {"name": "SX_RT_EXPORT_9_9_9_E5", "value": 11}
351 ]
352}
353
354ThreadTraceRegInclude = {
355  "entries": [
356   {"name": "REG_INCLUDE_SQDEC", "value": 1},
357   {"name": "REG_INCLUDE_SHDEC", "value": 2},
358   {"name": "REG_INCLUDE_GFXUDEC", "value": 4},
359   {"name": "REG_INCLUDE_COMP", "value": 8},
360   {"name": "REG_INCLUDE_CONTEXT", "value": 16},
361   {"name": "REG_INCLUDE_CONFIG", "value": 32},
362   {"name": "REG_INCLUDE_OTHER", "value": 64},
363   {"name": "REG_INCLUDE_READS", "value": 128}
364  ]
365}
366
367ThreadTraceTokenExclude = {
368  "entries": [
369   {"name": "TOKEN_EXCLUDE_VMEMEXEC", "value": 1},
370   {"name": "TOKEN_EXCLUDE_ALUEXEC", "value": 2},
371   {"name": "TOKEN_EXCLUDE_VALUINST", "value": 4},
372   {"name": "TOKEN_EXCLUDE_WAVERDY", "value": 8},
373   {"name": "TOKEN_EXCLUDE_IMMED1", "value": 16},
374   {"name": "TOKEN_EXCLUDE_IMMEDIATE", "value": 32},
375   {"name": "TOKEN_EXCLUDE_REG", "value": 64},
376   {"name": "TOKEN_EXCLUDE_EVENT", "value": 128},
377   {"name": "TOKEN_EXCLUDE_INST", "value": 256},
378   {"name": "TOKEN_EXCLUDE_UTILCTR", "value": 512},
379   {"name": "TOKEN_EXCLUDE_WAVEALLOC", "value": 1024},
380   {"name": "TOKEN_EXCLUDE_PERF", "value": 2048}
381  ]
382}
383
384GB_TILE_MODE0__MICRO_TILE_MODE = {
385 "entries": [
386  {"name": "ADDR_SURF_DISPLAY_MICRO_TILING", "value": 0},
387  {"name": "ADDR_SURF_THIN_MICRO_TILING", "value": 1},
388  {"name": "ADDR_SURF_DEPTH_MICRO_TILING", "value": 2},
389  {"name": "ADDR_SURF_THICK_MICRO_TILING_GFX6", "value": 3}
390 ]
391}
392
393IMG_DATA_FORMAT_STENCIL = {
394 "entries": [
395  {"name": "IMG_DATA_FORMAT_S8_16", "value": 59},
396  {"name": "IMG_DATA_FORMAT_S8_32", "value": 60},
397 ]
398}
399
400VRSCombinerModeSC = {
401 "entries": [
402  {"name": "VRS_COMB_MODE_PASSTHRU", "value": 0},
403  {"name": "VRS_COMB_MODE_OVERRIDE", "value": 1},
404  {"name": "VRS_COMB_MODE_MIN", "value": 2},
405  {"name": "VRS_COMB_MODE_MAX", "value": 3},
406  {"name": "VRS_COMB_MODE_SATURATE", "value": 4},
407 ]
408}
409
410VRSHtileEncoding = {
411 "entries": [
412  {"name": "VRS_HTILE_DISABLE", "value": 0},
413  {"name": "VRS_HTILE_2BIT_ENCODING", "value": 1},
414  {"name": "VRS_HTILE_4BIT_ENCODING", "value": 2},
415 ]
416}
417
418missing_enums_all = {
419  'FLOAT_MODE': {
420    "entries": [
421      {"name": "FP_32_ROUND_TOWARDS_ZERO", "value": 3},
422      {"name": "FP_16_64_ROUND_TOWARDS_ZERO", "value": 12},
423      {"name": "FP_32_DENORMS", "value": 48},
424      {"name": "FP_16_64_DENORMS", "value": 192},
425    ]
426  },
427  'QUANT_MODE': {
428    "entries": [
429      {"name": "X_16_8_FIXED_POINT_1_16TH", "value": 0},
430      {"name": "X_16_8_FIXED_POINT_1_8TH", "value": 1},
431      {"name": "X_16_8_FIXED_POINT_1_4TH", "value": 2},
432      {"name": "X_16_8_FIXED_POINT_1_2", "value": 3},
433      {"name": "X_16_8_FIXED_POINT_1", "value": 4},
434      {"name": "X_16_8_FIXED_POINT_1_256TH", "value": 5},
435      {"name": "X_14_10_FIXED_POINT_1_1024TH", "value": 6},
436      {"name": "X_12_12_FIXED_POINT_1_4096TH", "value": 7}
437    ]
438  },
439  "CLIP_RULE": {
440   "entries": [
441    {"name": "OUT", "value": 1},
442    {"name": "IN_0", "value": 2},
443    {"name": "IN_1", "value": 4},
444    {"name": "IN_10", "value": 8},
445    {"name": "IN_2", "value": 16},
446    {"name": "IN_20", "value": 32},
447    {"name": "IN_21", "value": 64},
448    {"name": "IN_210", "value": 128},
449    {"name": "IN_3", "value": 256},
450    {"name": "IN_30", "value": 512},
451    {"name": "IN_31", "value": 1024},
452    {"name": "IN_310", "value": 2048},
453    {"name": "IN_32", "value": 4096},
454    {"name": "IN_320", "value": 8192},
455    {"name": "IN_321", "value": 16384},
456    {"name": "IN_3210", "value": 32768}
457   ]
458  },
459  'PA_SU_VTX_CNTL__ROUND_MODE': {
460    "entries": [
461      {"name": "X_TRUNCATE", "value": 0},
462      {"name": "X_ROUND", "value": 1},
463      {"name": "X_ROUND_TO_EVEN", "value": 2},
464      {"name": "X_ROUND_TO_ODD", "value": 3}
465    ]
466  },
467  "PA_SU_SC_MODE_CNTL__POLYMODE_FRONT_PTYPE": {
468   "entries": [
469    {"name": "X_DRAW_POINTS", "value": 0},
470    {"name": "X_DRAW_LINES", "value": 1},
471    {"name": "X_DRAW_TRIANGLES", "value": 2}
472   ]
473  },
474  "PA_SU_SC_MODE_CNTL__POLY_MODE": {
475   "entries": [
476    {"name": "X_DISABLE_POLY_MODE", "value": 0},
477    {"name": "X_DUAL_MODE", "value": 1}
478   ]
479  },
480  'VGT_HS_OFFCHIP_PARAM__OFFCHIP_GRANULARITY': {
481    "entries": [
482      {"name": "X_8K_DWORDS", "value": 0},
483      {"name": "X_4K_DWORDS", "value": 1},
484      {"name": "X_2K_DWORDS", "value": 2},
485      {"name": "X_1K_DWORDS", "value": 3}
486    ]
487  },
488  "ROP3": {
489   "entries": [
490    {"name": "ROP3_CLEAR", "value": 0},
491    {"name": "X_0X05", "value": 5},
492    {"name": "X_0X0A", "value": 10},
493    {"name": "X_0X0F", "value": 15},
494    {"name": "ROP3_NOR", "value": 17},
495    {"name": "ROP3_AND_INVERTED", "value": 34},
496    {"name": "ROP3_COPY_INVERTED", "value": 51},
497    {"name": "ROP3_AND_REVERSE", "value": 68},
498    {"name": "X_0X50", "value": 80},
499    {"name": "ROP3_INVERT", "value": 85},
500    {"name": "X_0X5A", "value": 90},
501    {"name": "X_0X5F", "value": 95},
502    {"name": "ROP3_XOR", "value": 102},
503    {"name": "ROP3_NAND", "value": 119},
504    {"name": "ROP3_AND", "value": 136},
505    {"name": "ROP3_EQUIVALENT", "value": 153},
506    {"name": "X_0XA0", "value": 160},
507    {"name": "X_0XA5", "value": 165},
508    {"name": "ROP3_NO_OP", "value": 170},
509    {"name": "X_0XAF", "value": 175},
510    {"name": "ROP3_OR_INVERTED", "value": 187},
511    {"name": "ROP3_COPY", "value": 204},
512    {"name": "ROP3_OR_REVERSE", "value": 221},
513    {"name": "ROP3_OR", "value": 238},
514    {"name": "X_0XF0", "value": 240},
515    {"name": "X_0XF5", "value": 245},
516    {"name": "X_0XFA", "value": 250},
517    {"name": "ROP3_SET", "value": 255}
518   ]
519  },
520  "EXCP_EN": {
521   "entries": [
522    {"name": "INVALID", "value": 1},
523    {"name": "INPUT_DENORMAL", "value": 2},
524    {"name": "DIVIDE_BY_ZERO", "value": 4},
525    {"name": "OVERFLOW", "value": 8},
526    {"name": "UNDERFLOW", "value": 16},
527    {"name": "INEXACT", "value": 32},
528    {"name": "INT_DIVIDE_BY_ZERO", "value": 64},
529    {"name": "ADDRESS_WATCH", "value": 128},
530    {"name": "MEMORY_VIOLATION", "value": 256}
531   ]
532  }
533}
534
535missing_enums_gfx8plus = {
536  **missing_enums_all,
537  'CB_COLOR_DCC_CONTROL__MAX_UNCOMPRESSED_BLOCK_SIZE': {
538    "entries": [
539      {"name": "MAX_BLOCK_SIZE_64B", "value": 0},
540      {"name": "MAX_BLOCK_SIZE_128B", "value": 1},
541      {"name": "MAX_BLOCK_SIZE_256B", "value": 2}
542    ]
543  },
544  'CB_COLOR_DCC_CONTROL__MIN_COMPRESSED_BLOCK_SIZE': {
545    "entries": [
546      {"name": "MIN_BLOCK_SIZE_32B", "value": 0},
547      {"name": "MIN_BLOCK_SIZE_64B", "value": 1}
548    ]
549  },
550}
551
552missing_enums_gfx81plus = {
553  **missing_enums_gfx8plus,
554  "SX_BLEND_OPT_EPSILON__MRT0_EPSILON": {
555    "entries": [
556      {"name": "EXACT", "value": 0},
557      {"name": "11BIT_FORMAT", "value": 1},
558      {"name": "10BIT_FORMAT", "value": 3},
559      {"name": "8BIT_FORMAT", "value": 6},
560      {"name": "6BIT_FORMAT", "value": 11},
561      {"name": "5BIT_FORMAT", "value": 13},
562      {"name": "4BIT_FORMAT", "value": 15}
563    ]
564  },
565}
566
567missing_enums_gfx103plus = {
568  **missing_enums_gfx81plus,
569  "ColorFormat": ColorFormat,
570  "ThreadTraceRegInclude": ThreadTraceRegInclude,
571  "ThreadTraceTokenExclude": ThreadTraceTokenExclude,
572}
573
574missing_enums_gfx11plus = {
575  **missing_enums_gfx103plus,
576  "ZFormat": {
577   "entries": [
578    {"name": "Z_INVALID", "value": 0},
579    {"name": "Z_16", "value": 1},
580    {"name": "Z_24", "value": 2},
581    {"name": "Z_32_FLOAT", "value": 3}
582   ]
583  },
584  "StencilFormat": {
585   "entries": [
586    {"name": "STENCIL_INVALID", "value": 0},
587    {"name": "STENCIL_8", "value": 1}
588   ]
589  },
590  "SurfaceNumber": {
591   "entries": [
592    {"name": "NUMBER_UNORM", "value": 0},
593    {"name": "NUMBER_SNORM", "value": 1},
594    {"name": "NUMBER_USCALED", "value": 2},
595    {"name": "NUMBER_SSCALED", "value": 3},
596    {"name": "NUMBER_UINT", "value": 4},
597    {"name": "NUMBER_SINT", "value": 5},
598    {"name": "NUMBER_SRGB", "value": 6},
599    {"name": "NUMBER_FLOAT", "value": 7}
600   ]
601  },
602  "SurfaceSwap": {
603   "entries": [
604    {"name": "SWAP_STD", "value": 0},
605    {"name": "SWAP_ALT", "value": 1},
606    {"name": "SWAP_STD_REV", "value": 2},
607    {"name": "SWAP_ALT_REV", "value": 3}
608   ]
609  },
610}
611
612enums_missing = {
613  'gfx6': {
614    **missing_enums_all,
615   "GB_TILE_MODE0__MICRO_TILE_MODE": GB_TILE_MODE0__MICRO_TILE_MODE,
616  },
617  'gfx7': {
618    **missing_enums_all,
619  },
620  'gfx8': {
621    **missing_enums_gfx8plus,
622  },
623  'gfx81': {
624    **missing_enums_gfx81plus,
625  },
626  'gfx9': {
627    **missing_enums_gfx81plus,
628    "DB_DFSM_CONTROL__PUNCHOUT_MODE": DB_DFSM_CONTROL__PUNCHOUT_MODE,
629    "IMG_DATA_FORMAT_STENCIL": IMG_DATA_FORMAT_STENCIL,
630    "SQ_IMG_RSRC_WORD4__BC_SWIZZLE": SQ_IMG_RSRC_WORD4__BC_SWIZZLE,
631  },
632  'gfx10': {
633    **missing_enums_gfx81plus,
634    "DB_DFSM_CONTROL__PUNCHOUT_MODE": DB_DFSM_CONTROL__PUNCHOUT_MODE,
635    "ThreadTraceRegInclude": ThreadTraceRegInclude,
636    "ThreadTraceTokenExclude": ThreadTraceTokenExclude,
637  },
638  'gfx103': {
639    **missing_enums_gfx103plus,
640    "SX_DOWNCONVERT_FORMAT": SX_DOWNCONVERT_FORMAT,
641    "DB_DFSM_CONTROL__PUNCHOUT_MODE": DB_DFSM_CONTROL__PUNCHOUT_MODE,
642    "VRSHtileEncoding": VRSHtileEncoding,
643    "VRSCombinerModeSC": VRSCombinerModeSC,
644  },
645  'gfx11': {
646    **missing_enums_gfx11plus,
647  },
648}
649
650# Register field definitions that are missing in kernel headers
651fields_missing = {
652  # Format:
653  #   Register: [[Field, StartBit, EndBit, EnumType(optional), ReplaceField=True/False(optional)], ...]
654  'gfx6': {
655    "COMPUTE_RESOURCE_LIMITS": [["WAVES_PER_SH_GFX6", 0, 5]],
656    "GB_TILE_MODE0": [["MICRO_TILE_MODE", 0, 1, "GB_TILE_MODE0__MICRO_TILE_MODE"]],
657    "SQ_IMG_SAMP_WORD3": [["UPGRADED_DEPTH", 29, 29]],
658    "SQ_THREAD_TRACE_MASK": [["RANDOM_SEED", 16, 31]],
659  },
660  'gfx7': {
661    "SQ_IMG_SAMP_WORD3": [["UPGRADED_DEPTH", 29, 29]],
662    "SQ_THREAD_TRACE_MASK": [["RANDOM_SEED", 16, 31]],
663  },
664  'gfx8': {
665    "SQ_IMG_SAMP_WORD3": [["UPGRADED_DEPTH", 29, 29]],
666    "SQ_THREAD_TRACE_MASK": [["RANDOM_SEED", 16, 31]],
667  },
668  'gfx81': {
669    "SQ_IMG_SAMP_WORD3": [["UPGRADED_DEPTH", 29, 29]],
670    "SQ_THREAD_TRACE_MASK": [["RANDOM_SEED", 16, 31]],
671  },
672  'gfx9': {
673    "SQ_IMG_RSRC_WORD1": [
674      ["DATA_FORMAT_STENCIL", 20, 25, "IMG_DATA_FORMAT_STENCIL"],
675      ["NUM_FORMAT_FMASK", 26, 29, "IMG_NUM_FORMAT_FMASK"]
676    ],
677  },
678  'gfx10': {
679    "DB_RESERVED_REG_2": [["RESOURCE_LEVEL", 28, 31, None, True]],
680  },
681  'gfx103': {
682    "DB_RESERVED_REG_2": [["RESOURCE_LEVEL", 28, 31, None, True]],
683    "VGT_DRAW_PAYLOAD_CNTL": [["EN_VRS_RATE", 6, 6]],
684    "VGT_SHADER_STAGES_EN": [["PRIMGEN_PASSTHRU_NO_MSG", 26, 26]],
685  },
686}
687
688######### END HARDCODED CONFIGURATION
689
690def bitcount(n):
691    return bin(n).count('1')
692
693def generate_json(gfx_level, amd_headers_path):
694    gc_base_offsets = gfx_levels[gfx_level][0]
695
696    # Add the path to the filenames
697    filenames = [amd_headers_path + '/' + a for a in gfx_levels[gfx_level][1:]]
698
699    # Open the files
700    files = [open(a, 'r').readlines() if a is not None else None for a in filenames]
701
702    # Parse the offset.h file
703    name = None
704    offset = None
705    added_offsets = set()
706    regs = {}
707    for line in files[0]:
708        r = re_offset.match(line)
709        if r is None:
710            continue
711
712        if '_BASE_IDX' not in r.group('name'):
713            name = r.group('name')
714            offset = int(r.group('value'), 0) * 4
715            if len(gc_base_offsets) > 0 and r.group('mm') == 'mm':
716                continue
717        else:
718            if name != r.group('name')[:-9]:
719                print('Warning: "{0}" not preceded by {1} but by {2}'.format(r.group('name'), r.group('name')[:-9], name))
720                continue
721            idx = int(r.group('value'))
722            assert idx < len(gc_base_offsets)
723            offset += gc_base_offsets[idx] * 4
724
725        # Remove the _UMD suffix because it was mistakenly added to indicate it's for a User-Mode Driver
726        if name[-4:] == '_UMD':
727            name = name[:-4]
728
729        # Only accept writeable registers and debug registers
730        if register_filter(gfx_level, name, offset, offset in added_offsets):
731            regs[name] = {
732                'chips': [gfx_level],
733                'map': {'at': offset, 'to': 'mm'},
734                'name': name,
735            }
736            added_offsets.add(offset)
737
738
739    # Parse the sh_mask.h file
740    shifts = {}
741    masks = {}
742    for line in files[1]:
743        r = re_shift.match(line)
744        is_shift = r is not None
745        r = re_mask.match(line) if r is None else r
746        if r is None:
747            continue
748
749        name = r.group('name')
750        if name not in regs.keys():
751            continue
752
753        field = r.group('field')
754        value = int(r.group('value'), 0)
755        assert not is_shift or value < 32
756
757        d = shifts if is_shift else masks
758        if name not in d:
759            d[name] = {}
760        d[name][field] = value
761
762
763    # Parse the enum.h file
764    re_enum_begin = re.compile(r'^typedef enum (?P<name>\w+) {\n')
765    re_enum_entry = re.compile(r'\s*(?P<name>\w+)\s*=\s*(?P<value>\w+),?\n')
766    re_enum_end = re.compile(r'^} \w+;\n')
767    inside_enum = False
768    name = None
769    enums = enums_missing[gfx_level] if gfx_level in enums_missing else {}
770
771    for line in files[2]:
772        r = re_enum_begin.match(line)
773        if r is not None:
774            name = r.group('name')
775            if name in enums:
776                continue
777            enums[name] = {'entries': []}
778            inside_enum = True
779            continue
780
781        r = re_enum_end.match(line)
782        if r is not None:
783            inside_enum = False
784            name = None
785            continue
786
787        if inside_enum:
788            r = re_enum_entry.match(line)
789            assert r
790            enums[name]['entries'].append({
791                'name': r.group('name'),
792                'value': int(r.group('value'), 0),
793            })
794
795
796    # Assemble everything
797    reg_types = {}
798    reg_mappings = []
799    missing_fields = fields_missing[gfx_level] if gfx_level in fields_missing else {}
800
801    for (name, reg) in regs.items():
802        type = {'fields': []}
803
804        if name in shifts and name in masks:
805            for (field, shift) in shifts[name].items():
806                if field not in masks[name]:
807                    continue
808
809                new = {
810                    'bits': [shift, shift + bitcount(masks[name][field]) - 1],
811                    'name': field,
812                }
813                if field in enum_map:
814                    type_map = enum_map[field]
815                    type_name = None
816
817                    if len(type_map) == 1:
818                        type_name = type_map[0];
819                    else:
820                        reg_index = type_map.index(name) if name in type_map else -1
821                        if reg_index >= 1 and reg_index % 2 == 1:
822                            type_name = type_map[reg_index - 1]
823
824                    if type_name is not None:
825                        if type_name not in enums:
826                            print('{0}: {1} type not found for {2}.{3}'
827                                  .format(gfx_level, type_name, name, field), file=sys.stderr)
828                        else:
829                            new['enum_ref'] = type_name
830
831                type['fields'].append(new)
832
833        if name in missing_fields:
834            fields = missing_fields[name]
835            for f in fields:
836                field = {
837                    'bits': [f[1], f[2]],
838                    'name': f[0],
839                }
840                if len(f) >= 4 and f[3] is not None and f[3] in enums:
841                    field['enum_ref'] = f[3]
842                # missing_fields should replace overlapping fields if requested
843                if len(f) >= 5 and f[4]:
844                    for f2 in type['fields']:
845                        if f2['bits'] == field['bits']:
846                            type['fields'].remove(f2)
847
848                type['fields'].append(field)
849
850        if len(type['fields']) > 0:
851            reg_types[name] = type
852
853            # Don't define types that have only one field covering all bits
854            field0_bits = type['fields'][0]['bits'];
855            if len(type['fields']) > 1 or field0_bits[0] != 0 or field0_bits[1] != 31:
856                reg['type_ref'] = name
857
858            reg_mappings.append(reg)
859
860
861    # Generate and canonicalize json
862    all = {
863        'enums': enums,
864        'register_mappings': reg_mappings,
865        'register_types': reg_types,
866    }
867
868    return json_canonicalize(io.StringIO(json.dumps(all, indent=1)))
869
870
871if __name__ == '__main__':
872    if len(sys.argv) <= 1 or (sys.argv[1] not in gfx_levels and sys.argv[1] != 'all'):
873        print('First parameter should be one of: all, ' + ', '.join(gfx_levels.keys()), file=sys.stderr)
874        sys.exit(1)
875
876    if len(sys.argv) <= 2:
877        print('Second parameter should be the path to the amd/include directory.', file=sys.stderr)
878        sys.exit(1)
879
880    if sys.argv[1] == 'all':
881        for gfx_level in gfx_levels.keys():
882            print(generate_json(gfx_level, sys.argv[2]), file=open(gfx_level + '.json', 'w'))
883        sys.exit(0)
884
885    print(generate_json(sys.argv[1], sys.argv[2]))
886