1*61046927SAndroid Build Coastguard Worker# 2*61046927SAndroid Build Coastguard Worker# Copyright 2017-2019 Advanced Micro Devices, Inc. 3*61046927SAndroid Build Coastguard Worker# 4*61046927SAndroid Build Coastguard Worker# SPDX-License-Identifier: MIT 5*61046927SAndroid Build Coastguard Worker# 6*61046927SAndroid Build Coastguard Worker""" 7*61046927SAndroid Build Coastguard WorkerHelper script that parses a register header and produces a register database 8*61046927SAndroid Build Coastguard Workeras output. Use as: 9*61046927SAndroid Build Coastguard Worker 10*61046927SAndroid Build Coastguard Worker python3 parseheader.py ADDRESS_SPACE < header.h 11*61046927SAndroid Build Coastguard Worker 12*61046927SAndroid Build Coastguard WorkerThis script is included for reference -- we should be able to remove this in 13*61046927SAndroid Build Coastguard Workerthe future. 14*61046927SAndroid Build Coastguard Worker""" 15*61046927SAndroid Build Coastguard Worker 16*61046927SAndroid Build Coastguard Workerimport json 17*61046927SAndroid Build Coastguard Workerimport math 18*61046927SAndroid Build Coastguard Workerimport re 19*61046927SAndroid Build Coastguard Workerimport sys 20*61046927SAndroid Build Coastguard Worker 21*61046927SAndroid Build Coastguard Workerfrom regdb import Object, RegisterDatabase, deduplicate_enums, deduplicate_register_types 22*61046927SAndroid Build Coastguard Worker 23*61046927SAndroid Build Coastguard Worker 24*61046927SAndroid Build Coastguard WorkerRE_comment = re.compile(r'(/\*(.*)\*/)$|(//(.*))$') 25*61046927SAndroid Build Coastguard WorkerRE_prefix = re.compile(r'([RSV])_([0-9a-fA-F]+)_') 26*61046927SAndroid Build Coastguard WorkerRE_set_value = re.compile(r'\(\(\(unsigned\)\(x\) & ([0-9a-fA-Fx]+)\) << ([0-9]+)\)') 27*61046927SAndroid Build Coastguard WorkerRE_set_value_no_shift = re.compile(r'\((\(unsigned\))?\(x\) & ([0-9a-fA-Fx]+)\)') 28*61046927SAndroid Build Coastguard Worker 29*61046927SAndroid Build Coastguard Workerclass HeaderParser(object): 30*61046927SAndroid Build Coastguard Worker def __init__(self, address_space): 31*61046927SAndroid Build Coastguard Worker self.regdb = RegisterDatabase() 32*61046927SAndroid Build Coastguard Worker self.chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9'] 33*61046927SAndroid Build Coastguard Worker self.address_space = address_space 34*61046927SAndroid Build Coastguard Worker 35*61046927SAndroid Build Coastguard Worker def __fini_field(self): 36*61046927SAndroid Build Coastguard Worker if self.__field is None: 37*61046927SAndroid Build Coastguard Worker return 38*61046927SAndroid Build Coastguard Worker 39*61046927SAndroid Build Coastguard Worker if self.__enumentries: 40*61046927SAndroid Build Coastguard Worker self.__field.enum_ref = self.__regmap.name + '__' + self.__field.name 41*61046927SAndroid Build Coastguard Worker self.regdb.add_enum(self.__field.enum_ref, Object( 42*61046927SAndroid Build Coastguard Worker entries=self.__enumentries 43*61046927SAndroid Build Coastguard Worker )) 44*61046927SAndroid Build Coastguard Worker self.__fields.append(self.__field) 45*61046927SAndroid Build Coastguard Worker 46*61046927SAndroid Build Coastguard Worker self.__enumentries = None 47*61046927SAndroid Build Coastguard Worker self.__field = None 48*61046927SAndroid Build Coastguard Worker 49*61046927SAndroid Build Coastguard Worker def __fini_register(self): 50*61046927SAndroid Build Coastguard Worker if self.__regmap is None: 51*61046927SAndroid Build Coastguard Worker return 52*61046927SAndroid Build Coastguard Worker 53*61046927SAndroid Build Coastguard Worker if self.__fields: 54*61046927SAndroid Build Coastguard Worker self.regdb.add_register_type(self.__regmap.name, Object( 55*61046927SAndroid Build Coastguard Worker fields=self.__fields 56*61046927SAndroid Build Coastguard Worker )) 57*61046927SAndroid Build Coastguard Worker self.__regmap.type_ref = self.__regmap.name 58*61046927SAndroid Build Coastguard Worker self.regdb.add_register_mapping(self.__regmap) 59*61046927SAndroid Build Coastguard Worker 60*61046927SAndroid Build Coastguard Worker self.__regmap = None 61*61046927SAndroid Build Coastguard Worker self.__fields = None 62*61046927SAndroid Build Coastguard Worker 63*61046927SAndroid Build Coastguard Worker def parse_header(self, filp): 64*61046927SAndroid Build Coastguard Worker regdb = RegisterDatabase() 65*61046927SAndroid Build Coastguard Worker chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9'] 66*61046927SAndroid Build Coastguard Worker 67*61046927SAndroid Build Coastguard Worker self.__regmap = None 68*61046927SAndroid Build Coastguard Worker self.__fields = None 69*61046927SAndroid Build Coastguard Worker self.__field = None 70*61046927SAndroid Build Coastguard Worker self.__enumentries = None 71*61046927SAndroid Build Coastguard Worker 72*61046927SAndroid Build Coastguard Worker for line in filp: 73*61046927SAndroid Build Coastguard Worker if not line.startswith('#define '): 74*61046927SAndroid Build Coastguard Worker continue 75*61046927SAndroid Build Coastguard Worker 76*61046927SAndroid Build Coastguard Worker line = line[8:].strip() 77*61046927SAndroid Build Coastguard Worker 78*61046927SAndroid Build Coastguard Worker comment = None 79*61046927SAndroid Build Coastguard Worker m = RE_comment.search(line) 80*61046927SAndroid Build Coastguard Worker if m is not None: 81*61046927SAndroid Build Coastguard Worker comment = m.group(2) or m.group(4) 82*61046927SAndroid Build Coastguard Worker comment = comment.strip() 83*61046927SAndroid Build Coastguard Worker line = line[:m.span()[0]].strip() 84*61046927SAndroid Build Coastguard Worker 85*61046927SAndroid Build Coastguard Worker split = line.split(None, 1) 86*61046927SAndroid Build Coastguard Worker name = split[0] 87*61046927SAndroid Build Coastguard Worker 88*61046927SAndroid Build Coastguard Worker m = RE_prefix.match(name) 89*61046927SAndroid Build Coastguard Worker if m is None: 90*61046927SAndroid Build Coastguard Worker continue 91*61046927SAndroid Build Coastguard Worker 92*61046927SAndroid Build Coastguard Worker prefix = m.group(1) 93*61046927SAndroid Build Coastguard Worker prefix_address = int(m.group(2), 16) 94*61046927SAndroid Build Coastguard Worker name = name[m.span()[1]:] 95*61046927SAndroid Build Coastguard Worker 96*61046927SAndroid Build Coastguard Worker if prefix == 'V': 97*61046927SAndroid Build Coastguard Worker value = int(split[1], 0) 98*61046927SAndroid Build Coastguard Worker 99*61046927SAndroid Build Coastguard Worker for entry in self.__enumentries: 100*61046927SAndroid Build Coastguard Worker if name == entry.name: 101*61046927SAndroid Build Coastguard Worker sys.exit('Duplicate value define: name = {0}'.format(name)) 102*61046927SAndroid Build Coastguard Worker 103*61046927SAndroid Build Coastguard Worker entry = Object(name=name, value=value) 104*61046927SAndroid Build Coastguard Worker if comment is not None: 105*61046927SAndroid Build Coastguard Worker entry.comment = comment 106*61046927SAndroid Build Coastguard Worker self.__enumentries.append(entry) 107*61046927SAndroid Build Coastguard Worker continue 108*61046927SAndroid Build Coastguard Worker 109*61046927SAndroid Build Coastguard Worker if prefix == 'S': 110*61046927SAndroid Build Coastguard Worker self.__fini_field() 111*61046927SAndroid Build Coastguard Worker 112*61046927SAndroid Build Coastguard Worker if not name.endswith('(x)'): 113*61046927SAndroid Build Coastguard Worker sys.exit('Missing (x) in S line: {0}'.line) 114*61046927SAndroid Build Coastguard Worker name = name[:-3] 115*61046927SAndroid Build Coastguard Worker 116*61046927SAndroid Build Coastguard Worker for field in self.__fields: 117*61046927SAndroid Build Coastguard Worker if name == field.name: 118*61046927SAndroid Build Coastguard Worker sys.exit('Duplicate field define: {0}'.format(name)) 119*61046927SAndroid Build Coastguard Worker 120*61046927SAndroid Build Coastguard Worker m = RE_set_value.match(split[1]) 121*61046927SAndroid Build Coastguard Worker if m is not None: 122*61046927SAndroid Build Coastguard Worker unshifted_mask = int(m.group(1), 0) 123*61046927SAndroid Build Coastguard Worker shift = int(m.group(2), 0) 124*61046927SAndroid Build Coastguard Worker else: 125*61046927SAndroid Build Coastguard Worker m = RE_set_value_no_shift.match(split[1]) 126*61046927SAndroid Build Coastguard Worker if m is not None: 127*61046927SAndroid Build Coastguard Worker unshifted_mask = int(m.group(2), 0) 128*61046927SAndroid Build Coastguard Worker shift = 0 129*61046927SAndroid Build Coastguard Worker else: 130*61046927SAndroid Build Coastguard Worker sys.exit('Bad S_xxx_xxx define: {0}'.format(line)) 131*61046927SAndroid Build Coastguard Worker 132*61046927SAndroid Build Coastguard Worker num_bits = int(math.log2(unshifted_mask + 1)) 133*61046927SAndroid Build Coastguard Worker if unshifted_mask != (1 << num_bits) - 1: 134*61046927SAndroid Build Coastguard Worker sys.exit('Bad unshifted mask in {0}'.format(line)) 135*61046927SAndroid Build Coastguard Worker 136*61046927SAndroid Build Coastguard Worker self.__field = Object( 137*61046927SAndroid Build Coastguard Worker name=name, 138*61046927SAndroid Build Coastguard Worker bits=[shift, shift + num_bits - 1], 139*61046927SAndroid Build Coastguard Worker ) 140*61046927SAndroid Build Coastguard Worker if comment is not None: 141*61046927SAndroid Build Coastguard Worker self.__field.comment = comment 142*61046927SAndroid Build Coastguard Worker self.__enumentries = [] 143*61046927SAndroid Build Coastguard Worker 144*61046927SAndroid Build Coastguard Worker if prefix == 'R': 145*61046927SAndroid Build Coastguard Worker self.__fini_field() 146*61046927SAndroid Build Coastguard Worker self.__fini_register() 147*61046927SAndroid Build Coastguard Worker 148*61046927SAndroid Build Coastguard Worker if regdb.register_mappings_by_name(name): 149*61046927SAndroid Build Coastguard Worker sys.exit('Duplicate register define: {0}'.format(name)) 150*61046927SAndroid Build Coastguard Worker 151*61046927SAndroid Build Coastguard Worker address = int(split[1], 0) 152*61046927SAndroid Build Coastguard Worker if address != prefix_address: 153*61046927SAndroid Build Coastguard Worker sys.exit('Inconsistent register address: {0}'.format(line)) 154*61046927SAndroid Build Coastguard Worker 155*61046927SAndroid Build Coastguard Worker self.__regmap = Object( 156*61046927SAndroid Build Coastguard Worker name=name, 157*61046927SAndroid Build Coastguard Worker chips=self.chips, 158*61046927SAndroid Build Coastguard Worker map=Object(to=self.address_space, at=address), 159*61046927SAndroid Build Coastguard Worker ) 160*61046927SAndroid Build Coastguard Worker self.__fields = [] 161*61046927SAndroid Build Coastguard Worker 162*61046927SAndroid Build Coastguard Worker self.__fini_field() 163*61046927SAndroid Build Coastguard Worker self.__fini_register() 164*61046927SAndroid Build Coastguard Worker 165*61046927SAndroid Build Coastguard Workerdef main(): 166*61046927SAndroid Build Coastguard Worker map_to = sys.argv[1] 167*61046927SAndroid Build Coastguard Worker 168*61046927SAndroid Build Coastguard Worker parser = HeaderParser(map_to) 169*61046927SAndroid Build Coastguard Worker parser.parse_header(sys.stdin) 170*61046927SAndroid Build Coastguard Worker 171*61046927SAndroid Build Coastguard Worker deduplicate_enums(parser.regdb) 172*61046927SAndroid Build Coastguard Worker deduplicate_register_types(parser.regdb) 173*61046927SAndroid Build Coastguard Worker 174*61046927SAndroid Build Coastguard Worker print(parser.regdb.encode_json_pretty()) 175*61046927SAndroid Build Coastguard Worker 176*61046927SAndroid Build Coastguard Worker 177*61046927SAndroid Build Coastguard Workerif __name__ == '__main__': 178*61046927SAndroid Build Coastguard Worker main() 179*61046927SAndroid Build Coastguard Worker 180*61046927SAndroid Build Coastguard Worker# kate: space-indent on; indent-width 4; replace-tabs on; 181