1*61046927SAndroid Build Coastguard Worker#! /usr/bin/env python3 2*61046927SAndroid Build Coastguard Worker 3*61046927SAndroid Build Coastguard Worker# script to parse nvidia CL headers and generate inlines to be used in pushbuffer encoding. 4*61046927SAndroid Build Coastguard Worker# probably needs python3.9 5*61046927SAndroid Build Coastguard Worker 6*61046927SAndroid Build Coastguard Workerimport argparse 7*61046927SAndroid Build Coastguard Workerimport os.path 8*61046927SAndroid Build Coastguard Workerimport sys 9*61046927SAndroid Build Coastguard Workerimport re 10*61046927SAndroid Build Coastguard Workerimport subprocess 11*61046927SAndroid Build Coastguard Worker 12*61046927SAndroid Build Coastguard Workerfrom mako.template import Template 13*61046927SAndroid Build Coastguard Worker 14*61046927SAndroid Build Coastguard WorkerMETHOD_ARRAY_SIZES = { 15*61046927SAndroid Build Coastguard Worker 'BIND_GROUP_CONSTANT_BUFFER' : 16, 16*61046927SAndroid Build Coastguard Worker 'CALL_MME_DATA' : 256, 17*61046927SAndroid Build Coastguard Worker 'CALL_MME_MACRO' : 256, 18*61046927SAndroid Build Coastguard Worker 'LOAD_CONSTANT_BUFFER' : 16, 19*61046927SAndroid Build Coastguard Worker 'LOAD_INLINE_QMD_DATA' : 64, 20*61046927SAndroid Build Coastguard Worker 'SET_ANTI_ALIAS_SAMPLE_POSITIONS' : 4, 21*61046927SAndroid Build Coastguard Worker 'SET_BLEND' : 8, 22*61046927SAndroid Build Coastguard Worker 'SET_BLEND_PER_TARGET_*' : 8, 23*61046927SAndroid Build Coastguard Worker 'SET_COLOR_TARGET_*' : 8, 24*61046927SAndroid Build Coastguard Worker 'SET_COLOR_COMPRESSION' : 8, 25*61046927SAndroid Build Coastguard Worker 'SET_COLOR_CLEAR_VALUE' : 4, 26*61046927SAndroid Build Coastguard Worker 'SET_CT_WRITE' : 8, 27*61046927SAndroid Build Coastguard Worker 'SET_MME_SHADOW_SCRATCH' : 256, 28*61046927SAndroid Build Coastguard Worker 'SET_PIPELINE_*' : 6, 29*61046927SAndroid Build Coastguard Worker 'SET_SCG_COMPUTE_SCHEDULING_PARAMETERS' : 16, 30*61046927SAndroid Build Coastguard Worker 'SET_SCISSOR_*' : 16, 31*61046927SAndroid Build Coastguard Worker 'SET_SHADER_PERFORMANCE_SNAPSHOT_COUNTER_VALUE*' : 8, 32*61046927SAndroid Build Coastguard Worker 'SET_SHADER_PERFORMANCE_COUNTER_VALUE*' : 8, 33*61046927SAndroid Build Coastguard Worker 'SET_SHADER_PERFORMANCE_COUNTER_EVENT' : 8, 34*61046927SAndroid Build Coastguard Worker 'SET_SHADER_PERFORMANCE_COUNTER_CONTROL_A' : 8, 35*61046927SAndroid Build Coastguard Worker 'SET_SHADER_PERFORMANCE_COUNTER_CONTROL_B' : 8, 36*61046927SAndroid Build Coastguard Worker 'SET_STREAM_OUT_BUFFER_*' : 4, 37*61046927SAndroid Build Coastguard Worker 'SET_STREAM_OUT_CONTROL_*' : 4, 38*61046927SAndroid Build Coastguard Worker 'SET_VIEWPORT_*' : 16, 39*61046927SAndroid Build Coastguard Worker 'SET_VERTEX_ATTRIBUTE_*' : 16, 40*61046927SAndroid Build Coastguard Worker 'SET_VERTEX_STREAM_*' : 16, 41*61046927SAndroid Build Coastguard Worker} 42*61046927SAndroid Build Coastguard Worker 43*61046927SAndroid Build Coastguard WorkerMETHOD_IS_FLOAT = [ 44*61046927SAndroid Build Coastguard Worker 'SET_BLEND_CONST_*', 45*61046927SAndroid Build Coastguard Worker 'SET_DEPTH_BIAS', 46*61046927SAndroid Build Coastguard Worker 'SET_SLOPE_SCALE_DEPTH_BIAS', 47*61046927SAndroid Build Coastguard Worker 'SET_DEPTH_BIAS_CLAMP', 48*61046927SAndroid Build Coastguard Worker 'SET_DEPTH_BOUNDS_M*', 49*61046927SAndroid Build Coastguard Worker 'SET_LINE_WIDTH_FLOAT', 50*61046927SAndroid Build Coastguard Worker 'SET_ALIASED_LINE_WIDTH_FLOAT', 51*61046927SAndroid Build Coastguard Worker 'SET_VIEWPORT_SCALE_*', 52*61046927SAndroid Build Coastguard Worker 'SET_VIEWPORT_OFFSET_*', 53*61046927SAndroid Build Coastguard Worker 'SET_VIEWPORT_CLIP_MIN_Z', 54*61046927SAndroid Build Coastguard Worker 'SET_VIEWPORT_CLIP_MAX_Z', 55*61046927SAndroid Build Coastguard Worker 'SET_Z_CLEAR_VALUE', 56*61046927SAndroid Build Coastguard Worker] 57*61046927SAndroid Build Coastguard Worker 58*61046927SAndroid Build Coastguard WorkerTEMPLATE_H = Template("""\ 59*61046927SAndroid Build Coastguard Worker/* parsed class ${nvcl} */ 60*61046927SAndroid Build Coastguard Worker 61*61046927SAndroid Build Coastguard Worker#include "nvtypes.h" 62*61046927SAndroid Build Coastguard Worker#include "${clheader}" 63*61046927SAndroid Build Coastguard Worker 64*61046927SAndroid Build Coastguard Worker#include <assert.h> 65*61046927SAndroid Build Coastguard Worker#include <stdio.h> 66*61046927SAndroid Build Coastguard Worker#include "util/u_math.h" 67*61046927SAndroid Build Coastguard Worker 68*61046927SAndroid Build Coastguard Worker%for mthd in mthddict: 69*61046927SAndroid Build Coastguard Workerstruct nv_${nvcl.lower()}_${mthd} { 70*61046927SAndroid Build Coastguard Worker %for field_name in mthddict[mthd].field_name_start: 71*61046927SAndroid Build Coastguard Worker uint32_t ${field_name.lower()}; 72*61046927SAndroid Build Coastguard Worker %endfor 73*61046927SAndroid Build Coastguard Worker}; 74*61046927SAndroid Build Coastguard Worker 75*61046927SAndroid Build Coastguard Workerstatic inline void 76*61046927SAndroid Build Coastguard Worker__${nvcl}_${mthd}(uint32_t *val_out, struct nv_${nvcl.lower()}_${mthd} st) 77*61046927SAndroid Build Coastguard Worker{ 78*61046927SAndroid Build Coastguard Worker uint32_t val = 0; 79*61046927SAndroid Build Coastguard Worker %for field_name in mthddict[mthd].field_name_start: 80*61046927SAndroid Build Coastguard Worker <% 81*61046927SAndroid Build Coastguard Worker field_start = int(mthddict[mthd].field_name_start[field_name]) 82*61046927SAndroid Build Coastguard Worker field_end = int(mthddict[mthd].field_name_end[field_name]) 83*61046927SAndroid Build Coastguard Worker field_width = field_end - field_start + 1 84*61046927SAndroid Build Coastguard Worker %> 85*61046927SAndroid Build Coastguard Worker %if field_width == 32: 86*61046927SAndroid Build Coastguard Worker val |= st.${field_name.lower()}; 87*61046927SAndroid Build Coastguard Worker %else: 88*61046927SAndroid Build Coastguard Worker assert(st.${field_name.lower()} < (1ULL << ${field_width})); 89*61046927SAndroid Build Coastguard Worker val |= st.${field_name.lower()} << ${field_start}; 90*61046927SAndroid Build Coastguard Worker %endif 91*61046927SAndroid Build Coastguard Worker %endfor 92*61046927SAndroid Build Coastguard Worker *val_out = val; 93*61046927SAndroid Build Coastguard Worker} 94*61046927SAndroid Build Coastguard Worker 95*61046927SAndroid Build Coastguard Worker#define V_${nvcl}_${mthd}(val, args...) { ${bs} 96*61046927SAndroid Build Coastguard Worker %for field_name in mthddict[mthd].field_name_start: 97*61046927SAndroid Build Coastguard Worker %for d in mthddict[mthd].field_defs[field_name]: 98*61046927SAndroid Build Coastguard Worker UNUSED uint32_t ${field_name}_${d} = ${nvcl}_${mthd}_${field_name}_${d}; ${bs} 99*61046927SAndroid Build Coastguard Worker %endfor 100*61046927SAndroid Build Coastguard Worker %endfor 101*61046927SAndroid Build Coastguard Worker %if len(mthddict[mthd].field_name_start) > 1: 102*61046927SAndroid Build Coastguard Worker struct nv_${nvcl.lower()}_${mthd} __data = args; ${bs} 103*61046927SAndroid Build Coastguard Worker %else: 104*61046927SAndroid Build Coastguard Worker<% field_name = next(iter(mthddict[mthd].field_name_start)).lower() %>\ 105*61046927SAndroid Build Coastguard Worker struct nv_${nvcl.lower()}_${mthd} __data = { .${field_name} = (args) }; ${bs} 106*61046927SAndroid Build Coastguard Worker %endif 107*61046927SAndroid Build Coastguard Worker __${nvcl}_${mthd}(&val, __data); ${bs} 108*61046927SAndroid Build Coastguard Worker} 109*61046927SAndroid Build Coastguard Worker 110*61046927SAndroid Build Coastguard Worker%if mthddict[mthd].is_array: 111*61046927SAndroid Build Coastguard Worker#define VA_${nvcl}_${mthd}(i) V_${nvcl}_${mthd} 112*61046927SAndroid Build Coastguard Worker%else: 113*61046927SAndroid Build Coastguard Worker#define VA_${nvcl}_${mthd} V_${nvcl}_${mthd} 114*61046927SAndroid Build Coastguard Worker%endif 115*61046927SAndroid Build Coastguard Worker 116*61046927SAndroid Build Coastguard Worker%if mthddict[mthd].is_array: 117*61046927SAndroid Build Coastguard Worker#define P_${nvcl}_${mthd}(push, idx, args...) do { ${bs} 118*61046927SAndroid Build Coastguard Worker%else: 119*61046927SAndroid Build Coastguard Worker#define P_${nvcl}_${mthd}(push, args...) do { ${bs} 120*61046927SAndroid Build Coastguard Worker%endif 121*61046927SAndroid Build Coastguard Worker %for field_name in mthddict[mthd].field_name_start: 122*61046927SAndroid Build Coastguard Worker %for d in mthddict[mthd].field_defs[field_name]: 123*61046927SAndroid Build Coastguard Worker UNUSED uint32_t ${field_name}_${d} = ${nvcl}_${mthd}_${field_name}_${d}; ${bs} 124*61046927SAndroid Build Coastguard Worker %endfor 125*61046927SAndroid Build Coastguard Worker %endfor 126*61046927SAndroid Build Coastguard Worker uint32_t nvk_p_ret; ${bs} 127*61046927SAndroid Build Coastguard Worker V_${nvcl}_${mthd}(nvk_p_ret, args); ${bs} 128*61046927SAndroid Build Coastguard Worker %if mthddict[mthd].is_array: 129*61046927SAndroid Build Coastguard Worker nv_push_val(push, ${nvcl}_${mthd}(idx), nvk_p_ret); ${bs} 130*61046927SAndroid Build Coastguard Worker %else: 131*61046927SAndroid Build Coastguard Worker nv_push_val(push, ${nvcl}_${mthd}, nvk_p_ret); ${bs} 132*61046927SAndroid Build Coastguard Worker %endif 133*61046927SAndroid Build Coastguard Worker} while(0) 134*61046927SAndroid Build Coastguard Worker 135*61046927SAndroid Build Coastguard Worker%endfor 136*61046927SAndroid Build Coastguard Worker 137*61046927SAndroid Build Coastguard Workerconst char *P_PARSE_${nvcl}_MTHD(uint16_t idx); 138*61046927SAndroid Build Coastguard Workervoid P_DUMP_${nvcl}_MTHD_DATA(FILE *fp, uint16_t idx, uint32_t data, 139*61046927SAndroid Build Coastguard Worker const char *prefix); 140*61046927SAndroid Build Coastguard Worker""") 141*61046927SAndroid Build Coastguard Worker 142*61046927SAndroid Build Coastguard WorkerTEMPLATE_C = Template("""\ 143*61046927SAndroid Build Coastguard Worker#include "${header}" 144*61046927SAndroid Build Coastguard Worker 145*61046927SAndroid Build Coastguard Worker#include <stdio.h> 146*61046927SAndroid Build Coastguard Worker 147*61046927SAndroid Build Coastguard Workerconst char* 148*61046927SAndroid Build Coastguard WorkerP_PARSE_${nvcl}_MTHD(uint16_t idx) 149*61046927SAndroid Build Coastguard Worker{ 150*61046927SAndroid Build Coastguard Worker switch (idx) { 151*61046927SAndroid Build Coastguard Worker%for mthd in mthddict: 152*61046927SAndroid Build Coastguard Worker %if mthddict[mthd].is_array and mthddict[mthd].array_size == 0: 153*61046927SAndroid Build Coastguard Worker <% continue %> 154*61046927SAndroid Build Coastguard Worker %endif 155*61046927SAndroid Build Coastguard Worker %if mthddict[mthd].is_array: 156*61046927SAndroid Build Coastguard Worker %for i in range(mthddict[mthd].array_size): 157*61046927SAndroid Build Coastguard Worker case ${nvcl}_${mthd}(${i}): 158*61046927SAndroid Build Coastguard Worker return "${nvcl}_${mthd}(${i})"; 159*61046927SAndroid Build Coastguard Worker %endfor 160*61046927SAndroid Build Coastguard Worker % else: 161*61046927SAndroid Build Coastguard Worker case ${nvcl}_${mthd}: 162*61046927SAndroid Build Coastguard Worker return "${nvcl}_${mthd}"; 163*61046927SAndroid Build Coastguard Worker %endif 164*61046927SAndroid Build Coastguard Worker%endfor 165*61046927SAndroid Build Coastguard Worker default: 166*61046927SAndroid Build Coastguard Worker return "unknown method"; 167*61046927SAndroid Build Coastguard Worker } 168*61046927SAndroid Build Coastguard Worker} 169*61046927SAndroid Build Coastguard Worker 170*61046927SAndroid Build Coastguard Workervoid 171*61046927SAndroid Build Coastguard WorkerP_DUMP_${nvcl}_MTHD_DATA(FILE *fp, uint16_t idx, uint32_t data, 172*61046927SAndroid Build Coastguard Worker const char *prefix) 173*61046927SAndroid Build Coastguard Worker{ 174*61046927SAndroid Build Coastguard Worker uint32_t parsed; 175*61046927SAndroid Build Coastguard Worker switch (idx) { 176*61046927SAndroid Build Coastguard Worker%for mthd in mthddict: 177*61046927SAndroid Build Coastguard Worker %if mthddict[mthd].is_array and mthddict[mthd].array_size == 0: 178*61046927SAndroid Build Coastguard Worker <% continue %> 179*61046927SAndroid Build Coastguard Worker %endif 180*61046927SAndroid Build Coastguard Worker %if mthddict[mthd].is_array: 181*61046927SAndroid Build Coastguard Worker %for i in range(mthddict[mthd].array_size): 182*61046927SAndroid Build Coastguard Worker case ${nvcl}_${mthd}(${i}): 183*61046927SAndroid Build Coastguard Worker %endfor 184*61046927SAndroid Build Coastguard Worker % else: 185*61046927SAndroid Build Coastguard Worker case ${nvcl}_${mthd}: 186*61046927SAndroid Build Coastguard Worker %endif 187*61046927SAndroid Build Coastguard Worker %for field_name in mthddict[mthd].field_name_start: 188*61046927SAndroid Build Coastguard Worker <% 189*61046927SAndroid Build Coastguard Worker field_start = int(mthddict[mthd].field_name_start[field_name]) 190*61046927SAndroid Build Coastguard Worker field_end = int(mthddict[mthd].field_name_end[field_name]) 191*61046927SAndroid Build Coastguard Worker field_width = field_end - field_start + 1 192*61046927SAndroid Build Coastguard Worker %> 193*61046927SAndroid Build Coastguard Worker %if field_width == 32: 194*61046927SAndroid Build Coastguard Worker parsed = data; 195*61046927SAndroid Build Coastguard Worker %else: 196*61046927SAndroid Build Coastguard Worker parsed = (data >> ${field_start}) & ((1u << ${field_width}) - 1); 197*61046927SAndroid Build Coastguard Worker %endif 198*61046927SAndroid Build Coastguard Worker fprintf(fp, "%s.${field_name} = ", prefix); 199*61046927SAndroid Build Coastguard Worker %if len(mthddict[mthd].field_defs[field_name]): 200*61046927SAndroid Build Coastguard Worker switch (parsed) { 201*61046927SAndroid Build Coastguard Worker %for d in mthddict[mthd].field_defs[field_name]: 202*61046927SAndroid Build Coastguard Worker case ${nvcl}_${mthd}_${field_name}_${d}: 203*61046927SAndroid Build Coastguard Worker fprintf(fp, "${d}${bs}n"); 204*61046927SAndroid Build Coastguard Worker break; 205*61046927SAndroid Build Coastguard Worker %endfor 206*61046927SAndroid Build Coastguard Worker default: 207*61046927SAndroid Build Coastguard Worker fprintf(fp, "0x%x${bs}n", parsed); 208*61046927SAndroid Build Coastguard Worker break; 209*61046927SAndroid Build Coastguard Worker } 210*61046927SAndroid Build Coastguard Worker %else: 211*61046927SAndroid Build Coastguard Worker %if mthddict[mthd].is_float: 212*61046927SAndroid Build Coastguard Worker fprintf(fp, "%ff (0x%x)${bs}n", uif(parsed), parsed); 213*61046927SAndroid Build Coastguard Worker %else: 214*61046927SAndroid Build Coastguard Worker fprintf(fp, "(0x%x)${bs}n", parsed); 215*61046927SAndroid Build Coastguard Worker %endif 216*61046927SAndroid Build Coastguard Worker %endif 217*61046927SAndroid Build Coastguard Worker %endfor 218*61046927SAndroid Build Coastguard Worker break; 219*61046927SAndroid Build Coastguard Worker%endfor 220*61046927SAndroid Build Coastguard Worker default: 221*61046927SAndroid Build Coastguard Worker fprintf(fp, "%s.VALUE = 0x%x${bs}n", prefix, data); 222*61046927SAndroid Build Coastguard Worker break; 223*61046927SAndroid Build Coastguard Worker } 224*61046927SAndroid Build Coastguard Worker} 225*61046927SAndroid Build Coastguard Worker""") 226*61046927SAndroid Build Coastguard Worker 227*61046927SAndroid Build Coastguard WorkerTEMPLATE_RS = Template("""\ 228*61046927SAndroid Build Coastguard Worker// parsed class ${nvcl} 229*61046927SAndroid Build Coastguard Worker 230*61046927SAndroid Build Coastguard Worker% if version is not None: 231*61046927SAndroid Build Coastguard Workerpub const ${version[0]}: u16 = ${version[1]}; 232*61046927SAndroid Build Coastguard Worker% endif 233*61046927SAndroid Build Coastguard Worker""") 234*61046927SAndroid Build Coastguard Worker 235*61046927SAndroid Build Coastguard WorkerTEMPLATE_RS_MTHD = Template("""\ 236*61046927SAndroid Build Coastguard Worker 237*61046927SAndroid Build Coastguard Worker// parsed class ${nvcl} 238*61046927SAndroid Build Coastguard Worker 239*61046927SAndroid Build Coastguard Worker## Write out the methods in Rust 240*61046927SAndroid Build Coastguard Worker%for mthd_name, mthd in mthddict.items(): 241*61046927SAndroid Build Coastguard Worker## Identify the field type. 242*61046927SAndroid Build Coastguard Worker<% 243*61046927SAndroid Build Coastguard Workerfor field_name, field_value in mthd.field_defs.items(): 244*61046927SAndroid Build Coastguard Worker if field_name == 'V' and len(field_value) > 0: 245*61046927SAndroid Build Coastguard Worker mthd.field_rs_types[field_name] = to_camel(mthd_name) + 'V' 246*61046927SAndroid Build Coastguard Worker mthd.field_is_rs_enum[field_name] = True 247*61046927SAndroid Build Coastguard Worker elif len(field_value) > 0: 248*61046927SAndroid Build Coastguard Worker assert(field_name != "") 249*61046927SAndroid Build Coastguard Worker mthd.field_rs_types[field_name] = to_camel(mthd_name) + to_camel(field_name) 250*61046927SAndroid Build Coastguard Worker mthd.field_is_rs_enum[field_name] = True 251*61046927SAndroid Build Coastguard Worker elif mthd.is_float: 252*61046927SAndroid Build Coastguard Worker mthd.field_rs_types[field_name] = "f32" 253*61046927SAndroid Build Coastguard Worker mthd.field_is_rs_enum[field_name] = False 254*61046927SAndroid Build Coastguard Worker else: 255*61046927SAndroid Build Coastguard Worker mthd.field_rs_types[field_name] = "u32" 256*61046927SAndroid Build Coastguard Worker mthd.field_is_rs_enum[field_name] = False 257*61046927SAndroid Build Coastguard Worker 258*61046927SAndroid Build Coastguard Worker # TRUE and FALSE are special cases. 259*61046927SAndroid Build Coastguard Worker if len(field_value) == 2: 260*61046927SAndroid Build Coastguard Worker for enumerant in field_value: 261*61046927SAndroid Build Coastguard Worker if enumerant.lower() == 'true' or enumerant.lower() == 'false': 262*61046927SAndroid Build Coastguard Worker mthd.field_rs_types[field_name] = "bool" 263*61046927SAndroid Build Coastguard Worker mthd.field_is_rs_enum[field_name] = False 264*61046927SAndroid Build Coastguard Worker break 265*61046927SAndroid Build Coastguard Worker%> 266*61046927SAndroid Build Coastguard Worker 267*61046927SAndroid Build Coastguard Worker## If there are a range of values for a field, we define an enum. 268*61046927SAndroid Build Coastguard Worker%for field_name in mthd.field_defs: 269*61046927SAndroid Build Coastguard Worker %if mthd.field_is_rs_enum[field_name]: 270*61046927SAndroid Build Coastguard Worker#[repr(u16)] 271*61046927SAndroid Build Coastguard Worker#[derive(Copy, Clone, Debug, PartialEq)] 272*61046927SAndroid Build Coastguard Workerpub enum ${mthd.field_rs_types[field_name]} { 273*61046927SAndroid Build Coastguard Worker %for field_name, field_value in mthd.field_defs[field_name].items(): 274*61046927SAndroid Build Coastguard Worker ${to_camel(rs_field_name(field_name))} = ${field_value.lower()}, 275*61046927SAndroid Build Coastguard Worker %endfor 276*61046927SAndroid Build Coastguard Worker} 277*61046927SAndroid Build Coastguard Worker %endif 278*61046927SAndroid Build Coastguard Worker%endfor 279*61046927SAndroid Build Coastguard Worker 280*61046927SAndroid Build Coastguard Worker## We also define a struct with the fields for the mthd. 281*61046927SAndroid Build Coastguard Worker#[derive(Copy, Clone, Debug, PartialEq)] 282*61046927SAndroid Build Coastguard Workerpub struct ${to_camel(mthd_name)} { 283*61046927SAndroid Build Coastguard Worker %for field_name in mthddict[mthd_name].field_name_start: 284*61046927SAndroid Build Coastguard Worker pub ${rs_field_name(field_name.lower())}: ${mthd.field_rs_types[field_name]}, 285*61046927SAndroid Build Coastguard Worker %endfor 286*61046927SAndroid Build Coastguard Worker} 287*61046927SAndroid Build Coastguard Worker 288*61046927SAndroid Build Coastguard Worker## Notice that the "to_bits" implementation is identical, so the first brace is 289*61046927SAndroid Build Coastguard Worker## not closed. 290*61046927SAndroid Build Coastguard Worker% if not mthd.is_array: 291*61046927SAndroid Build Coastguard Worker## This trait lays out how the conversion to u32 happens 292*61046927SAndroid Build Coastguard Workerimpl Mthd for ${to_camel(mthd_name)} { 293*61046927SAndroid Build Coastguard Worker const ADDR: u16 = ${mthd.addr.replace('(', '').replace(')', '')}; 294*61046927SAndroid Build Coastguard Worker const CLASS: u16 = ${version[1].lower() if version is not None else nvcl.lower().replace("nv", "0x")}; 295*61046927SAndroid Build Coastguard Worker 296*61046927SAndroid Build Coastguard Worker%else: 297*61046927SAndroid Build Coastguard Workerimpl ArrayMthd for ${to_camel(mthd_name)} { 298*61046927SAndroid Build Coastguard Worker const CLASS: u16 = ${version[1].lower() if version is not None else nvcl.lower().replace("nv", "0x")}; 299*61046927SAndroid Build Coastguard Worker 300*61046927SAndroid Build Coastguard Worker fn addr(i: usize) -> u16 { 301*61046927SAndroid Build Coastguard Worker <% assert not ('i' in mthd.addr and 'j' in mthd.addr) %> 302*61046927SAndroid Build Coastguard Worker (${mthd.addr.replace('j', 'i').replace('(', '').replace(')', '')}).try_into().unwrap() 303*61046927SAndroid Build Coastguard Worker } 304*61046927SAndroid Build Coastguard Worker%endif 305*61046927SAndroid Build Coastguard Worker 306*61046927SAndroid Build Coastguard Worker #[inline] 307*61046927SAndroid Build Coastguard Worker fn to_bits(self) -> u32 { 308*61046927SAndroid Build Coastguard Worker let mut val = 0; 309*61046927SAndroid Build Coastguard Worker %for field_name in mthddict[mthd_name].field_name_start: 310*61046927SAndroid Build Coastguard Worker <% 311*61046927SAndroid Build Coastguard Worker field_start = int(mthd.field_name_start[field_name]) 312*61046927SAndroid Build Coastguard Worker field_end = int(mthd.field_name_end[field_name]) 313*61046927SAndroid Build Coastguard Worker field_width = field_end - field_start + 1 314*61046927SAndroid Build Coastguard Worker field = rs_field_name(field_name.lower()) if mthd.field_rs_types[field_name] == "u32" else f"{rs_field_name(field_name)} as u32" 315*61046927SAndroid Build Coastguard Worker %> 316*61046927SAndroid Build Coastguard Worker %if field_width == 32: 317*61046927SAndroid Build Coastguard Worker val |= self.${field}; 318*61046927SAndroid Build Coastguard Worker %else: 319*61046927SAndroid Build Coastguard Worker %if "as u32" in field: 320*61046927SAndroid Build Coastguard Worker assert!((self.${field}) < (1 << ${field_width})); 321*61046927SAndroid Build Coastguard Worker val |= (self.${field}) << ${field_start}; 322*61046927SAndroid Build Coastguard Worker %else: 323*61046927SAndroid Build Coastguard Worker assert!(self.${field} < (1 << ${field_width})); 324*61046927SAndroid Build Coastguard Worker val |= self.${field} << ${field_start}; 325*61046927SAndroid Build Coastguard Worker %endif 326*61046927SAndroid Build Coastguard Worker %endif 327*61046927SAndroid Build Coastguard Worker %endfor 328*61046927SAndroid Build Coastguard Worker 329*61046927SAndroid Build Coastguard Worker val 330*61046927SAndroid Build Coastguard Worker } 331*61046927SAndroid Build Coastguard Worker## Close the first brace. 332*61046927SAndroid Build Coastguard Worker} 333*61046927SAndroid Build Coastguard Worker%endfor 334*61046927SAndroid Build Coastguard Worker""") 335*61046927SAndroid Build Coastguard Worker 336*61046927SAndroid Build Coastguard Worker## A mere convenience to convert snake_case to CamelCase. Numbers are prefixed 337*61046927SAndroid Build Coastguard Worker## with "_". 338*61046927SAndroid Build Coastguard Workerdef to_camel(snake_str): 339*61046927SAndroid Build Coastguard Worker result = ''.join(word.title() for word in snake_str.split('_')) 340*61046927SAndroid Build Coastguard Worker return result if not result[0].isdigit() else '_' + result 341*61046927SAndroid Build Coastguard Worker 342*61046927SAndroid Build Coastguard Workerdef rs_field_name(name): 343*61046927SAndroid Build Coastguard Worker name = name.lower() 344*61046927SAndroid Build Coastguard Worker 345*61046927SAndroid Build Coastguard Worker # Fix up some Rust keywords 346*61046927SAndroid Build Coastguard Worker if name == 'type': 347*61046927SAndroid Build Coastguard Worker return 'type_' 348*61046927SAndroid Build Coastguard Worker elif name == 'override': 349*61046927SAndroid Build Coastguard Worker return 'override_' 350*61046927SAndroid Build Coastguard Worker elif name[0].isdigit(): 351*61046927SAndroid Build Coastguard Worker return '_' + name 352*61046927SAndroid Build Coastguard Worker else: 353*61046927SAndroid Build Coastguard Worker return name 354*61046927SAndroid Build Coastguard Worker 355*61046927SAndroid Build Coastguard Workerdef glob_match(glob, name): 356*61046927SAndroid Build Coastguard Worker if glob.endswith('*'): 357*61046927SAndroid Build Coastguard Worker return name.startswith(glob[:-1]) 358*61046927SAndroid Build Coastguard Worker else: 359*61046927SAndroid Build Coastguard Worker assert '*' not in glob 360*61046927SAndroid Build Coastguard Worker return name == glob 361*61046927SAndroid Build Coastguard Worker 362*61046927SAndroid Build Coastguard Workerclass method(object): 363*61046927SAndroid Build Coastguard Worker @property 364*61046927SAndroid Build Coastguard Worker def array_size(self): 365*61046927SAndroid Build Coastguard Worker for (glob, value) in METHOD_ARRAY_SIZES.items(): 366*61046927SAndroid Build Coastguard Worker if glob_match(glob, self.name): 367*61046927SAndroid Build Coastguard Worker return value 368*61046927SAndroid Build Coastguard Worker return 0 369*61046927SAndroid Build Coastguard Worker 370*61046927SAndroid Build Coastguard Worker @property 371*61046927SAndroid Build Coastguard Worker def is_float(self): 372*61046927SAndroid Build Coastguard Worker for glob in METHOD_IS_FLOAT: 373*61046927SAndroid Build Coastguard Worker if glob_match(glob, self.name): 374*61046927SAndroid Build Coastguard Worker assert len(self.field_defs) == 1 375*61046927SAndroid Build Coastguard Worker return True 376*61046927SAndroid Build Coastguard Worker return False 377*61046927SAndroid Build Coastguard Worker 378*61046927SAndroid Build Coastguard Workerdef parse_header(nvcl, f): 379*61046927SAndroid Build Coastguard Worker # Simple state machine 380*61046927SAndroid Build Coastguard Worker # state 0 looking for a new method define 381*61046927SAndroid Build Coastguard Worker # state 1 looking for new fields in a method 382*61046927SAndroid Build Coastguard Worker # state 2 looking for enums for a fields in a method 383*61046927SAndroid Build Coastguard Worker # blank lines reset the state machine to 0 384*61046927SAndroid Build Coastguard Worker 385*61046927SAndroid Build Coastguard Worker version = None 386*61046927SAndroid Build Coastguard Worker state = 0 387*61046927SAndroid Build Coastguard Worker mthddict = {} 388*61046927SAndroid Build Coastguard Worker curmthd = {} 389*61046927SAndroid Build Coastguard Worker for line in f: 390*61046927SAndroid Build Coastguard Worker 391*61046927SAndroid Build Coastguard Worker if line.strip() == "": 392*61046927SAndroid Build Coastguard Worker state = 0 393*61046927SAndroid Build Coastguard Worker if (curmthd): 394*61046927SAndroid Build Coastguard Worker if not len(curmthd.field_name_start): 395*61046927SAndroid Build Coastguard Worker del mthddict[curmthd.name] 396*61046927SAndroid Build Coastguard Worker curmthd = {} 397*61046927SAndroid Build Coastguard Worker continue 398*61046927SAndroid Build Coastguard Worker 399*61046927SAndroid Build Coastguard Worker if line.startswith("#define"): 400*61046927SAndroid Build Coastguard Worker list = line.split(); 401*61046927SAndroid Build Coastguard Worker if "_cl_" in list[1]: 402*61046927SAndroid Build Coastguard Worker continue 403*61046927SAndroid Build Coastguard Worker 404*61046927SAndroid Build Coastguard Worker if not list[1].startswith(nvcl): 405*61046927SAndroid Build Coastguard Worker if len(list) > 2 and list[2].startswith("0x"): 406*61046927SAndroid Build Coastguard Worker assert version is None 407*61046927SAndroid Build Coastguard Worker version = (list[1], list[2]) 408*61046927SAndroid Build Coastguard Worker continue 409*61046927SAndroid Build Coastguard Worker 410*61046927SAndroid Build Coastguard Worker if list[1].endswith("TYPEDEF"): 411*61046927SAndroid Build Coastguard Worker continue 412*61046927SAndroid Build Coastguard Worker 413*61046927SAndroid Build Coastguard Worker if state == 2: 414*61046927SAndroid Build Coastguard Worker teststr = nvcl + "_" + curmthd.name + "_" + curfield + "_" 415*61046927SAndroid Build Coastguard Worker if ":" in list[2]: 416*61046927SAndroid Build Coastguard Worker state = 1 417*61046927SAndroid Build Coastguard Worker elif teststr in list[1]: 418*61046927SAndroid Build Coastguard Worker curmthd.field_defs[curfield][list[1].removeprefix(teststr)] = list[2] 419*61046927SAndroid Build Coastguard Worker else: 420*61046927SAndroid Build Coastguard Worker state = 1 421*61046927SAndroid Build Coastguard Worker 422*61046927SAndroid Build Coastguard Worker if state == 1: 423*61046927SAndroid Build Coastguard Worker teststr = nvcl + "_" + curmthd.name + "_" 424*61046927SAndroid Build Coastguard Worker if teststr in list[1]: 425*61046927SAndroid Build Coastguard Worker if ("0x" in list[2]): 426*61046927SAndroid Build Coastguard Worker state = 1 427*61046927SAndroid Build Coastguard Worker else: 428*61046927SAndroid Build Coastguard Worker field = list[1].removeprefix(teststr) 429*61046927SAndroid Build Coastguard Worker bitfield = list[2].split(":") 430*61046927SAndroid Build Coastguard Worker curmthd.field_name_start[field] = bitfield[1] 431*61046927SAndroid Build Coastguard Worker curmthd.field_name_end[field] = bitfield[0] 432*61046927SAndroid Build Coastguard Worker curmthd.field_defs[field] = {} 433*61046927SAndroid Build Coastguard Worker curfield = field 434*61046927SAndroid Build Coastguard Worker state = 2 435*61046927SAndroid Build Coastguard Worker else: 436*61046927SAndroid Build Coastguard Worker if not len(curmthd.field_name_start): 437*61046927SAndroid Build Coastguard Worker del mthddict[curmthd.name] 438*61046927SAndroid Build Coastguard Worker curmthd = {} 439*61046927SAndroid Build Coastguard Worker state = 0 440*61046927SAndroid Build Coastguard Worker 441*61046927SAndroid Build Coastguard Worker if state == 0: 442*61046927SAndroid Build Coastguard Worker if (curmthd): 443*61046927SAndroid Build Coastguard Worker if not len(curmthd.field_name_start): 444*61046927SAndroid Build Coastguard Worker del mthddict[curmthd.name] 445*61046927SAndroid Build Coastguard Worker teststr = nvcl + "_" 446*61046927SAndroid Build Coastguard Worker is_array = 0 447*61046927SAndroid Build Coastguard Worker if (':' in list[2]): 448*61046927SAndroid Build Coastguard Worker continue 449*61046927SAndroid Build Coastguard Worker name = list[1].removeprefix(teststr) 450*61046927SAndroid Build Coastguard Worker if name.endswith("(i)"): 451*61046927SAndroid Build Coastguard Worker is_array = 1 452*61046927SAndroid Build Coastguard Worker name = name.removesuffix("(i)") 453*61046927SAndroid Build Coastguard Worker if name.endswith("(j)"): 454*61046927SAndroid Build Coastguard Worker is_array = 1 455*61046927SAndroid Build Coastguard Worker name = name.removesuffix("(j)") 456*61046927SAndroid Build Coastguard Worker x = method() 457*61046927SAndroid Build Coastguard Worker x.name = name 458*61046927SAndroid Build Coastguard Worker x.addr = list[2] 459*61046927SAndroid Build Coastguard Worker x.is_array = is_array 460*61046927SAndroid Build Coastguard Worker x.field_name_start = {} 461*61046927SAndroid Build Coastguard Worker x.field_name_end = {} 462*61046927SAndroid Build Coastguard Worker x.field_defs = {} 463*61046927SAndroid Build Coastguard Worker x.field_rs_types = {} 464*61046927SAndroid Build Coastguard Worker x.field_is_rs_enum = {} 465*61046927SAndroid Build Coastguard Worker mthddict[x.name] = x 466*61046927SAndroid Build Coastguard Worker 467*61046927SAndroid Build Coastguard Worker curmthd = x 468*61046927SAndroid Build Coastguard Worker state = 1 469*61046927SAndroid Build Coastguard Worker 470*61046927SAndroid Build Coastguard Worker return (version, mthddict) 471*61046927SAndroid Build Coastguard Worker 472*61046927SAndroid Build Coastguard Workerdef convert_to_rust_constants(filename): 473*61046927SAndroid Build Coastguard Worker with open(filename, 'r') as file: 474*61046927SAndroid Build Coastguard Worker lines = file.readlines() 475*61046927SAndroid Build Coastguard Worker 476*61046927SAndroid Build Coastguard Worker rust_items = [] 477*61046927SAndroid Build Coastguard Worker processed_constants = {} 478*61046927SAndroid Build Coastguard Worker file_prefix = "NV" + os.path.splitext(os.path.basename(filename))[0].upper() + "_" 479*61046927SAndroid Build Coastguard Worker file_prefix = file_prefix.replace('CL', '') 480*61046927SAndroid Build Coastguard Worker for line in lines: 481*61046927SAndroid Build Coastguard Worker match = re.match(r'#define\s+(\w+)\((\w+)\)\s+(.+)', line.strip()) 482*61046927SAndroid Build Coastguard Worker if match: 483*61046927SAndroid Build Coastguard Worker name, arg, expr = match.groups() 484*61046927SAndroid Build Coastguard Worker if name in processed_constants: 485*61046927SAndroid Build Coastguard Worker processed_constants[name] += 1 486*61046927SAndroid Build Coastguard Worker name += f"_{processed_constants[name]}" 487*61046927SAndroid Build Coastguard Worker else: 488*61046927SAndroid Build Coastguard Worker processed_constants[name] = 0 489*61046927SAndroid Build Coastguard Worker name = name.replace(file_prefix, '') 490*61046927SAndroid Build Coastguard Worker # convert to snake case 491*61046927SAndroid Build Coastguard Worker name = re.sub(r'(?<=[a-z])(?=[A-Z])', '_', name).lower() 492*61046927SAndroid Build Coastguard Worker rust_items.append(f"#[inline]\npub fn {name} ({arg}: u32) -> u32 {{ {expr.replace('(', '').replace(')', '')} }} ") 493*61046927SAndroid Build Coastguard Worker else: 494*61046927SAndroid Build Coastguard Worker match = re.match(r'#define\s+(\w+)\s+(?:MW\()?(\d+):(\d+)\)?', line.strip()) 495*61046927SAndroid Build Coastguard Worker if match: 496*61046927SAndroid Build Coastguard Worker name, high, low = match.groups() 497*61046927SAndroid Build Coastguard Worker high = int(high) + 1 # Convert to exclusive range 498*61046927SAndroid Build Coastguard Worker if name in processed_constants: 499*61046927SAndroid Build Coastguard Worker processed_constants[name] += 1 500*61046927SAndroid Build Coastguard Worker name += f"_{processed_constants[name]}" 501*61046927SAndroid Build Coastguard Worker else: 502*61046927SAndroid Build Coastguard Worker processed_constants[name] = 0 503*61046927SAndroid Build Coastguard Worker # name = name.replace('__', '_').replace(file_prefix, '') 504*61046927SAndroid Build Coastguard Worker name = name.replace(file_prefix, '') 505*61046927SAndroid Build Coastguard Worker rust_items.append(f"pub const {name}: Range<u32> = {low}..{high};") 506*61046927SAndroid Build Coastguard Worker else: 507*61046927SAndroid Build Coastguard Worker match = re.match(r'#define\s+(\w+)\s+\(?0x(\w+)\)?', line.strip()) 508*61046927SAndroid Build Coastguard Worker if match: 509*61046927SAndroid Build Coastguard Worker name, value = match.groups() 510*61046927SAndroid Build Coastguard Worker if name in processed_constants: 511*61046927SAndroid Build Coastguard Worker processed_constants[name] += 1 512*61046927SAndroid Build Coastguard Worker name += f"_{processed_constants[name]}" 513*61046927SAndroid Build Coastguard Worker else: 514*61046927SAndroid Build Coastguard Worker processed_constants[name] = 0 515*61046927SAndroid Build Coastguard Worker name = name.replace(file_prefix, '') 516*61046927SAndroid Build Coastguard Worker rust_items.append(f"pub const {name}: u32 = 0x{value};") 517*61046927SAndroid Build Coastguard Worker else: 518*61046927SAndroid Build Coastguard Worker match = re.match(r'#define\s+(\w+)\s+\(?(\d+)\)?', line.strip()) 519*61046927SAndroid Build Coastguard Worker if match: 520*61046927SAndroid Build Coastguard Worker name, value = match.groups() 521*61046927SAndroid Build Coastguard Worker if name in processed_constants: 522*61046927SAndroid Build Coastguard Worker processed_constants[name] += 1 523*61046927SAndroid Build Coastguard Worker name += f"_{processed_constants[name]}" 524*61046927SAndroid Build Coastguard Worker else: 525*61046927SAndroid Build Coastguard Worker processed_constants[name] = 0 526*61046927SAndroid Build Coastguard Worker name = name.replace(file_prefix, '') 527*61046927SAndroid Build Coastguard Worker rust_items.append(f"pub const {name}: u32 = {value};") 528*61046927SAndroid Build Coastguard Worker 529*61046927SAndroid Build Coastguard Worker return '\n'.join(rust_items) 530*61046927SAndroid Build Coastguard Worker 531*61046927SAndroid Build Coastguard Workerdef main(): 532*61046927SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 533*61046927SAndroid Build Coastguard Worker parser.add_argument('--out-h', required=False, help='Output C header.') 534*61046927SAndroid Build Coastguard Worker parser.add_argument('--out-c', required=False, help='Output C file.') 535*61046927SAndroid Build Coastguard Worker parser.add_argument('--out-rs', required=False, help='Output Rust file.') 536*61046927SAndroid Build Coastguard Worker parser.add_argument('--out-rs-mthd', required=False, 537*61046927SAndroid Build Coastguard Worker help='Output Rust file for methods.') 538*61046927SAndroid Build Coastguard Worker parser.add_argument('--in-h', 539*61046927SAndroid Build Coastguard Worker help='Input class header file.', 540*61046927SAndroid Build Coastguard Worker required=True) 541*61046927SAndroid Build Coastguard Worker args = parser.parse_args() 542*61046927SAndroid Build Coastguard Worker 543*61046927SAndroid Build Coastguard Worker clheader = os.path.basename(args.in_h) 544*61046927SAndroid Build Coastguard Worker nvcl = clheader 545*61046927SAndroid Build Coastguard Worker nvcl = nvcl.removeprefix("cl") 546*61046927SAndroid Build Coastguard Worker nvcl = nvcl.removesuffix(".h") 547*61046927SAndroid Build Coastguard Worker nvcl = nvcl.upper() 548*61046927SAndroid Build Coastguard Worker nvcl = "NV" + nvcl 549*61046927SAndroid Build Coastguard Worker 550*61046927SAndroid Build Coastguard Worker with open(args.in_h, 'r', encoding='utf-8') as f: 551*61046927SAndroid Build Coastguard Worker (version, mthddict) = parse_header(nvcl, f) 552*61046927SAndroid Build Coastguard Worker 553*61046927SAndroid Build Coastguard Worker environment = { 554*61046927SAndroid Build Coastguard Worker 'clheader': clheader, 555*61046927SAndroid Build Coastguard Worker 'nvcl': nvcl, 556*61046927SAndroid Build Coastguard Worker 'version': version, 557*61046927SAndroid Build Coastguard Worker 'mthddict': mthddict, 558*61046927SAndroid Build Coastguard Worker 'rs_field_name': rs_field_name, 559*61046927SAndroid Build Coastguard Worker 'to_camel': to_camel, 560*61046927SAndroid Build Coastguard Worker 'bs': '\\' 561*61046927SAndroid Build Coastguard Worker } 562*61046927SAndroid Build Coastguard Worker 563*61046927SAndroid Build Coastguard Worker try: 564*61046927SAndroid Build Coastguard Worker if args.out_h is not None: 565*61046927SAndroid Build Coastguard Worker environment['header'] = os.path.basename(args.out_h) 566*61046927SAndroid Build Coastguard Worker with open(args.out_h, 'w', encoding='utf-8') as f: 567*61046927SAndroid Build Coastguard Worker f.write(TEMPLATE_H.render(**environment)) 568*61046927SAndroid Build Coastguard Worker if args.out_c is not None: 569*61046927SAndroid Build Coastguard Worker with open(args.out_c, 'w', encoding='utf-8') as f: 570*61046927SAndroid Build Coastguard Worker f.write(TEMPLATE_C.render(**environment)) 571*61046927SAndroid Build Coastguard Worker if args.out_rs is not None: 572*61046927SAndroid Build Coastguard Worker with open(args.out_rs, 'w', encoding='utf-8') as f: 573*61046927SAndroid Build Coastguard Worker f.write(TEMPLATE_RS.render(**environment)) 574*61046927SAndroid Build Coastguard Worker if args.out_rs_mthd is not None: 575*61046927SAndroid Build Coastguard Worker with open(args.out_rs_mthd, 'w', encoding='utf-8') as f: 576*61046927SAndroid Build Coastguard Worker f.write("#![allow(non_camel_case_types)]\n") 577*61046927SAndroid Build Coastguard Worker f.write("#![allow(non_snake_case)]\n") 578*61046927SAndroid Build Coastguard Worker f.write("#![allow(non_upper_case_globals)]\n\n") 579*61046927SAndroid Build Coastguard Worker f.write("use std::ops::Range;\n") 580*61046927SAndroid Build Coastguard Worker f.write("use crate::Mthd;\n") 581*61046927SAndroid Build Coastguard Worker f.write("use crate::ArrayMthd;\n") 582*61046927SAndroid Build Coastguard Worker f.write("\n") 583*61046927SAndroid Build Coastguard Worker f.write(convert_to_rust_constants(args.in_h)) 584*61046927SAndroid Build Coastguard Worker f.write("\n") 585*61046927SAndroid Build Coastguard Worker f.write(TEMPLATE_RS_MTHD.render(**environment)) 586*61046927SAndroid Build Coastguard Worker 587*61046927SAndroid Build Coastguard Worker except Exception: 588*61046927SAndroid Build Coastguard Worker # In the event there's an error, this imports some helpers from mako 589*61046927SAndroid Build Coastguard Worker # to print a useful stack trace and prints it, then exits with 590*61046927SAndroid Build Coastguard Worker # status 1, if python is run with debug; otherwise it just raises 591*61046927SAndroid Build Coastguard Worker # the exception 592*61046927SAndroid Build Coastguard Worker import sys 593*61046927SAndroid Build Coastguard Worker from mako import exceptions 594*61046927SAndroid Build Coastguard Worker print(exceptions.text_error_template().render(), file=sys.stderr) 595*61046927SAndroid Build Coastguard Worker sys.exit(1) 596*61046927SAndroid Build Coastguard Worker 597*61046927SAndroid Build Coastguard Workerif __name__ == '__main__': 598*61046927SAndroid Build Coastguard Worker main() 599