nouveau/headers: Generate Rust for QMDs

This also involves adding array support to the struct parser.
Fortunately, the header files for QMDs are really consistent here and we
can make lots of assumptions like that i is always the index variable.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28756>
This commit is contained in:
Faith Ekstrand 2024-04-10 14:40:36 -05:00 committed by Marge Bot
parent 20c1a69125
commit 64f02ac16d
2 changed files with 40 additions and 3 deletions

View file

@ -79,6 +79,17 @@ if with_nouveau_vk
depend_files: nvk_cl_header_depend_files,
)
fs = import('fs')
if cl.endswith('c0') and fs.is_file('nvidia/classes/'+cl+'qmd.h')
cl_rs_generated += custom_target(
'nvh_classes_' + cl + '_qmd.rs',
input : ['struct_parser.py', 'nvidia/classes/'+cl+'qmd.h'],
output : ['nvh_classes_'+cl+'_qmd.rs'],
command : [prog_python, '@INPUT0@', '--in-h', '@INPUT1@',
'--out-rs', '@OUTPUT0@']
)
endif
if cl.endswith('97')
cl_rs_generated += custom_target(
'nvh_classes_' + cl + '_tex.rs',

View file

@ -17,11 +17,20 @@ TEMPLATE_RS = Template("""\
// This file is generated by struct_parser.py. DO NOT EDIT!
#![allow(non_snake_case)]
use std::ops::Range;
% for s in structs:
% for f in s.fields:
% if f.stride:
#[inline]
pub fn ${s.name}_${f.name}(i: usize) -> Range<usize> {
(i * ${f.stride} + ${f.lo})..(i * ${f.stride} + ${f.hi + 1})
}
% else:
pub const ${s.name}_${f.name}: Range<usize> = ${f.lo}..${f.hi + 1};
% endif:
% for e in f.enums:
pub const ${s.name}_${f.name}_${e.name}: u32 = ${e.value};
% endfor
@ -38,15 +47,24 @@ STRUCTS = [
# This one goes last because it's a substring of the others
'TEXHEAD',
'TEXSAMP',
'QMDV00_06',
'QMDV01_06',
'QMDV01_07',
'QMDV02_01',
'QMDV02_02',
'QMDV02_03',
'QMDV02_04',
'QMDV03_00',
]
Enum = namedtuple('Enum', ['name', 'value'])
class Field(object):
def __init__(self, name, lo, hi):
def __init__(self, name, lo, hi, stride=0):
self.name = name
self.lo = lo
self.hi = hi
self.stride = stride
self.enums = []
def add_enum(self, name, value):
@ -57,12 +75,13 @@ class Struct(object):
self.name = name
self.fields = []
def add_field(self, name, lo, hi):
self.fields.append(Field(name, lo, hi))
def add_field(self, name, lo, hi, stride=0):
self.fields.append(Field(name, lo, hi, stride))
DRF_RE = re.compile(r'(?P<hi>[0-9]+):(?P<lo>[0-9]+)')
FIELD_NAME_RE = re.compile(r'_?(?P<dw>[0-9]+)?_?(?P<name>.*)')
MW_RE = re.compile(r'MW\((?P<hi>[0-9]+):(?P<lo>[0-9]+)\)')
MW_ARR_RE = re.compile(r'MW\(\((?P<hi>\d+)\+\(i\)\*(?P<stride>\d+)\):\((?P<lo>[0-9]+)\+\(i\)\*(?P=stride)\)\)')
def parse_header(nvcl, file):
structs = {}
@ -96,6 +115,7 @@ def parse_header(nvcl, file):
drf = DRF_RE.match(line[2])
mw = MW_RE.match(line[2])
mw_arr = MW_ARR_RE.match(line[2])
if drf:
dw = int(name_m.group('dw'))
lo = int(drf.group('lo')) + dw * 32
@ -105,6 +125,12 @@ def parse_header(nvcl, file):
lo = int(mw.group('lo'))
hi = int(mw.group('hi'))
struct.add_field(name, lo, hi)
elif mw_arr:
lo = int(mw_arr.group('lo'))
hi = int(mw_arr.group('hi'))
stride = int(mw_arr.group('stride'))
assert name.endswith('(i)')
struct.add_field(name.removesuffix('(i)'), lo, hi, stride)
else:
for f in struct.fields:
if name.startswith(f.name + '_'):