Path: blob/21.2-virgl/src/amd/registers/parseheader.py
7081 views
#1# Copyright 2017-2019 Advanced Micro Devices, Inc.2#3# Permission is hereby granted, free of charge, to any person obtaining a4# copy of this software and associated documentation files (the "Software"),5# to deal in the Software without restriction, including without limitation6# on the rights to use, copy, modify, merge, publish, distribute, sub7# license, and/or sell copies of the Software, and to permit persons to whom8# the Software is furnished to do so, subject to the following conditions:9#10# The above copyright notice and this permission notice (including the next11# paragraph) shall be included in all copies or substantial portions of the12# Software.13#14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17# THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20# USE OR OTHER DEALINGS IN THE SOFTWARE.21#22"""23Helper script that parses a register header and produces a register database24as output. Use as:2526python3 parseheader.py ADDRESS_SPACE < header.h2728This script is included for reference -- we should be able to remove this in29the future.30"""3132from __future__ import absolute_import, division, print_function, unicode_literals3334import json35import math36import re37import sys3839from regdb import Object, RegisterDatabase, deduplicate_enums, deduplicate_register_types404142RE_comment = re.compile(r'(/\*(.*)\*/)$|(//(.*))$')43RE_prefix = re.compile(r'([RSV])_([0-9a-fA-F]+)_')44RE_set_value = re.compile(r'\(\(\(unsigned\)\(x\) & ([0-9a-fA-Fx]+)\) << ([0-9]+)\)')45RE_set_value_no_shift = re.compile(r'\((\(unsigned\))?\(x\) & ([0-9a-fA-Fx]+)\)')4647class HeaderParser(object):48def __init__(self, address_space):49self.regdb = RegisterDatabase()50self.chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9']51self.address_space = address_space5253def __fini_field(self):54if self.__field is None:55return5657if self.__enumentries:58self.__field.enum_ref = self.__regmap.name + '__' + self.__field.name59self.regdb.add_enum(self.__field.enum_ref, Object(60entries=self.__enumentries61))62self.__fields.append(self.__field)6364self.__enumentries = None65self.__field = None6667def __fini_register(self):68if self.__regmap is None:69return7071if self.__fields:72self.regdb.add_register_type(self.__regmap.name, Object(73fields=self.__fields74))75self.__regmap.type_ref = self.__regmap.name76self.regdb.add_register_mapping(self.__regmap)7778self.__regmap = None79self.__fields = None8081def parse_header(self, filp):82regdb = RegisterDatabase()83chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9']8485self.__regmap = None86self.__fields = None87self.__field = None88self.__enumentries = None8990for line in filp:91if not line.startswith('#define '):92continue9394line = line[8:].strip()9596comment = None97m = RE_comment.search(line)98if m is not None:99comment = m.group(2) or m.group(4)100comment = comment.strip()101line = line[:m.span()[0]].strip()102103split = line.split(None, 1)104name = split[0]105106m = RE_prefix.match(name)107if m is None:108continue109110prefix = m.group(1)111prefix_address = int(m.group(2), 16)112name = name[m.span()[1]:]113114if prefix == 'V':115value = int(split[1], 0)116117for entry in self.__enumentries:118if name == entry.name:119sys.exit('Duplicate value define: name = {0}'.format(name))120121entry = Object(name=name, value=value)122if comment is not None:123entry.comment = comment124self.__enumentries.append(entry)125continue126127if prefix == 'S':128self.__fini_field()129130if not name.endswith('(x)'):131sys.exit('Missing (x) in S line: {0}'.line)132name = name[:-3]133134for field in self.__fields:135if name == field.name:136sys.exit('Duplicate field define: {0}'.format(name))137138m = RE_set_value.match(split[1])139if m is not None:140unshifted_mask = int(m.group(1), 0)141shift = int(m.group(2), 0)142else:143m = RE_set_value_no_shift.match(split[1])144if m is not None:145unshifted_mask = int(m.group(2), 0)146shift = 0147else:148sys.exit('Bad S_xxx_xxx define: {0}'.format(line))149150num_bits = int(math.log2(unshifted_mask + 1))151if unshifted_mask != (1 << num_bits) - 1:152sys.exit('Bad unshifted mask in {0}'.format(line))153154self.__field = Object(155name=name,156bits=[shift, shift + num_bits - 1],157)158if comment is not None:159self.__field.comment = comment160self.__enumentries = []161162if prefix == 'R':163self.__fini_field()164self.__fini_register()165166if regdb.register_mappings_by_name(name):167sys.exit('Duplicate register define: {0}'.format(name))168169address = int(split[1], 0)170if address != prefix_address:171sys.exit('Inconsistent register address: {0}'.format(line))172173self.__regmap = Object(174name=name,175chips=self.chips,176map=Object(to=self.address_space, at=address),177)178self.__fields = []179180self.__fini_field()181self.__fini_register()182183def main():184map_to = sys.argv[1]185186parser = HeaderParser(map_to)187parser.parse_header(sys.stdin)188189deduplicate_enums(parser.regdb)190deduplicate_register_types(parser.regdb)191192print(parser.regdb.encode_json_pretty())193194195if __name__ == '__main__':196main()197198# kate: space-indent on; indent-width 4; replace-tabs on;199200201