nouveau/headers: Autogenerate push method dumpers

Instead of typing this in nv_push.c, we now generate it based on the
class headers that are generated.

This makes it that we never have human errors in any of the checks and
allow to just support parsing everything we can.

Signed-off-by: Mary Guillemard <mary@mary.zone>
Reviewed-by: Mel Henning <mhenning@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37475>
This commit is contained in:
Mary Guillemard 2025-09-19 14:37:45 +02:00 committed by Marge Bot
parent be61c12f3e
commit 3a2b53f47f
3 changed files with 168 additions and 164 deletions

View file

@ -50,8 +50,11 @@ hwref_gens = [
'turing/tu102',
]
flat_nv_classes = ''
cl_generated = []
foreach cl : nv_classes
flat_nv_classes = flat_nv_classes + cl + ' '
cl_generated += custom_target(
cl + '.h',
input : ['class_parser.py', 'nvidia/classes/'+cl+'.h', 'util.py'],
@ -61,9 +64,16 @@ foreach cl : nv_classes
)
endforeach
nv_push_class_dump_h = custom_target(
'nv_push_class_dump.h',
input : ['nv_push_class_dump_h.py', 'nvidia/classes/'+cl+'.h', 'util.py'],
output : ['nv_push_class_dump.h'],
command : [prog_python, '@INPUT0@', '--classes', flat_nv_classes, '--out-h', '@OUTPUT0@'],
)
_libnvidia_headers = static_library(
'nvidia_headers_c',
['nv_push.c', cl_generated],
['nv_push.c', cl_generated, nv_push_class_dump_h],
include_directories : ['.', 'nvidia/classes', inc_include, inc_src],
c_args : [no_override_init_args],
gnu_symbol_visibility : 'hidden',

View file

@ -5,33 +5,7 @@
#include <inttypes.h>
#include "util/os_misc.h"
#include "nv_push_cl902d.h"
#include "nv_push_cl9039.h"
#include "nv_push_cl906f.h"
#include "nv_push_cl9097.h"
#include "nv_push_cl90b5.h"
#include "nv_push_cla097.h"
#include "nv_push_cla0b5.h"
#include "nv_push_cla040.h"
#include "nv_push_cla0c0.h"
#include "nv_push_cla140.h"
#include "nv_push_clb06f.h"
#include "nv_push_clb197.h"
#include "nv_push_clc0c0.h"
#include "nv_push_clc1b5.h"
#include "nv_push_clc397.h"
#include "nv_push_clc3c0.h"
#include "nv_push_clc56f.h"
#include "nv_push_clc597.h"
#include "nv_push_clc5b5.h"
#include "nv_push_clc5c0.h"
#include "nv_push_clc5b0.h"
#include "nv_push_clc697.h"
#include "nv_push_clc6b5.h"
#include "nv_push_clc6c0.h"
#include "nv_push_clc797.h"
#include "nv_push_clc7c0.h"
#include "nv_push_clcab5.h"
#include "nv_push_class_dump.h"
#ifndef NDEBUG
void
@ -84,8 +58,6 @@ vk_push_print(FILE *fp, const struct nv_push *push,
curr_subchans[3] = 0x2d;
curr_subchans[4] = devinfo->cls_copy;
const bool print_offsets = true;
while (cur < push->end) {
@ -174,143 +146,12 @@ vk_push_print(FILE *fp, const struct nv_push *push,
curr_subchans[subchan] = value & 0xffff;
}
int class_id = curr_subchans[subchan];
int cls_hi = (class_id & 0xff00) >> 8;
int cls_lo = class_id & 0xff;
if (!is_tert) {
if (mthd < 0x100) {
if (cls_hi >= 0xc5)
mthd_name = P_PARSE_NVC56F_MTHD(mthd);
else if (cls_hi >= 0xb0)
mthd_name = P_PARSE_NVB06F_MTHD(mthd);
else
mthd_name = P_PARSE_NV906F_MTHD(mthd);
} else {
switch (cls_lo) {
case 0x97:
if (cls_hi >= 0xc7)
mthd_name = P_PARSE_NVC797_MTHD(mthd);
else if (cls_hi >= 0xc6)
mthd_name = P_PARSE_NVC697_MTHD(mthd);
else if (cls_hi >= 0xc5)
mthd_name = P_PARSE_NVC597_MTHD(mthd);
else if (cls_hi >= 0xc3)
mthd_name = P_PARSE_NVC397_MTHD(mthd);
else if (cls_hi >= 0xb1)
mthd_name = P_PARSE_NVB197_MTHD(mthd);
else if (cls_hi >= 0xa0)
mthd_name = P_PARSE_NVA097_MTHD(mthd);
else
mthd_name = P_PARSE_NV9097_MTHD(mthd);
break;
case 0xc0:
if (cls_hi >= 0xc7)
mthd_name = P_PARSE_NVC7C0_MTHD(mthd);
else if (cls_hi >= 0xc6)
mthd_name = P_PARSE_NVC6C0_MTHD(mthd);
else if (cls_hi >= 0xc5)
mthd_name = P_PARSE_NVC5C0_MTHD(mthd);
else if (cls_hi >= 0xc3)
mthd_name = P_PARSE_NVC3C0_MTHD(mthd);
else if (cls_hi >= 0xc0)
mthd_name = P_PARSE_NVC0C0_MTHD(mthd);
else
mthd_name = P_PARSE_NVA0C0_MTHD(mthd);
break;
case 0x39:
case 0x40:
if (cls_hi >= 0xa1)
mthd_name = P_PARSE_NVA140_MTHD(mthd);
else if (cls_hi >= 0xa0)
mthd_name = P_PARSE_NVA040_MTHD(mthd);
else if (cls_hi >= 0x90)
mthd_name = P_PARSE_NV9039_MTHD(mthd);
break;
case 0x2d:
mthd_name = P_PARSE_NV902D_MTHD(mthd);
break;
case 0xb5:
if (cls_hi >= 0xca)
mthd_name = P_PARSE_NVCAB5_MTHD(mthd);
else if (cls_hi >= 0xc6)
mthd_name = P_PARSE_NVC6B5_MTHD(mthd);
else if (cls_hi >= 0xc5)
mthd_name = P_PARSE_NVC5B5_MTHD(mthd);
else if (cls_hi >= 0xc1)
mthd_name = P_PARSE_NVC1B5_MTHD(mthd);
else if (cls_hi >= 0xa0)
mthd_name = P_PARSE_NVA0B5_MTHD(mthd);
else
mthd_name = P_PARSE_NV90B5_MTHD(mthd);
break;
case 0xb0:
mthd_name = P_PARSE_NVC5B0_MTHD(mthd);
break;
default:
mthd_name = "unknown method";
break;
}
}
}
if (!is_tert)
mthd_name = P_PARSE_NV_MTHD(class_id, mthd);
fprintf(fp, "\tmthd %04x %s\n", mthd, mthd_name);
if (mthd < 0x100) {
if (cls_hi >= 0xb0)
P_DUMP_NVB06F_MTHD_DATA(fp, mthd, value, "\t\t");
else
P_DUMP_NV906F_MTHD_DATA(fp, mthd, value, "\t\t");
} else {
switch (cls_lo) {
case 0x97:
if (cls_hi >= 0xc5)
P_DUMP_NVC597_MTHD_DATA(fp, mthd, value, "\t\t");
else if (cls_hi >= 0xc3)
P_DUMP_NVC397_MTHD_DATA(fp, mthd, value, "\t\t");
else if (cls_hi >= 0xb1)
P_DUMP_NVB197_MTHD_DATA(fp, mthd, value, "\t\t");
else if (cls_hi >= 0xa0)
P_DUMP_NVA097_MTHD_DATA(fp, mthd, value, "\t\t");
else
P_DUMP_NV9097_MTHD_DATA(fp, mthd, value, "\t\t");
break;
case 0xc0:
if (cls_hi >= 0xc3)
P_DUMP_NVC3C0_MTHD_DATA(fp, mthd, value, "\t\t");
else if (cls_hi >= 0xc0)
P_DUMP_NVC0C0_MTHD_DATA(fp, mthd, value, "\t\t");
else
P_DUMP_NVA0C0_MTHD_DATA(fp, mthd, value, "\t\t");
break;
case 0x39:
case 0x40:
if (cls_hi >= 0xa1)
P_DUMP_NVA140_MTHD_DATA(fp, mthd, value, "\t\t");
else if (cls_hi >= 0xa0)
P_DUMP_NVA040_MTHD_DATA(fp, mthd, value, "\t\t");
else if (cls_hi >= 0x90)
P_DUMP_NV9039_MTHD_DATA(fp, mthd, value, "\t\t");
break;
case 0x2d:
P_DUMP_NV902D_MTHD_DATA(fp, mthd, value, "\t\t");
break;
case 0xb5:
if (cls_hi >= 0xca)
P_DUMP_NVCAB5_MTHD_DATA(fp, mthd, value, "\t\t");
else if (cls_hi >= 0xc1)
P_DUMP_NVC1B5_MTHD_DATA(fp, mthd, value, "\t\t");
else if (cls_hi >= 0xa0)
P_DUMP_NVA0B5_MTHD_DATA(fp, mthd, value, "\t\t");
else
P_DUMP_NV90B5_MTHD_DATA(fp, mthd, value, "\t\t");
break;
case 0xb0:
P_DUMP_NVC5B0_MTHD_DATA(fp, mthd, value, "\t\t");
break;
default:
fprintf(fp, "%s.VALUE = 0x%x\n", "\t\t", value);
break;
}
}
P_DUMP_NV_MTHD_DATA(fp, class_id, mthd, value, "\t\t");
if (!is_immd)
cur++;

View file

@ -0,0 +1,153 @@
#! /usr/bin/env python3
import argparse
from collections import defaultdict
from mako.template import Template
import util
TEMPLATE_H = Template(
"""\
#pragma once
%for (engine_id, classes) in classes_per_eng.items():
%for cl in classes:
#include "nv_push_cl${cl_for_filename(cl)}.h"
%endfor
%endfor
static inline const char*
P_PARSE_NV_MTHD(uint16_t class_id, uint16_t idx)
{
uint16_t cls_hi = (class_id & 0xff00) >> 8;
uint16_t cls_lo = class_id & 0xff;
if (idx < 0x100) {
%for cl_idx in range(0, len(classes_per_eng[0x6F])):
if (cls_hi >= ${hex(class_id_to_arch_id(classes_per_eng[0x6F][cl_idx]))})
return P_PARSE_${cl_for_function_name(classes_per_eng[0x6F][cl_idx])}_MTHD(idx);
else
%endfor
{
assert(false && "unknown class id");
}
} else {
switch (cls_lo) {
%for (engine_id, classes) in classes_per_eng.items():
case ${hex(engine_id)}:
%if len(classes) == 1:
return P_PARSE_${cl_for_function_name(classes[-1])}_MTHD(idx);
%else:
%for cl_idx in range(0, len(classes)):
if (cls_hi >= ${hex(class_id_to_arch_id(classes[cl_idx]))})
return P_PARSE_${cl_for_function_name(classes[cl_idx])}_MTHD(idx);
else
%endfor
{
assert(false && "unknown class id");
}
break;
%endif
%endfor
default:
break;
}
}
return "unknown method";
}
static inline void
P_DUMP_NV_MTHD_DATA(FILE *fp, uint16_t class_id, uint16_t idx, uint32_t data,
const char *prefix)
{
uint16_t cls_hi = (class_id & 0xff00) >> 8;
uint16_t cls_lo = class_id & 0xff;
if (idx < 0x100) {
%for cl_idx in range(0, len(classes_per_eng[0x6F])):
if (cls_hi >= ${hex(class_id_to_arch_id(classes_per_eng[0x6F][cl_idx]))})
P_DUMP_${cl_for_function_name(classes_per_eng[0x6F][cl_idx])}_MTHD_DATA(fp, idx, data, prefix);
else
%endfor
{
assert(false && "unknown class id");
}
} else {
switch (cls_lo) {
%for (engine_id, classes) in classes_per_eng.items():
case ${hex(engine_id)}:
%if len(classes) == 1:
P_DUMP_${cl_for_function_name(classes[-1])}_MTHD_DATA(fp, idx, data, prefix);
%else:
%for cl_idx in range(0, len(classes)):
if (cls_hi >= ${hex(class_id_to_arch_id(classes[cl_idx]))})
P_DUMP_${cl_for_function_name(classes[cl_idx])}_MTHD_DATA(fp, idx, data, prefix);
else
%endfor
{
assert(false && "unknown class id");
}
%endif
break;
%endfor
default:
fprintf(fp, "%s.VALUE = 0x%x\\n", prefix, data);
break;
}
}
}
"""
)
def cl_for_filename(class_id):
return f"{class_id:04x}"
def cl_for_function_name(class_id):
return f"NV{class_id:04X}"
def class_id_to_engine_id(class_id):
return class_id & 0xFF
def class_id_to_arch_id(class_id):
return (class_id & 0xFF00) >> 8
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--out-h", required=False, help="Output C header.")
parser.add_argument("--classes", help="Input class header file.", required=True)
args = parser.parse_args()
classes = args.classes.strip().split(" ")
classes_per_eng = defaultdict(list)
for cl in classes:
class_id = int(cl.removeprefix("cl"), 16)
engine_id = class_id_to_engine_id(class_id)
classes_per_eng[engine_id].append(class_id)
# Ensure everything is sorted in reverse order
for engine_id in classes_per_eng:
classes_per_eng[engine_id].sort(reverse=True)
environment = {
"classes_per_eng": classes_per_eng,
"cl_for_filename": cl_for_filename,
"cl_for_function_name": cl_for_function_name,
"class_id_to_arch_id": class_id_to_arch_id,
}
if args.out_h is not None:
util.write_template(args.out_h, TEMPLATE_H, environment)
if __name__ == "__main__":
main()