Path: blob/21.2-virgl/src/intel/perf/gen_perf.py
4547 views
# Copyright (c) 2015-2017 Intel Corporation1#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.2021import argparse22import os23import sys24import textwrap2526import xml.etree.ElementTree as et2728hashed_funcs = {}2930c_file = None31_c_indent = 03233def c(*args):34code = ' '.join(map(str,args))35for line in code.splitlines():36text = ''.rjust(_c_indent) + line37c_file.write(text.rstrip() + "\n")3839# indented, but no trailing newline...40def c_line_start(code):41c_file.write(''.rjust(_c_indent) + code)42def c_raw(code):43c_file.write(code)4445def c_indent(n):46global _c_indent47_c_indent = _c_indent + n48def c_outdent(n):49global _c_indent50_c_indent = _c_indent - n5152header_file = None53_h_indent = 05455def h(*args):56code = ' '.join(map(str,args))57for line in code.splitlines():58text = ''.rjust(_h_indent) + line59header_file.write(text.rstrip() + "\n")6061def h_indent(n):62global _c_indent63_h_indent = _h_indent + n64def h_outdent(n):65global _c_indent66_h_indent = _h_indent - n676869def emit_fadd(tmp_id, args):70c("double tmp{0} = {1} + {2};".format(tmp_id, args[1], args[0]))71return tmp_id + 17273# Be careful to check for divide by zero...74def emit_fdiv(tmp_id, args):75c("double tmp{0} = {1};".format(tmp_id, args[1]))76c("double tmp{0} = {1};".format(tmp_id + 1, args[0]))77c("double tmp{0} = tmp{1} ? tmp{2} / tmp{1} : 0;".format(tmp_id + 2, tmp_id + 1, tmp_id))78return tmp_id + 37980def emit_fmax(tmp_id, args):81c("double tmp{0} = {1};".format(tmp_id, args[1]))82c("double tmp{0} = {1};".format(tmp_id + 1, args[0]))83c("double tmp{0} = MAX(tmp{1}, tmp{2});".format(tmp_id + 2, tmp_id, tmp_id + 1))84return tmp_id + 38586def emit_fmul(tmp_id, args):87c("double tmp{0} = {1} * {2};".format(tmp_id, args[1], args[0]))88return tmp_id + 18990def emit_fsub(tmp_id, args):91c("double tmp{0} = {1} - {2};".format(tmp_id, args[1], args[0]))92return tmp_id + 19394def emit_read(tmp_id, args):95type = args[1].lower()96c("uint64_t tmp{0} = results->accumulator[query->{1}_offset + {2}];".format(tmp_id, type, args[0]))97return tmp_id + 19899def emit_uadd(tmp_id, args):100c("uint64_t tmp{0} = {1} + {2};".format(tmp_id, args[1], args[0]))101return tmp_id + 1102103# Be careful to check for divide by zero...104def emit_udiv(tmp_id, args):105c("uint64_t tmp{0} = {1};".format(tmp_id, args[1]))106c("uint64_t tmp{0} = {1};".format(tmp_id + 1, args[0]))107if args[0].isdigit():108assert int(args[0]) > 0109c("uint64_t tmp{0} = tmp{2} / tmp{1};".format(tmp_id + 2, tmp_id + 1, tmp_id))110else:111c("uint64_t tmp{0} = tmp{1} ? tmp{2} / tmp{1} : 0;".format(tmp_id + 2, tmp_id + 1, tmp_id))112return tmp_id + 3113114def emit_umul(tmp_id, args):115c("uint64_t tmp{0} = {1} * {2};".format(tmp_id, args[1], args[0]))116return tmp_id + 1117118def emit_usub(tmp_id, args):119c("uint64_t tmp{0} = {1} - {2};".format(tmp_id, args[1], args[0]))120return tmp_id + 1121122def emit_umin(tmp_id, args):123c("uint64_t tmp{0} = MIN({1}, {2});".format(tmp_id, args[1], args[0]))124return tmp_id + 1125126def emit_lshft(tmp_id, args):127c("uint64_t tmp{0} = {1} << {2};".format(tmp_id, args[1], args[0]))128return tmp_id + 1129130def emit_rshft(tmp_id, args):131c("uint64_t tmp{0} = {1} >> {2};".format(tmp_id, args[1], args[0]))132return tmp_id + 1133134def emit_and(tmp_id, args):135c("uint64_t tmp{0} = {1} & {2};".format(tmp_id, args[1], args[0]))136return tmp_id + 1137138ops = {}139# (n operands, emitter)140ops["FADD"] = (2, emit_fadd)141ops["FDIV"] = (2, emit_fdiv)142ops["FMAX"] = (2, emit_fmax)143ops["FMUL"] = (2, emit_fmul)144ops["FSUB"] = (2, emit_fsub)145ops["READ"] = (2, emit_read)146ops["UADD"] = (2, emit_uadd)147ops["UDIV"] = (2, emit_udiv)148ops["UMUL"] = (2, emit_umul)149ops["USUB"] = (2, emit_usub)150ops["UMIN"] = (2, emit_umin)151ops["<<"] = (2, emit_lshft)152ops[">>"] = (2, emit_rshft)153ops["AND"] = (2, emit_and)154155def brkt(subexp):156if " " in subexp:157return "(" + subexp + ")"158else:159return subexp160161def splice_bitwise_and(args):162return brkt(args[1]) + " & " + brkt(args[0])163164def splice_logical_and(args):165return brkt(args[1]) + " && " + brkt(args[0])166167def splice_ult(args):168return brkt(args[1]) + " < " + brkt(args[0])169170def splice_ugte(args):171return brkt(args[1]) + " >= " + brkt(args[0])172173exp_ops = {}174# (n operands, splicer)175exp_ops["AND"] = (2, splice_bitwise_and)176exp_ops["UGTE"] = (2, splice_ugte)177exp_ops["ULT"] = (2, splice_ult)178exp_ops["&&"] = (2, splice_logical_and)179180181hw_vars = {}182hw_vars["$EuCoresTotalCount"] = "perf->sys_vars.n_eus"183hw_vars["$EuSlicesTotalCount"] = "perf->sys_vars.n_eu_slices"184hw_vars["$EuSubslicesTotalCount"] = "perf->sys_vars.n_eu_sub_slices"185hw_vars["$EuThreadsCount"] = "perf->sys_vars.eu_threads_count"186hw_vars["$SliceMask"] = "perf->sys_vars.slice_mask"187# subslice_mask is interchangeable with subslice/dual-subslice since Gfx12+188# only has dual subslices which can be assimilated with 16EUs subslices.189hw_vars["$SubsliceMask"] = "perf->sys_vars.subslice_mask"190hw_vars["$DualSubsliceMask"] = "perf->sys_vars.subslice_mask"191hw_vars["$GpuTimestampFrequency"] = "perf->sys_vars.timestamp_frequency"192hw_vars["$GpuMinFrequency"] = "perf->sys_vars.gt_min_freq"193hw_vars["$GpuMaxFrequency"] = "perf->sys_vars.gt_max_freq"194hw_vars["$SkuRevisionId"] = "perf->sys_vars.revision"195hw_vars["$QueryMode"] = "perf->sys_vars.query_mode"196197def output_rpn_equation_code(set, counter, equation):198c("/* RPN equation: " + equation + " */")199tokens = equation.split()200stack = []201tmp_id = 0202tmp = None203204for token in tokens:205stack.append(token)206while stack and stack[-1] in ops:207op = stack.pop()208argc, callback = ops[op]209args = []210for i in range(0, argc):211operand = stack.pop()212if operand[0] == "$":213if operand in hw_vars:214operand = hw_vars[operand]215elif operand in set.counter_vars:216reference = set.counter_vars[operand]217operand = set.read_funcs[operand[1:]] + "(perf, query, results)"218else:219raise Exception("Failed to resolve variable " + operand + " in equation " + equation + " for " + set.name + " :: " + counter.get('name'));220args.append(operand)221222tmp_id = callback(tmp_id, args)223224tmp = "tmp{0}".format(tmp_id - 1)225stack.append(tmp)226227if len(stack) != 1:228raise Exception("Spurious empty rpn code for " + set.name + " :: " +229counter.get('name') + ".\nThis is probably due to some unhandled RPN function, in the equation \"" +230equation + "\"")231232value = stack[-1]233234if value in hw_vars:235value = hw_vars[value]236if value in set.counter_vars:237value = set.read_funcs[value[1:]] + "(perf, query, results)"238239c("\nreturn " + value + ";")240241def splice_rpn_expression(set, counter, expression):242tokens = expression.split()243stack = []244245for token in tokens:246stack.append(token)247while stack and stack[-1] in exp_ops:248op = stack.pop()249argc, callback = exp_ops[op]250args = []251for i in range(0, argc):252operand = stack.pop()253if operand[0] == "$":254if operand in hw_vars:255operand = hw_vars[operand]256else:257raise Exception("Failed to resolve variable " + operand + " in expression " + expression + " for " + set.name + " :: " + counter.get('name'));258args.append(operand)259260subexp = callback(args)261262stack.append(subexp)263264if len(stack) != 1:265raise Exception("Spurious empty rpn expression for " + set.name + " :: " +266counter.get('name') + ".\nThis is probably due to some unhandled RPN operation, in the expression \"" +267expression + "\"")268269return stack[-1]270271def output_counter_read(gen, set, counter):272c("\n")273c("/* {0} :: {1} */".format(set.name, counter.get('name')))274275if counter.read_hash in hashed_funcs:276c("#define %s \\" % counter.read_sym)277c_indent(3)278c("%s" % hashed_funcs[counter.read_hash])279c_outdent(3)280else:281ret_type = counter.get('data_type')282if ret_type == "uint64":283ret_type = "uint64_t"284285read_eq = counter.get('equation')286287c("static " + ret_type)288c(counter.read_sym + "(UNUSED struct intel_perf_config *perf,\n")289c_indent(len(counter.read_sym) + 1)290c("const struct intel_perf_query_info *query,\n")291c("const struct intel_perf_query_result *results)\n")292c_outdent(len(counter.read_sym) + 1)293294c("{")295c_indent(3)296output_rpn_equation_code(set, counter, read_eq)297c_outdent(3)298c("}")299300hashed_funcs[counter.read_hash] = counter.read_sym301302303def output_counter_max(gen, set, counter):304max_eq = counter.get('max_equation')305306if not counter.has_max_func():307return308309c("\n")310c("/* {0} :: {1} */".format(set.name, counter.get('name')))311312if counter.max_hash in hashed_funcs:313c("#define %s \\" % counter.max_sym())314c_indent(3)315c("%s" % hashed_funcs[counter.max_hash])316c_outdent(3)317else:318ret_type = counter.get('data_type')319if ret_type == "uint64":320ret_type = "uint64_t"321322c("static " + ret_type)323c(counter.max_sym() + "(struct intel_perf_config *perf)\n")324c("{")325c_indent(3)326output_rpn_equation_code(set, counter, max_eq)327c_outdent(3)328c("}")329330hashed_funcs[counter.max_hash] = counter.max_sym()331332333c_type_sizes = { "uint32_t": 4, "uint64_t": 8, "float": 4, "double": 8, "bool": 4 }334def sizeof(c_type):335return c_type_sizes[c_type]336337def pot_align(base, pot_alignment):338return (base + pot_alignment - 1) & ~(pot_alignment - 1);339340semantic_type_map = {341"duration": "raw",342"ratio": "event"343}344345def output_availability(set, availability, counter_name):346expression = splice_rpn_expression(set, counter_name, availability)347lines = expression.split(' && ')348n_lines = len(lines)349if n_lines == 1:350c("if (" + lines[0] + ") {")351else:352c("if (" + lines[0] + " &&")353c_indent(4)354for i in range(1, (n_lines - 1)):355c(lines[i] + " &&")356c(lines[(n_lines - 1)] + ") {")357c_outdent(4)358359360def output_units(unit):361return unit.replace(' ', '_').upper()362363364# should a unit be visible in description?365units_map = {366"bytes" : True,367"cycles" : True,368"eu atomic requests to l3 cache lines" : False,369"eu bytes per l3 cache line" : False,370"eu requests to l3 cache lines" : False,371"eu sends to l3 cache lines" : False,372"events" : True,373"hz" : True,374"messages" : True,375"ns" : True,376"number" : False,377"percent" : True,378"pixels" : True,379"texels" : True,380"threads" : True,381"us" : True,382"utilization" : False,383}384385386def desc_units(unit):387val = units_map.get(unit)388if val is None:389raise Exception("Unknown unit: " + unit)390if val == False:391return ""392if unit == 'hz':393unit = 'Hz'394return " Unit: " + unit + "."395396397def output_counter_report(set, counter, current_offset):398data_type = counter.get('data_type')399data_type_uc = data_type.upper()400c_type = data_type401402if "uint" in c_type:403c_type = c_type + "_t"404405semantic_type = counter.get('semantic_type')406if semantic_type in semantic_type_map:407semantic_type = semantic_type_map[semantic_type]408409semantic_type_uc = semantic_type.upper()410411c("\n")412413availability = counter.get('availability')414if availability:415output_availability(set, availability, counter.get('name'))416c_indent(3)417418c("counter = &query->counters[query->n_counters++];\n")419c("counter->oa_counter_read_" + data_type + " = " + set.read_funcs[counter.get('symbol_name')] + ";\n")420c("counter->name = \"" + counter.get('name') + "\";\n")421c("counter->desc = \"" + counter.get('description') + desc_units(counter.get('units')) + "\";\n")422c("counter->symbol_name = \"" + counter.get('symbol_name') + "\";\n")423c("counter->category = \"" + counter.get('mdapi_group') + "\";\n")424c("counter->type = INTEL_PERF_COUNTER_TYPE_" + semantic_type_uc + ";\n")425c("counter->data_type = INTEL_PERF_COUNTER_DATA_TYPE_" + data_type_uc + ";\n")426c("counter->units = INTEL_PERF_COUNTER_UNITS_" + output_units(counter.get('units')) + ";\n")427c("counter->raw_max = " + set.max_values[counter.get('symbol_name')] + ";\n")428429current_offset = pot_align(current_offset, sizeof(c_type))430c("counter->offset = " + str(current_offset) + ";\n")431432if availability:433c_outdent(3);434c("}")435436return current_offset + sizeof(c_type)437438439register_types = {440'FLEX': 'flex_regs',441'NOA': 'mux_regs',442'OA': 'b_counter_regs',443}444445def compute_register_lengths(set):446register_lengths = {}447register_configs = set.findall('register_config')448for register_config in register_configs:449t = register_types[register_config.get('type')]450if t not in register_lengths:451register_lengths[t] = len(register_config.findall('register'))452else:453register_lengths[t] += len(register_config.findall('register'))454455return register_lengths456457458def generate_register_configs(set):459register_configs = set.findall('register_config')460461for register_config in register_configs:462t = register_types[register_config.get('type')]463464availability = register_config.get('availability')465if availability:466output_availability(set, availability, register_config.get('type') + ' register config')467c_indent(3)468469registers = register_config.findall('register')470c("static const struct intel_perf_query_register_prog %s[] = {" % t)471c_indent(3)472for register in registers:473c("{ .reg = %s, .val = %s }," % (register.get('address'), register.get('value')))474c_outdent(3)475c("};")476c("query->config.%s = %s;" % (t, t))477c("query->config.n_%s = ARRAY_SIZE(%s);" % (t, t))478479if availability:480c_outdent(3)481c("}")482c("\n")483484485# Wraps a <counter> element from the oa-*.xml files.486class Counter:487def __init__(self, set, xml):488self.xml = xml489self.set = set490self.read_hash = None491self.max_hash = None492493self.read_sym = "{0}__{1}__{2}__read".format(self.set.gen.chipset,494self.set.underscore_name,495self.xml.get('underscore_name'))496497def get(self, prop):498return self.xml.get(prop)499500# Compute the hash of a counter's equation by expanding (including all the501# sub-equations it depends on)502def compute_hashes(self):503if self.read_hash is not None:504return505506def replace_token(token):507if token[0] != "$":508return token509if token not in self.set.counter_vars:510return token511self.set.counter_vars[token].compute_hashes()512return self.set.counter_vars[token].read_hash513514read_eq = self.xml.get('equation')515self.read_hash = ' '.join(map(replace_token, read_eq.split()))516517max_eq = self.xml.get('max_equation')518if max_eq:519self.max_hash = ' '.join(map(replace_token, max_eq.split()))520521def has_max_func(self):522max_eq = self.xml.get('max_equation')523if not max_eq:524return False525526try:527val = float(max_eq)528return False529except ValueError:530pass531532for token in max_eq.split():533if token[0] == '$' and token not in hw_vars:534return False535return True536537def max_sym(self):538assert self.has_max_func()539return "{0}__{1}__{2}__max".format(self.set.gen.chipset,540self.set.underscore_name,541self.xml.get('underscore_name'))542543def max_value(self):544max_eq = self.xml.get('max_equation')545if not max_eq:546return "0 /* undefined */"547548try:549return "{0}".format(float(max_eq))550except ValueError:551pass552553for token in max_eq.split():554if token[0] == '$' and token not in hw_vars:555return "0 /* unsupported (varies over time) */"556557return "{0}__{1}__{2}__max(perf)".format(self.set.gen.chipset,558self.set.underscore_name,559self.xml.get('underscore_name'))560561# Wraps a <set> element from the oa-*.xml files.562class Set:563def __init__(self, gen, xml):564self.gen = gen565self.xml = xml566567self.counter_vars = {}568self.max_values = {}569self.read_funcs = {}570571xml_counters = self.xml.findall("counter")572self.counters = []573for xml_counter in xml_counters:574counter = Counter(self, xml_counter)575self.counters.append(counter)576self.counter_vars["$" + counter.get('symbol_name')] = counter577self.read_funcs[counter.get('symbol_name')] = counter.read_sym578self.max_values[counter.get('symbol_name')] = counter.max_value()579580for counter in self.counters:581counter.compute_hashes()582583@property584def hw_config_guid(self):585return self.xml.get('hw_config_guid')586587@property588def name(self):589return self.xml.get('name')590591@property592def symbol_name(self):593return self.xml.get('symbol_name')594595@property596def underscore_name(self):597return self.xml.get('underscore_name')598599def findall(self, path):600return self.xml.findall(path)601602def find(self, path):603return self.xml.find(path)604605606# Wraps an entire oa-*.xml file.607class Gen:608def __init__(self, filename):609self.filename = filename610self.xml = et.parse(self.filename)611self.chipset = self.xml.find('.//set').get('chipset').lower()612self.sets = []613614for xml_set in self.xml.findall(".//set"):615self.sets.append(Set(self, xml_set))616617618def main():619global c_file620global header_file621622parser = argparse.ArgumentParser()623parser.add_argument("--header", help="Header file to write", required=True)624parser.add_argument("--code", help="C file to write", required=True)625parser.add_argument("xml_files", nargs='+', help="List of xml metrics files to process")626627args = parser.parse_args()628629c_file = open(args.code, 'w')630header_file = open(args.header, 'w')631632gens = []633for xml_file in args.xml_files:634gens.append(Gen(xml_file))635636637copyright = textwrap.dedent("""\638/* Autogenerated file, DO NOT EDIT manually! generated by {}639*640* Copyright (c) 2015 Intel Corporation641*642* Permission is hereby granted, free of charge, to any person obtaining a643* copy of this software and associated documentation files (the "Software"),644* to deal in the Software without restriction, including without limitation645* the rights to use, copy, modify, merge, publish, distribute, sublicense,646* and/or sell copies of the Software, and to permit persons to whom the647* Software is furnished to do so, subject to the following conditions:648*649* The above copyright notice and this permission notice (including the next650* paragraph) shall be included in all copies or substantial portions of the651* Software.652*653* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR654* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,655* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL656* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER657* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING658* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER659* DEALINGS IN THE SOFTWARE.660*/661662""").format(os.path.basename(__file__))663664h(copyright)665h(textwrap.dedent("""\666#pragma once667668struct intel_perf_config;669670"""))671672c(copyright)673c(textwrap.dedent("""\674#include <stdint.h>675#include <stdbool.h>676677#include <drm-uapi/i915_drm.h>678679#include "util/hash_table.h"680#include "util/ralloc.h"681682"""))683684c("#include \"" + os.path.basename(args.header) + "\"")685686c(textwrap.dedent("""\687#include "perf/intel_perf.h"688689690#define MIN(a, b) ((a < b) ? (a) : (b))691#define MAX(a, b) ((a > b) ? (a) : (b))692693694"""))695696# Print out all equation functions.697for gen in gens:698for set in gen.sets:699for counter in set.counters:700output_counter_read(gen, set, counter)701output_counter_max(gen, set, counter)702703# Print out all metric sets registration functions for each set in each704# generation.705for gen in gens:706for set in gen.sets:707counters = set.counters708709c("\n")710c("\nstatic void\n")711c("{0}_register_{1}_counter_query(struct intel_perf_config *perf)\n".format(gen.chipset, set.underscore_name))712c("{\n")713c_indent(3)714715c("struct intel_perf_query_info *query = rzalloc(perf, struct intel_perf_query_info);\n")716c("\n")717c("query->perf = perf;\n")718c("query->kind = INTEL_PERF_QUERY_TYPE_OA;\n")719c("query->name = \"" + set.name + "\";\n")720c("query->symbol_name = \"" + set.symbol_name + "\";\n")721c("query->guid = \"" + set.hw_config_guid + "\";\n")722723c("query->counters = rzalloc_array(query, struct intel_perf_query_counter, %u);" % len(counters))724c("query->n_counters = 0;")725c("query->oa_metrics_set_id = 0; /* determined at runtime, via sysfs */")726727if gen.chipset == "hsw":728c(textwrap.dedent("""\729query->oa_format = I915_OA_FORMAT_A45_B8_C8;730/* Accumulation buffer offsets... */731query->gpu_time_offset = 0;732query->a_offset = query->gpu_time_offset + 1;733query->b_offset = query->a_offset + 45;734query->c_offset = query->b_offset + 8;735query->perfcnt_offset = query->c_offset + 8;736query->rpstat_offset = query->perfcnt_offset + 2;737"""))738else:739c(textwrap.dedent("""\740query->oa_format = I915_OA_FORMAT_A32u40_A4u32_B8_C8;741/* Accumulation buffer offsets... */742query->gpu_time_offset = 0;743query->gpu_clock_offset = query->gpu_time_offset + 1;744query->a_offset = query->gpu_clock_offset + 1;745query->b_offset = query->a_offset + 36;746query->c_offset = query->b_offset + 8;747query->perfcnt_offset = query->c_offset + 8;748query->rpstat_offset = query->perfcnt_offset + 2;749"""))750751752c("\n")753c("struct intel_perf_query_counter *counter = query->counters;\n")754755c("\n")756c("/* Note: we're assuming there can't be any variation in the definition ")757c(" * of a query between contexts so it's ok to describe a query within a ")758c(" * global variable which only needs to be initialized once... */")759c("\nif (!query->data_size) {")760c_indent(3)761762generate_register_configs(set)763764offset = 0765for counter in counters:766offset = output_counter_report(set, counter, offset)767768769c("\nquery->data_size = counter->offset + intel_perf_query_counter_get_size(counter);\n")770771c_outdent(3)772c("}");773774c("\n_mesa_hash_table_insert(perf->oa_metrics_table, query->guid, query);")775776c_outdent(3)777c("}\n")778779h("void intel_oa_register_queries_" + gen.chipset + "(struct intel_perf_config *perf);\n")780781c("\nvoid")782c("intel_oa_register_queries_" + gen.chipset + "(struct intel_perf_config *perf)")783c("{")784c_indent(3)785786for set in gen.sets:787c("{0}_register_{1}_counter_query(perf);".format(gen.chipset, set.underscore_name))788789c_outdent(3)790c("}")791792793if __name__ == '__main__':794main()795796797