1bf215546Sopenharmony_ci# 2bf215546Sopenharmony_ci# Copyright 2017-2019 Advanced Micro Devices, Inc. 3bf215546Sopenharmony_ci# 4bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci# copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci# to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci# on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci# license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci# the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci# 11bf215546Sopenharmony_ci# The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci# paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci# Software. 14bf215546Sopenharmony_ci# 15bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci# THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci# USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci# 23bf215546Sopenharmony_ci""" 24bf215546Sopenharmony_ciHelper script that parses a register header and produces a register database 25bf215546Sopenharmony_cias output. Use as: 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci python3 parseheader.py ADDRESS_SPACE < header.h 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ciThis script is included for reference -- we should be able to remove this in 30bf215546Sopenharmony_cithe future. 31bf215546Sopenharmony_ci""" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ciimport json 34bf215546Sopenharmony_ciimport math 35bf215546Sopenharmony_ciimport re 36bf215546Sopenharmony_ciimport sys 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cifrom regdb import Object, RegisterDatabase, deduplicate_enums, deduplicate_register_types 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ciRE_comment = re.compile(r'(/\*(.*)\*/)$|(//(.*))$') 42bf215546Sopenharmony_ciRE_prefix = re.compile(r'([RSV])_([0-9a-fA-F]+)_') 43bf215546Sopenharmony_ciRE_set_value = re.compile(r'\(\(\(unsigned\)\(x\) & ([0-9a-fA-Fx]+)\) << ([0-9]+)\)') 44bf215546Sopenharmony_ciRE_set_value_no_shift = re.compile(r'\((\(unsigned\))?\(x\) & ([0-9a-fA-Fx]+)\)') 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ciclass HeaderParser(object): 47bf215546Sopenharmony_ci def __init__(self, address_space): 48bf215546Sopenharmony_ci self.regdb = RegisterDatabase() 49bf215546Sopenharmony_ci self.chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9'] 50bf215546Sopenharmony_ci self.address_space = address_space 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci def __fini_field(self): 53bf215546Sopenharmony_ci if self.__field is None: 54bf215546Sopenharmony_ci return 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci if self.__enumentries: 57bf215546Sopenharmony_ci self.__field.enum_ref = self.__regmap.name + '__' + self.__field.name 58bf215546Sopenharmony_ci self.regdb.add_enum(self.__field.enum_ref, Object( 59bf215546Sopenharmony_ci entries=self.__enumentries 60bf215546Sopenharmony_ci )) 61bf215546Sopenharmony_ci self.__fields.append(self.__field) 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci self.__enumentries = None 64bf215546Sopenharmony_ci self.__field = None 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci def __fini_register(self): 67bf215546Sopenharmony_ci if self.__regmap is None: 68bf215546Sopenharmony_ci return 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci if self.__fields: 71bf215546Sopenharmony_ci self.regdb.add_register_type(self.__regmap.name, Object( 72bf215546Sopenharmony_ci fields=self.__fields 73bf215546Sopenharmony_ci )) 74bf215546Sopenharmony_ci self.__regmap.type_ref = self.__regmap.name 75bf215546Sopenharmony_ci self.regdb.add_register_mapping(self.__regmap) 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci self.__regmap = None 78bf215546Sopenharmony_ci self.__fields = None 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci def parse_header(self, filp): 81bf215546Sopenharmony_ci regdb = RegisterDatabase() 82bf215546Sopenharmony_ci chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9'] 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci self.__regmap = None 85bf215546Sopenharmony_ci self.__fields = None 86bf215546Sopenharmony_ci self.__field = None 87bf215546Sopenharmony_ci self.__enumentries = None 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci for line in filp: 90bf215546Sopenharmony_ci if not line.startswith('#define '): 91bf215546Sopenharmony_ci continue 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci line = line[8:].strip() 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci comment = None 96bf215546Sopenharmony_ci m = RE_comment.search(line) 97bf215546Sopenharmony_ci if m is not None: 98bf215546Sopenharmony_ci comment = m.group(2) or m.group(4) 99bf215546Sopenharmony_ci comment = comment.strip() 100bf215546Sopenharmony_ci line = line[:m.span()[0]].strip() 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci split = line.split(None, 1) 103bf215546Sopenharmony_ci name = split[0] 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci m = RE_prefix.match(name) 106bf215546Sopenharmony_ci if m is None: 107bf215546Sopenharmony_ci continue 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci prefix = m.group(1) 110bf215546Sopenharmony_ci prefix_address = int(m.group(2), 16) 111bf215546Sopenharmony_ci name = name[m.span()[1]:] 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if prefix == 'V': 114bf215546Sopenharmony_ci value = int(split[1], 0) 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci for entry in self.__enumentries: 117bf215546Sopenharmony_ci if name == entry.name: 118bf215546Sopenharmony_ci sys.exit('Duplicate value define: name = {0}'.format(name)) 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci entry = Object(name=name, value=value) 121bf215546Sopenharmony_ci if comment is not None: 122bf215546Sopenharmony_ci entry.comment = comment 123bf215546Sopenharmony_ci self.__enumentries.append(entry) 124bf215546Sopenharmony_ci continue 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci if prefix == 'S': 127bf215546Sopenharmony_ci self.__fini_field() 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if not name.endswith('(x)'): 130bf215546Sopenharmony_ci sys.exit('Missing (x) in S line: {0}'.line) 131bf215546Sopenharmony_ci name = name[:-3] 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci for field in self.__fields: 134bf215546Sopenharmony_ci if name == field.name: 135bf215546Sopenharmony_ci sys.exit('Duplicate field define: {0}'.format(name)) 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci m = RE_set_value.match(split[1]) 138bf215546Sopenharmony_ci if m is not None: 139bf215546Sopenharmony_ci unshifted_mask = int(m.group(1), 0) 140bf215546Sopenharmony_ci shift = int(m.group(2), 0) 141bf215546Sopenharmony_ci else: 142bf215546Sopenharmony_ci m = RE_set_value_no_shift.match(split[1]) 143bf215546Sopenharmony_ci if m is not None: 144bf215546Sopenharmony_ci unshifted_mask = int(m.group(2), 0) 145bf215546Sopenharmony_ci shift = 0 146bf215546Sopenharmony_ci else: 147bf215546Sopenharmony_ci sys.exit('Bad S_xxx_xxx define: {0}'.format(line)) 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci num_bits = int(math.log2(unshifted_mask + 1)) 150bf215546Sopenharmony_ci if unshifted_mask != (1 << num_bits) - 1: 151bf215546Sopenharmony_ci sys.exit('Bad unshifted mask in {0}'.format(line)) 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci self.__field = Object( 154bf215546Sopenharmony_ci name=name, 155bf215546Sopenharmony_ci bits=[shift, shift + num_bits - 1], 156bf215546Sopenharmony_ci ) 157bf215546Sopenharmony_ci if comment is not None: 158bf215546Sopenharmony_ci self.__field.comment = comment 159bf215546Sopenharmony_ci self.__enumentries = [] 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci if prefix == 'R': 162bf215546Sopenharmony_ci self.__fini_field() 163bf215546Sopenharmony_ci self.__fini_register() 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci if regdb.register_mappings_by_name(name): 166bf215546Sopenharmony_ci sys.exit('Duplicate register define: {0}'.format(name)) 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci address = int(split[1], 0) 169bf215546Sopenharmony_ci if address != prefix_address: 170bf215546Sopenharmony_ci sys.exit('Inconsistent register address: {0}'.format(line)) 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci self.__regmap = Object( 173bf215546Sopenharmony_ci name=name, 174bf215546Sopenharmony_ci chips=self.chips, 175bf215546Sopenharmony_ci map=Object(to=self.address_space, at=address), 176bf215546Sopenharmony_ci ) 177bf215546Sopenharmony_ci self.__fields = [] 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci self.__fini_field() 180bf215546Sopenharmony_ci self.__fini_register() 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_cidef main(): 183bf215546Sopenharmony_ci map_to = sys.argv[1] 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci parser = HeaderParser(map_to) 186bf215546Sopenharmony_ci parser.parse_header(sys.stdin) 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci deduplicate_enums(parser.regdb) 189bf215546Sopenharmony_ci deduplicate_register_types(parser.regdb) 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci print(parser.regdb.encode_json_pretty()) 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ciif __name__ == '__main__': 195bf215546Sopenharmony_ci main() 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci# kate: space-indent on; indent-width 4; replace-tabs on; 198