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