#!/usr/bin/python3
#
# Copyright © 2019-2024 Google, Inc.
#
# SPDX-License-Identifier: MIT
import xml.parsers.expat
import sys
import os
import collections
import argparse
import time
import datetime
class Error(Exception):
def __init__(self, message):
self.message = message
class Enum(object):
def __init__(self, name):
self.name = name
self.values = []
def has_name(self, name):
for (n, value) in self.values:
if n == name:
return True
return False
def names(self):
return [n for (n, value) in self.values]
def dump(self):
use_hex = False
for (name, value) in self.values:
if value > 0x1000:
use_hex = True
print("enum %s {" % self.name)
for (name, value) in self.values:
if use_hex:
print("\t%s = 0x%08x," % (name, value))
else:
print("\t%s = %d," % (name, value))
print("};\n")
def dump_pack_struct(self):
pass
class Field(object):
def __init__(self, name, low, high, shr, type, parser):
self.name = name
self.low = low
self.high = high
self.shr = shr
self.type = type
builtin_types = [ None, "a3xx_regid", "boolean", "uint", "hex", "int", "fixed", "ufixed", "float", "address", "waddress" ]
maxpos = parser.current_bitsize - 1
if low < 0 or low > maxpos:
raise parser.error("low attribute out of range: %d" % low)
if high < 0 or high > maxpos:
raise parser.error("high attribute out of range: %d" % high)
if high < low:
raise parser.error("low is greater than high: low=%d, high=%d" % (low, high))
if self.type == "boolean" and not low == high:
raise parser.error("booleans should be 1 bit fields")
elif self.type == "float" and not (high - low == 31 or high - low == 15):
raise parser.error("floats should be 16 or 32 bit fields")
elif not self.type in builtin_types and not self.type in parser.enums:
raise parser.error("unknown type '%s'" % self.type)
def ctype(self, var_name):
if self.type == None:
type = "uint32_t"
val = var_name
elif self.type == "boolean":
type = "bool"
val = var_name
elif self.type == "uint" or self.type == "hex" or self.type == "a3xx_regid":
type = "uint32_t"
val = var_name
elif self.type == "int":
type = "int32_t"
val = var_name
elif self.type == "fixed":
type = "float"
val = "((int32_t)(%s * %d.0))" % (var_name, 1 << self.radix)
elif self.type == "ufixed":
type = "float"
val = "((uint32_t)(%s * %d.0))" % (var_name, 1 << self.radix)
elif self.type == "float" and self.high - self.low == 31:
type = "float"
val = "fui(%s)" % var_name
elif self.type == "float" and self.high - self.low == 15:
type = "float"
val = "_mesa_float_to_half(%s)" % var_name
elif self.type in [ "address", "waddress" ]:
type = "uint64_t"
val = var_name
else:
type = "enum %s" % self.type
val = var_name
if self.shr > 0:
val = "(%s >> %d)" % (val, self.shr)
return (type, val)
def tab_to(name, value):
tab_count = (68 - (len(name) & ~7)) // 8
if tab_count <= 0:
tab_count = 1
print(name + ('\t' * tab_count) + value)
def mask(low, high):
return ((0xffffffffffffffff >> (64 - (high + 1 - low))) << low)
def field_name(reg, f):
if f.name:
name = f.name.lower()
else:
# We hit this path when a reg is defined with no bitset fields, ie.
# <reg32 offset="0x88db" name="RB_BLIT_DST_ARRAY_PITCH" low="0" high="28" shr="6" type="uint"/>
name = reg.name.lower()
if (name in [ "double", "float", "int" ]) or not (name[0].isalpha()):
name = "_" + name
return name
# indices - array of (ctype, stride, __offsets_NAME)
def indices_varlist(indices):
return ", ".join(["i%d" % i for i in range(len(indices))])
def indices_prototype(indices):
return ", ".join(["%s i%d" % (ctype, idx)
for (idx,