1#!/usr/bin/env python3 2# 3# © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 4# 5# SPDX-License-Identifier: BSD-3-Clause 6 7from Cheetah.Template import Template 8 9import argparse 10import itertools 11import subprocess 12import logging 13import sys 14 15logger = logging.getLogger(__name__) 16 17valid_access_strs = \ 18 set([''.join(x) for x in itertools.chain.from_iterable( 19 itertools.combinations('oOrwRW', r) for r in range(1, 6))]) 20 21 22class register: 23 def __init__(self, name, type_name, variants=[], access='rw'): 24 if access in ['o', 'O']: 25 access += 'rw' 26 if access not in valid_access_strs: 27 logger.error("Invalid access type '%s'", access) 28 sys.exit(1) 29 self.name = name 30 self.type_name = type_name 31 self._variants = variants 32 self._read = 'r' in access 33 self._write = 'w' in access 34 self._volatile_read = 'R' in access 35 self._barrier_write = 'W' in access 36 self._ordered = 'O' in access 37 self._non_ordered = 'o' in access or 'O' not in access 38 39 @property 40 def variants(self): 41 ret = [] 42 type_name = self.type_name[:-1] if self.type_name.endswith( 43 '!') else self.type_name 44 45 for v in self._variants: 46 if v.endswith('!'): 47 ret.append((v[:-1], 48 type_name if self.type_name.endswith( 49 '!') else v[:-1])) 50 else: 51 ret.append(('_'.join((self.name, v)), 52 type_name if self.type_name.endswith( 53 '!') else '_'.join((type_name, v)))) 54 55 if not ret: 56 ret = [(self.name, type_name)] 57 return sorted(ret) 58 59 @property 60 def is_readable(self): 61 return self._read 62 63 @property 64 def is_volatile(self): 65 return self._volatile_read 66 67 @property 68 def is_writable(self): 69 return self._write 70 71 @property 72 def is_writeable_barrier(self): 73 return self._barrier_write 74 75 @property 76 def need_ordered(self): 77 return self._ordered 78 79 @property 80 def need_non_ordered(self): 81 return self._non_ordered 82 83 84def generate_accessors(template, input, ns): 85 registers = {} 86 87 for line in input.splitlines(): 88 if line.startswith('//'): 89 continue 90 tokens = line.split(maxsplit=1) 91 if not tokens: 92 continue 93 name = tokens[0] 94 if name in registers: 95 raise Exception("duplicate register:", name) 96 97 if len(tokens) == 1: 98 registers[name] = register(name, name) 99 continue 100 args = tokens[1] 101 102 type_name = name 103 if args.startswith('<'): 104 type_name, args = args[1:].split('>', maxsplit=1) 105 args = args.strip() 106 107 identifiers = [] 108 if args.startswith('['): 109 identifiers, args = args[1:].split(']', maxsplit=1) 110 identifiers = identifiers.split() 111 args = args.strip() 112 113 if args: 114 registers[name] = register(name, type_name, identifiers, args) 115 else: 116 registers[name] = register(name, type_name, identifiers) 117 118 ns['registers'] = [registers[r] for r in sorted(registers.keys())] 119 120 output = str(Template(file=template, searchList=ns)) 121 122 return output 123 124 125def main(): 126 logging.basicConfig( 127 level=logging.INFO, 128 format="%(message)s", 129 ) 130 131 args = argparse.ArgumentParser() 132 133 mode_args = args.add_mutually_exclusive_group(required=True) 134 mode_args.add_argument('-t', '--template', 135 type=argparse.FileType('r', encoding="utf-8"), 136 help="Template file used to generate output") 137 138 args.add_argument('-o', '--output', 139 type=argparse.FileType('w', encoding="utf-8"), 140 default=sys.stdout, help="Write output to file") 141 args.add_argument("-f", "--formatter", 142 help="specify clang-format to format the code") 143 args.add_argument("input", metavar='INPUT', nargs='*', 144 help="Input type register file to process", 145 type=argparse.FileType('r', encoding="utf-8")) 146 options = args.parse_args() 147 148 output = "" 149 150 input = "" 151 for f in options.input: 152 input += f.read() 153 f.close() 154 155 output += generate_accessors(options.template, input, {}) 156 157 if options.formatter: 158 ret = subprocess.run([options.formatter], input=output.encode("utf-8"), 159 stdout=subprocess.PIPE) 160 output = ret.stdout.decode("utf-8") 161 if ret.returncode != 0: 162 raise Exception("failed to format output:\n ", ret.stderr) 163 164 options.output.write(output) 165 166 167if __name__ == '__main__': 168 main() 169