Path: blob/21.2-virgl/src/gallium/drivers/swr/rasterizer/codegen/gen_archrast.py
4574 views
# Copyright (C) 2014-2016 Intel Corporation. All Rights Reserved.1#2# Permission is hereby granted, free of charge, to any person obtaining a3# copy of this software and associated documentation files (the "Software"),4# to deal in the Software without restriction, including without limitation5# the rights to use, copy, modify, merge, publish, distribute, sublicense,6# and/or sell copies of the Software, and to permit persons to whom the7# Software is furnished to do so, subject to the following conditions:8#9# The above copyright notice and this permission notice (including the next10# paragraph) shall be included in all copies or substantial portions of the11# Software.12#13# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING18# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS19# IN THE SOFTWARE.2021# Python source22from __future__ import print_function23import os24import sys25import re26from gen_common import *2728def parse_event_fields(lines, idx, event_dict):29"""30Parses lines from a proto file that contain an event definition and stores it in event_dict31"""32fields = []33end_of_event = False3435# record all fields in event definition.36# note: we don't check if there's a leading brace.37while not end_of_event and idx < len(lines):38line = lines[idx].rstrip()39idx += 14041# ex 1: uint32_t numSampleCLZExecuted; // number of sample_cl_z instructions executed42# ex 2: char reason[256]; // size of reason43match = re.match(r'^(\s*)([\w\*]+)(\s+)([\w]+)(\[\d+\])*;\s*(\/\/.*)*$', line)44# group 1 -45# group 2 type46# group 3 -47# group 4 name48# group 5 [array size]49# group 6 //comment5051if match:52field = {53"type": match.group(2),54"name": match.group(4),55"size": int(match.group(5)[1:-1]) if match.group(5) else 1,56"desc": match.group(6)[2:].strip() if match.group(6) else "",57}58fields.append(field)5960end_of_event = re.match(r'(\s*)};', line)6162event_dict['fields'] = fields63event_dict['num_fields'] = len(fields)6465return idx6667def parse_enums(lines, idx, event_dict):68"""69Parses lines from a proto file that contain an enum definition and stores it in event_dict70"""71enum_names = []72end_of_enum = False7374# record all enum values in enumeration75# note: we don't check if there's a leading brace.76while not end_of_enum and idx < len(lines):77line = lines[idx].rstrip()78idx += 17980preprocessor = re.search(r'#if|#endif', line)8182if not preprocessor:83enum = re.match(r'(\s*)(\w+)(\s*)', line)8485if enum:86enum_names.append(line)8788end_of_enum = re.match(r'(\s*)};', line)8990event_dict['names'] = enum_names91return idx9293def parse_protos(files, verbose=False):94"""95Parses a proto file and returns a dictionary of event definitions96"""9798# Protos structure:99#100# {101# "events": {102# "defs": { // dict of event definitions where keys are 'group_name::event_name"103# ...,104# "ApiStat::DrawInfoEvent": {105# "id": 3,106# "group": "ApiStat",107# "name": "DrawInfoEvent", // name of event without 'group_name::' prefix108# "desc": "",109# "fields": [110# {111# "type": "uint32_t",112# "name": "drawId",113# "size": 1,114# "desc": "",115# },116# ...117# ]118# },119# ...120# },121# "groups": { // dict of groups with lists of event keys122# "ApiStat": [123# "ApiStat::DispatchEvent",124# "ApiStat::DrawInfoEvent",125# ...126# ],127# "Framework": [128# "Framework::ThreadStartApiEvent",129# "Framework::ThreadStartWorkerEvent",130# ...131# ],132# ...133# },134# "map": { // map of event ids to match archrast output to event key135# "1": "Framework::ThreadStartApiEvent",136# "2": "Framework::ThreadStartWorkerEvent",137# "3": "ApiStat::DrawInfoEvent",138# ...139# }140# },141# "enums": { ... } // enums follow similar defs, map (groups?) structure142# }143144protos = {145'events': {146'defs': {}, # event dictionary containing events with their fields147'map': {}, # dictionary to map event ids to event names148'groups': {} # event keys stored by groups149},150'enums': {151'defs': {},152'map': {}153}154}155156event_id = 0157enum_id = 0158159if type(files) is not list:160files = [files]161162for filename in files:163if verbose:164print("Parsing proto file: %s" % os.path.normpath(filename))165166with open(filename, 'r') as f:167lines = f.readlines()168in_brief = False169brief = []170idx = 0171while idx < len(lines):172line = lines[idx].strip()173idx += 1174175# If currently processing a brief, keep processing or change state176if in_brief:177match = re.match(r'^\s*\/\/\/\s*(.*)$', line) # i.e. "/// more event desc..."178if match:179brief.append(match.group(1).strip())180continue181else:182in_brief = False183184# Match event/enum brief185match = re.match(r'^\s*\/\/\/\s*@(brief|breif)\s*(.*)$', line) # i.e. "///@brief My event desc..."186if match:187in_brief = True188brief.append(match.group(2).strip())189continue190191# Match event definition192match = re.match(r'event(\s*)(((\w*)::){0,1}(\w+))', line) # i.e. "event SWTag::CounterEvent"193if match:194event_id += 1195196# Parse event attributes197event_key = match.group(2) # i.e. SWTag::CounterEvent198event_group = match.group(4) if match.group(4) else "" # i.e. SWTag199event_name = match.group(5) # i.e. CounterEvent200201# Define event attributes202event = {203'id': event_id,204'group': event_group,205'name': event_name,206'desc': ' '.join(brief)207}208# Add period at end of event desc if necessary209if event["desc"] and event["desc"][-1] != '.':210event["desc"] += '.'211212# Reset brief213brief = []214215# Now add event fields216idx = parse_event_fields(lines, idx, event)217218# Register event and mapping219protos['events']['defs'][event_key] = event220protos['events']['map'][event_id] = event_key221222continue223224# Match enum definition225match = re.match(r'enum(\s*)(\w+)', line)226if match:227enum_id += 1228229# Parse enum attributes230enum_name = match.group(2)231232# Define enum attr233enum = {234'name': enum_name,235'desc': ' '.join(brief)236}237# Add period at end of event desc if necessary238if enum["desc"] and enum["desc"][-1] != '.':239enum["desc"] += '.'240241# Reset brief242brief = []243244# Now add enum fields245idx = parse_enums(lines, idx, enum)246247# Register enum and mapping248protos['enums']['defs'][enum_name] = enum249protos['enums']['map'][enum_id] = enum_name250251continue252253# Sort and group events254event_groups = protos['events']['groups']255for key in sorted(protos['events']['defs']):256group = protos['events']['defs'][key]['group']257if group not in event_groups:258event_groups[group] = []259event_groups[group].append(key)260261return protos262263264def main():265266# Parse args...267parser = ArgumentParser()268parser.add_argument("--proto", "-p", dest="protos", nargs='+', help="Path to all proto file(s) to process. Accepts one or more paths (i.e. events.proto and events_private.proto)", required=True)269parser.add_argument("--output-dir", help="Output dir (defaults to ./codegen). Will create folder if it does not exist.", required=False, default="codegen")270parser.add_argument("--verbose", "-v", help="Verbose", action="store_true")271args = parser.parse_args()272273if not os.path.exists(args.output_dir):274MakeDir(args.output_dir)275276for f in args.protos:277if not os.path.exists(f):278print('Error: Could not find proto file %s' % f, file=sys.stderr)279return 1280281# Parse each proto file and add to protos container282protos = parse_protos(args.protos, args.verbose)283284files = [285["gen_ar_event.hpp", ""],286["gen_ar_event.cpp", ""],287["gen_ar_eventhandler.hpp", "gen_ar_event.hpp"],288["gen_ar_eventhandlerfile.hpp", "gen_ar_eventhandler.hpp"]289]290291rval = 0292293try:294# Delete existing files295for f in files:296filename = f[0]297output_fullpath = os.path.join(args.output_dir, filename)298if os.path.exists(output_fullpath):299if args.verbose:300print("Deleting existing file: %s" % output_fullpath)301os.remove(output_fullpath)302303# Generate files from templates304print("Generating c++ from proto files...")305for f in files:306filename = f[0]307event_header = f[1]308curdir = os.path.dirname(os.path.abspath(__file__))309template_file = os.path.join(curdir, 'templates', filename)310output_fullpath = os.path.join(args.output_dir, filename)311312if args.verbose:313print("Generating: %s" % output_fullpath)314MakoTemplateWriter.to_file(template_file, output_fullpath,315cmdline=sys.argv,316filename=filename,317protos=protos,318event_header=event_header)319320except Exception as e:321print(e)322rval = 1323324return rval325326if __name__ == '__main__':327sys.exit(main())328329330