xref: /aosp_15_r20/external/mesa3d/src/nouveau/headers/struct_parser.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker#! /usr/bin/env python3
2*61046927SAndroid Build Coastguard Worker#
3*61046927SAndroid Build Coastguard Worker# Copyright © 2024 Collabora Ltd. and Red Hat Inc.
4*61046927SAndroid Build Coastguard Worker# SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker
6*61046927SAndroid Build Coastguard Workerimport argparse
7*61046927SAndroid Build Coastguard Workerimport os.path
8*61046927SAndroid Build Coastguard Workerimport re
9*61046927SAndroid Build Coastguard Workerimport sys
10*61046927SAndroid Build Coastguard Worker
11*61046927SAndroid Build Coastguard Workerfrom collections import namedtuple
12*61046927SAndroid Build Coastguard Workerfrom mako.template import Template
13*61046927SAndroid Build Coastguard Worker
14*61046927SAndroid Build Coastguard WorkerTEMPLATE_RS = Template("""\
15*61046927SAndroid Build Coastguard Worker// Copyright © 2024 Collabora Ltd. and Red Hat Inc.
16*61046927SAndroid Build Coastguard Worker// SPDX-License-Identifier: MIT
17*61046927SAndroid Build Coastguard Worker
18*61046927SAndroid Build Coastguard Worker// This file is generated by struct_parser.py. DO NOT EDIT!
19*61046927SAndroid Build Coastguard Worker
20*61046927SAndroid Build Coastguard Worker#![allow(non_snake_case)]
21*61046927SAndroid Build Coastguard Worker
22*61046927SAndroid Build Coastguard Workeruse std::ops::Range;
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker% for s in structs:
25*61046927SAndroid Build Coastguard Worker    % for f in s.fields:
26*61046927SAndroid Build Coastguard Worker        % if f.stride:
27*61046927SAndroid Build Coastguard Worker#[inline]
28*61046927SAndroid Build Coastguard Workerpub fn ${s.name}_${f.name}(i: usize) -> Range<usize> {
29*61046927SAndroid Build Coastguard Worker    (i * ${f.stride} + ${f.lo})..(i * ${f.stride} + ${f.hi + 1})
30*61046927SAndroid Build Coastguard Worker}
31*61046927SAndroid Build Coastguard Worker        % else:
32*61046927SAndroid Build Coastguard Workerpub const ${s.name}_${f.name}: Range<usize> = ${f.lo}..${f.hi + 1};
33*61046927SAndroid Build Coastguard Worker        % endif:
34*61046927SAndroid Build Coastguard Worker        % for e in f.enums:
35*61046927SAndroid Build Coastguard Workerpub const ${s.name}_${f.name}_${e.name}: u32 = ${e.value};
36*61046927SAndroid Build Coastguard Worker        % endfor
37*61046927SAndroid Build Coastguard Worker    % endfor
38*61046927SAndroid Build Coastguard Worker% endfor
39*61046927SAndroid Build Coastguard Worker""")
40*61046927SAndroid Build Coastguard Worker
41*61046927SAndroid Build Coastguard WorkerSTRUCTS = [
42*61046927SAndroid Build Coastguard Worker    'SPHV3',
43*61046927SAndroid Build Coastguard Worker    'SPHV4',
44*61046927SAndroid Build Coastguard Worker    'TEXHEADV2',
45*61046927SAndroid Build Coastguard Worker    'TEXHEADV3',
46*61046927SAndroid Build Coastguard Worker    'TEXHEAD_BL',
47*61046927SAndroid Build Coastguard Worker    'TEXHEAD_1D',
48*61046927SAndroid Build Coastguard Worker    'TEXHEAD_PITCH',
49*61046927SAndroid Build Coastguard Worker    # This one goes last because it's a substring of the others
50*61046927SAndroid Build Coastguard Worker    'TEXHEAD',
51*61046927SAndroid Build Coastguard Worker    'TEXSAMP',
52*61046927SAndroid Build Coastguard Worker    'QMDV00_06',
53*61046927SAndroid Build Coastguard Worker    'QMDV01_06',
54*61046927SAndroid Build Coastguard Worker    'QMDV01_07',
55*61046927SAndroid Build Coastguard Worker    'QMDV02_01',
56*61046927SAndroid Build Coastguard Worker    'QMDV02_02',
57*61046927SAndroid Build Coastguard Worker    'QMDV02_03',
58*61046927SAndroid Build Coastguard Worker    'QMDV02_04',
59*61046927SAndroid Build Coastguard Worker    'QMDV03_00',
60*61046927SAndroid Build Coastguard Worker]
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard WorkerEnum = namedtuple('Enum', ['name', 'value'])
63*61046927SAndroid Build Coastguard Worker
64*61046927SAndroid Build Coastguard Workerclass Field(object):
65*61046927SAndroid Build Coastguard Worker    def __init__(self, name, lo, hi, stride=0):
66*61046927SAndroid Build Coastguard Worker        self.name = name
67*61046927SAndroid Build Coastguard Worker        self.lo = lo
68*61046927SAndroid Build Coastguard Worker        self.hi = hi
69*61046927SAndroid Build Coastguard Worker        self.stride = stride
70*61046927SAndroid Build Coastguard Worker        self.enums = []
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker    def add_enum(self, name, value):
73*61046927SAndroid Build Coastguard Worker        self.enums.append(Enum(name, value))
74*61046927SAndroid Build Coastguard Worker
75*61046927SAndroid Build Coastguard Workerclass Struct(object):
76*61046927SAndroid Build Coastguard Worker    def __init__(self, name):
77*61046927SAndroid Build Coastguard Worker        self.name = name
78*61046927SAndroid Build Coastguard Worker        self.fields = []
79*61046927SAndroid Build Coastguard Worker
80*61046927SAndroid Build Coastguard Worker    def add_field(self, name, lo, hi, stride=0):
81*61046927SAndroid Build Coastguard Worker        self.fields.append(Field(name, lo, hi, stride))
82*61046927SAndroid Build Coastguard Worker
83*61046927SAndroid Build Coastguard WorkerDRF_RE = re.compile(r'(?P<hi>[0-9]+):(?P<lo>[0-9]+)')
84*61046927SAndroid Build Coastguard WorkerFIELD_NAME_RE = re.compile(r'_?(?P<dw>[0-9]+)?_?(?P<name>.*)')
85*61046927SAndroid Build Coastguard WorkerMW_RE = re.compile(r'MW\((?P<hi>[0-9]+):(?P<lo>[0-9]+)\)')
86*61046927SAndroid Build Coastguard WorkerMW_ARR_RE = re.compile(r'MW\(\((?P<hi>\d+)\+\(i\)\*(?P<stride>\d+)\):\((?P<lo>[0-9]+)\+\(i\)\*(?P=stride)\)\)')
87*61046927SAndroid Build Coastguard Worker
88*61046927SAndroid Build Coastguard Workerdef parse_header(nvcl, file):
89*61046927SAndroid Build Coastguard Worker    structs = {}
90*61046927SAndroid Build Coastguard Worker    for line in file:
91*61046927SAndroid Build Coastguard Worker        line = line.strip().split()
92*61046927SAndroid Build Coastguard Worker        if not line:
93*61046927SAndroid Build Coastguard Worker            continue
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker        if line[0] != '#define':
96*61046927SAndroid Build Coastguard Worker            continue
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker        if not line[1].startswith(nvcl):
99*61046927SAndroid Build Coastguard Worker            continue
100*61046927SAndroid Build Coastguard Worker
101*61046927SAndroid Build Coastguard Worker        name = line[1][(len(nvcl)+1):]
102*61046927SAndroid Build Coastguard Worker
103*61046927SAndroid Build Coastguard Worker        struct = None
104*61046927SAndroid Build Coastguard Worker        for s in STRUCTS:
105*61046927SAndroid Build Coastguard Worker            if name.startswith(s):
106*61046927SAndroid Build Coastguard Worker                if s not in structs:
107*61046927SAndroid Build Coastguard Worker                    structs[s] = Struct(s)
108*61046927SAndroid Build Coastguard Worker                struct = structs[s]
109*61046927SAndroid Build Coastguard Worker                name = name[len(s):]
110*61046927SAndroid Build Coastguard Worker                break
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker        if struct is None:
113*61046927SAndroid Build Coastguard Worker            continue
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker        name_m = FIELD_NAME_RE.match(name)
116*61046927SAndroid Build Coastguard Worker        name = name_m.group('name')
117*61046927SAndroid Build Coastguard Worker
118*61046927SAndroid Build Coastguard Worker        drf = DRF_RE.match(line[2])
119*61046927SAndroid Build Coastguard Worker        mw = MW_RE.match(line[2])
120*61046927SAndroid Build Coastguard Worker        mw_arr = MW_ARR_RE.match(line[2])
121*61046927SAndroid Build Coastguard Worker        if drf:
122*61046927SAndroid Build Coastguard Worker            dw = int(name_m.group('dw'))
123*61046927SAndroid Build Coastguard Worker            lo = int(drf.group('lo')) + dw * 32
124*61046927SAndroid Build Coastguard Worker            hi = int(drf.group('hi')) + dw * 32
125*61046927SAndroid Build Coastguard Worker            struct.add_field(name, lo, hi)
126*61046927SAndroid Build Coastguard Worker        elif mw:
127*61046927SAndroid Build Coastguard Worker            lo = int(mw.group('lo'))
128*61046927SAndroid Build Coastguard Worker            hi = int(mw.group('hi'))
129*61046927SAndroid Build Coastguard Worker            struct.add_field(name, lo, hi)
130*61046927SAndroid Build Coastguard Worker        elif mw_arr:
131*61046927SAndroid Build Coastguard Worker            lo = int(mw_arr.group('lo'))
132*61046927SAndroid Build Coastguard Worker            hi = int(mw_arr.group('hi'))
133*61046927SAndroid Build Coastguard Worker            stride = int(mw_arr.group('stride'))
134*61046927SAndroid Build Coastguard Worker            assert name.endswith('(i)')
135*61046927SAndroid Build Coastguard Worker            struct.add_field(name.removesuffix('(i)'), lo, hi, stride)
136*61046927SAndroid Build Coastguard Worker        else:
137*61046927SAndroid Build Coastguard Worker            for f in struct.fields:
138*61046927SAndroid Build Coastguard Worker                if name.startswith(f.name + '_'):
139*61046927SAndroid Build Coastguard Worker                    name = name[(len(f.name)+1):]
140*61046927SAndroid Build Coastguard Worker                    f.add_enum(name, line[2])
141*61046927SAndroid Build Coastguard Worker
142*61046927SAndroid Build Coastguard Worker    return list(structs.values())
143*61046927SAndroid Build Coastguard Worker
144*61046927SAndroid Build Coastguard WorkerNVCL_RE = re.compile(r'cl(?P<clsver>[0-9a-f]{4}).*')
145*61046927SAndroid Build Coastguard Worker
146*61046927SAndroid Build Coastguard Workerdef main():
147*61046927SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser()
148*61046927SAndroid Build Coastguard Worker    parser.add_argument('--out-rs', required=True, help='Output Rust file.')
149*61046927SAndroid Build Coastguard Worker    parser.add_argument('--in-h',
150*61046927SAndroid Build Coastguard Worker                        help='Input class header file.',
151*61046927SAndroid Build Coastguard Worker                        required=True)
152*61046927SAndroid Build Coastguard Worker    args = parser.parse_args()
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker    clheader = os.path.basename(args.in_h)
155*61046927SAndroid Build Coastguard Worker    nvcl = NVCL_RE.match(clheader).group('clsver')
156*61046927SAndroid Build Coastguard Worker    nvcl = nvcl.upper()
157*61046927SAndroid Build Coastguard Worker    nvcl = "NV" + nvcl
158*61046927SAndroid Build Coastguard Worker
159*61046927SAndroid Build Coastguard Worker    with open(args.in_h, 'r', encoding='utf-8') as f:
160*61046927SAndroid Build Coastguard Worker        structs = parse_header(nvcl, f)
161*61046927SAndroid Build Coastguard Worker
162*61046927SAndroid Build Coastguard Worker    try:
163*61046927SAndroid Build Coastguard Worker        with open(args.out_rs, 'w', encoding='utf-8') as f:
164*61046927SAndroid Build Coastguard Worker            f.write(TEMPLATE_RS.render(structs=structs))
165*61046927SAndroid Build Coastguard Worker
166*61046927SAndroid Build Coastguard Worker    except Exception:
167*61046927SAndroid Build Coastguard Worker        # In the event there's an error, this imports some helpers from mako
168*61046927SAndroid Build Coastguard Worker        # to print a useful stack trace and prints it, then exits with
169*61046927SAndroid Build Coastguard Worker        # status 1, if python is run with debug; otherwise it just raises
170*61046927SAndroid Build Coastguard Worker        # the exception
171*61046927SAndroid Build Coastguard Worker        import sys
172*61046927SAndroid Build Coastguard Worker        from mako import exceptions
173*61046927SAndroid Build Coastguard Worker        print(exceptions.text_error_template().render(), file=sys.stderr)
174*61046927SAndroid Build Coastguard Worker        sys.exit(1)
175*61046927SAndroid Build Coastguard Worker
176*61046927SAndroid Build Coastguard Workerif __name__ == '__main__':
177*61046927SAndroid Build Coastguard Worker    main()
178