17ec681f3Smrg# 27ec681f3Smrg# Copyright 2017-2019 Advanced Micro Devices, Inc. 37ec681f3Smrg# 47ec681f3Smrg# Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg# copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg# to deal in the Software without restriction, including without limitation 77ec681f3Smrg# on the rights to use, copy, modify, merge, publish, distribute, sub 87ec681f3Smrg# license, and/or sell copies of the Software, and to permit persons to whom 97ec681f3Smrg# the Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg# 117ec681f3Smrg# The above copyright notice and this permission notice (including the next 127ec681f3Smrg# paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg# Software. 147ec681f3Smrg# 157ec681f3Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg# THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 197ec681f3Smrg# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 207ec681f3Smrg# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 217ec681f3Smrg# USE OR OTHER DEALINGS IN THE SOFTWARE. 227ec681f3Smrg# 237ec681f3Smrg""" 247ec681f3SmrgHelper script that parses a register header and produces a register database 257ec681f3Smrgas output. Use as: 267ec681f3Smrg 277ec681f3Smrg python3 parseheader.py ADDRESS_SPACE < header.h 287ec681f3Smrg 297ec681f3SmrgThis script is included for reference -- we should be able to remove this in 307ec681f3Smrgthe future. 317ec681f3Smrg""" 327ec681f3Smrg 337ec681f3Smrgimport json 347ec681f3Smrgimport math 357ec681f3Smrgimport re 367ec681f3Smrgimport sys 377ec681f3Smrg 387ec681f3Smrgfrom regdb import Object, RegisterDatabase, deduplicate_enums, deduplicate_register_types 397ec681f3Smrg 407ec681f3Smrg 417ec681f3SmrgRE_comment = re.compile(r'(/\*(.*)\*/)$|(//(.*))$') 427ec681f3SmrgRE_prefix = re.compile(r'([RSV])_([0-9a-fA-F]+)_') 437ec681f3SmrgRE_set_value = re.compile(r'\(\(\(unsigned\)\(x\) & ([0-9a-fA-Fx]+)\) << ([0-9]+)\)') 447ec681f3SmrgRE_set_value_no_shift = re.compile(r'\((\(unsigned\))?\(x\) & ([0-9a-fA-Fx]+)\)') 457ec681f3Smrg 467ec681f3Smrgclass HeaderParser(object): 477ec681f3Smrg def __init__(self, address_space): 487ec681f3Smrg self.regdb = RegisterDatabase() 497ec681f3Smrg self.chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9'] 507ec681f3Smrg self.address_space = address_space 517ec681f3Smrg 527ec681f3Smrg def __fini_field(self): 537ec681f3Smrg if self.__field is None: 547ec681f3Smrg return 557ec681f3Smrg 567ec681f3Smrg if self.__enumentries: 577ec681f3Smrg self.__field.enum_ref = self.__regmap.name + '__' + self.__field.name 587ec681f3Smrg self.regdb.add_enum(self.__field.enum_ref, Object( 597ec681f3Smrg entries=self.__enumentries 607ec681f3Smrg )) 617ec681f3Smrg self.__fields.append(self.__field) 627ec681f3Smrg 637ec681f3Smrg self.__enumentries = None 647ec681f3Smrg self.__field = None 657ec681f3Smrg 667ec681f3Smrg def __fini_register(self): 677ec681f3Smrg if self.__regmap is None: 687ec681f3Smrg return 697ec681f3Smrg 707ec681f3Smrg if self.__fields: 717ec681f3Smrg self.regdb.add_register_type(self.__regmap.name, Object( 727ec681f3Smrg fields=self.__fields 737ec681f3Smrg )) 747ec681f3Smrg self.__regmap.type_ref = self.__regmap.name 757ec681f3Smrg self.regdb.add_register_mapping(self.__regmap) 767ec681f3Smrg 777ec681f3Smrg self.__regmap = None 787ec681f3Smrg self.__fields = None 797ec681f3Smrg 807ec681f3Smrg def parse_header(self, filp): 817ec681f3Smrg regdb = RegisterDatabase() 827ec681f3Smrg chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9'] 837ec681f3Smrg 847ec681f3Smrg self.__regmap = None 857ec681f3Smrg self.__fields = None 867ec681f3Smrg self.__field = None 877ec681f3Smrg self.__enumentries = None 887ec681f3Smrg 897ec681f3Smrg for line in filp: 907ec681f3Smrg if not line.startswith('#define '): 917ec681f3Smrg continue 927ec681f3Smrg 937ec681f3Smrg line = line[8:].strip() 947ec681f3Smrg 957ec681f3Smrg comment = None 967ec681f3Smrg m = RE_comment.search(line) 977ec681f3Smrg if m is not None: 987ec681f3Smrg comment = m.group(2) or m.group(4) 997ec681f3Smrg comment = comment.strip() 1007ec681f3Smrg line = line[:m.span()[0]].strip() 1017ec681f3Smrg 1027ec681f3Smrg split = line.split(None, 1) 1037ec681f3Smrg name = split[0] 1047ec681f3Smrg 1057ec681f3Smrg m = RE_prefix.match(name) 1067ec681f3Smrg if m is None: 1077ec681f3Smrg continue 1087ec681f3Smrg 1097ec681f3Smrg prefix = m.group(1) 1107ec681f3Smrg prefix_address = int(m.group(2), 16) 1117ec681f3Smrg name = name[m.span()[1]:] 1127ec681f3Smrg 1137ec681f3Smrg if prefix == 'V': 1147ec681f3Smrg value = int(split[1], 0) 1157ec681f3Smrg 1167ec681f3Smrg for entry in self.__enumentries: 1177ec681f3Smrg if name == entry.name: 1187ec681f3Smrg sys.exit('Duplicate value define: name = {0}'.format(name)) 1197ec681f3Smrg 1207ec681f3Smrg entry = Object(name=name, value=value) 1217ec681f3Smrg if comment is not None: 1227ec681f3Smrg entry.comment = comment 1237ec681f3Smrg self.__enumentries.append(entry) 1247ec681f3Smrg continue 1257ec681f3Smrg 1267ec681f3Smrg if prefix == 'S': 1277ec681f3Smrg self.__fini_field() 1287ec681f3Smrg 1297ec681f3Smrg if not name.endswith('(x)'): 1307ec681f3Smrg sys.exit('Missing (x) in S line: {0}'.line) 1317ec681f3Smrg name = name[:-3] 1327ec681f3Smrg 1337ec681f3Smrg for field in self.__fields: 1347ec681f3Smrg if name == field.name: 1357ec681f3Smrg sys.exit('Duplicate field define: {0}'.format(name)) 1367ec681f3Smrg 1377ec681f3Smrg m = RE_set_value.match(split[1]) 1387ec681f3Smrg if m is not None: 1397ec681f3Smrg unshifted_mask = int(m.group(1), 0) 1407ec681f3Smrg shift = int(m.group(2), 0) 1417ec681f3Smrg else: 1427ec681f3Smrg m = RE_set_value_no_shift.match(split[1]) 1437ec681f3Smrg if m is not None: 1447ec681f3Smrg unshifted_mask = int(m.group(2), 0) 1457ec681f3Smrg shift = 0 1467ec681f3Smrg else: 1477ec681f3Smrg sys.exit('Bad S_xxx_xxx define: {0}'.format(line)) 1487ec681f3Smrg 1497ec681f3Smrg num_bits = int(math.log2(unshifted_mask + 1)) 1507ec681f3Smrg if unshifted_mask != (1 << num_bits) - 1: 1517ec681f3Smrg sys.exit('Bad unshifted mask in {0}'.format(line)) 1527ec681f3Smrg 1537ec681f3Smrg self.__field = Object( 1547ec681f3Smrg name=name, 1557ec681f3Smrg bits=[shift, shift + num_bits - 1], 1567ec681f3Smrg ) 1577ec681f3Smrg if comment is not None: 1587ec681f3Smrg self.__field.comment = comment 1597ec681f3Smrg self.__enumentries = [] 1607ec681f3Smrg 1617ec681f3Smrg if prefix == 'R': 1627ec681f3Smrg self.__fini_field() 1637ec681f3Smrg self.__fini_register() 1647ec681f3Smrg 1657ec681f3Smrg if regdb.register_mappings_by_name(name): 1667ec681f3Smrg sys.exit('Duplicate register define: {0}'.format(name)) 1677ec681f3Smrg 1687ec681f3Smrg address = int(split[1], 0) 1697ec681f3Smrg if address != prefix_address: 1707ec681f3Smrg sys.exit('Inconsistent register address: {0}'.format(line)) 1717ec681f3Smrg 1727ec681f3Smrg self.__regmap = Object( 1737ec681f3Smrg name=name, 1747ec681f3Smrg chips=self.chips, 1757ec681f3Smrg map=Object(to=self.address_space, at=address), 1767ec681f3Smrg ) 1777ec681f3Smrg self.__fields = [] 1787ec681f3Smrg 1797ec681f3Smrg self.__fini_field() 1807ec681f3Smrg self.__fini_register() 1817ec681f3Smrg 1827ec681f3Smrgdef main(): 1837ec681f3Smrg map_to = sys.argv[1] 1847ec681f3Smrg 1857ec681f3Smrg parser = HeaderParser(map_to) 1867ec681f3Smrg parser.parse_header(sys.stdin) 1877ec681f3Smrg 1887ec681f3Smrg deduplicate_enums(parser.regdb) 1897ec681f3Smrg deduplicate_register_types(parser.regdb) 1907ec681f3Smrg 1917ec681f3Smrg print(parser.regdb.encode_json_pretty()) 1927ec681f3Smrg 1937ec681f3Smrg 1947ec681f3Smrgif __name__ == '__main__': 1957ec681f3Smrg main() 1967ec681f3Smrg 1977ec681f3Smrg# kate: space-indent on; indent-width 4; replace-tabs on; 198