1# Copyright (c) 2015-2017 Intel Corporation 2# 3# Permission is hereby granted, free of charge, to any person obtaining a 4# copy of this software and associated documentation files (the "Software"), 5# to deal in the Software without restriction, including without limitation 6# the rights to use, copy, modify, merge, publish, distribute, sublicense, 7# and/or sell copies of the Software, and to permit persons to whom the 8# Software is furnished to do so, subject to the following conditions: 9# 10# The above copyright notice and this permission notice (including the next 11# paragraph) shall be included in all copies or substantial portions of the 12# Software. 13# 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20# IN THE SOFTWARE. 21 22import argparse 23import os 24import sys 25import textwrap 26 27import xml.etree.ElementTree as et 28 29hashed_funcs = {} 30 31c_file = None 32_c_indent = 0 33 34def c(*args): 35 code = ' '.join(map(str,args)) 36 for line in code.splitlines(): 37 text = ''.rjust(_c_indent) + line 38 c_file.write(text.rstrip() + "\n") 39 40# indented, but no trailing newline... 41def c_line_start(code): 42 c_file.write(''.rjust(_c_indent) + code) 43def c_raw(code): 44 c_file.write(code) 45 46def c_indent(n): 47 global _c_indent 48 _c_indent = _c_indent + n 49def c_outdent(n): 50 global _c_indent 51 _c_indent = _c_indent - n 52 53header_file = None 54_h_indent = 0 55 56def h(*args): 57 code = ' '.join(map(str,args)) 58 for line in code.splitlines(): 59 text = ''.rjust(_h_indent) + line 60 header_file.write(text.rstrip() + "\n") 61 62def h_indent(n): 63 global _c_indent 64 _h_indent = _h_indent + n 65def h_outdent(n): 66 global _c_indent 67 _h_indent = _h_indent - n 68 69 70def emit_fadd(tmp_id, args): 71 c("double tmp{0} = {1} + {2};".format(tmp_id, args[1], args[0])) 72 return tmp_id + 1 73 74# Be careful to check for divide by zero... 75def emit_fdiv(tmp_id, args): 76 c("double tmp{0} = {1};".format(tmp_id, args[1])) 77 c("double tmp{0} = {1};".format(tmp_id + 1, args[0])) 78 c("double tmp{0} = tmp{1} ? tmp{2} / tmp{1} : 0;".format(tmp_id + 2, tmp_id + 1, tmp_id)) 79 return tmp_id + 3 80 81def emit_fmax(tmp_id, args): 82 c("double tmp{0} = {1};".format(tmp_id, args[1])) 83 c("double tmp{0} = {1};".format(tmp_id + 1, args[0])) 84 c("double tmp{0} = MAX(tmp{1}, tmp{2});".format(tmp_id + 2, tmp_id, tmp_id + 1)) 85 return tmp_id + 3 86 87def emit_fmul(tmp_id, args): 88 c("double tmp{0} = {1} * {2};".format(tmp_id, args[1], args[0])) 89 return tmp_id + 1 90 91def emit_fsub(tmp_id, args): 92 c("double tmp{0} = {1} - {2};".format(tmp_id, args[1], args[0])) 93 return tmp_id + 1 94 95def emit_read(tmp_id, args): 96 type = args[1].lower() 97 c("uint64_t tmp{0} = accumulator[query->{1}_offset + {2}];".format(tmp_id, type, args[0])) 98 return tmp_id + 1 99 100def emit_uadd(tmp_id, args): 101 c("uint64_t tmp{0} = {1} + {2};".format(tmp_id, args[1], args[0])) 102 return tmp_id + 1 103 104# Be careful to check for divide by zero... 105def emit_udiv(tmp_id, args): 106 c("uint64_t tmp{0} = {1};".format(tmp_id, args[1])) 107 c("uint64_t tmp{0} = {1};".format(tmp_id + 1, args[0])) 108 if args[0].isdigit(): 109 assert int(args[0]) > 0 110 c("uint64_t tmp{0} = tmp{2} / tmp{1};".format(tmp_id + 2, tmp_id + 1, tmp_id)) 111 else: 112 c("uint64_t tmp{0} = tmp{1} ? tmp{2} / tmp{1} : 0;".format(tmp_id + 2, tmp_id + 1, tmp_id)) 113 return tmp_id + 3 114 115def emit_umul(tmp_id, args): 116 c("uint64_t tmp{0} = {1} * {2};".format(tmp_id, args[1], args[0])) 117 return tmp_id + 1 118 119def emit_usub(tmp_id, args): 120 c("uint64_t tmp{0} = {1} - {2};".format(tmp_id, args[1], args[0])) 121 return tmp_id + 1 122 123def emit_umin(tmp_id, args): 124 c("uint64_t tmp{0} = MIN({1}, {2});".format(tmp_id, args[1], args[0])) 125 return tmp_id + 1 126 127def emit_lshft(tmp_id, args): 128 c("uint64_t tmp{0} = {1} << {2};".format(tmp_id, args[1], args[0])) 129 return tmp_id + 1 130 131def emit_rshft(tmp_id, args): 132 c("uint64_t tmp{0} = {1} >> {2};".format(tmp_id, args[1], args[0])) 133 return tmp_id + 1 134 135def emit_and(tmp_id, args): 136 c("uint64_t tmp{0} = {1} & {2};".format(tmp_id, args[1], args[0])) 137 return tmp_id + 1 138 139ops = {} 140# (n operands, emitter) 141ops["FADD"] = (2, emit_fadd) 142ops["FDIV"] = (2, emit_fdiv) 143ops["FMAX"] = (2, emit_fmax) 144ops["FMUL"] = (2, emit_fmul) 145ops["FSUB"] = (2, emit_fsub) 146ops["READ"] = (2, emit_read) 147ops["UADD"] = (2, emit_uadd) 148ops["UDIV"] = (2, emit_udiv) 149ops["UMUL"] = (2, emit_umul) 150ops["USUB"] = (2, emit_usub) 151ops["UMIN"] = (2, emit_umin) 152ops["<<"] = (2, emit_lshft) 153ops[">>"] = (2, emit_rshft) 154ops["AND"] = (2, emit_and) 155 156def brkt(subexp): 157 if " " in subexp: 158 return "(" + subexp + ")" 159 else: 160 return subexp 161 162def splice_bitwise_and(args): 163 return brkt(args[1]) + " & " + brkt(args[0]) 164 165def splice_logical_and(args): 166 return brkt(args[1]) + " && " + brkt(args[0]) 167 168def splice_ult(args): 169 return brkt(args[1]) + " < " + brkt(args[0]) 170 171def splice_ugte(args): 172 return brkt(args[1]) + " >= " + brkt(args[0]) 173 174exp_ops = {} 175# (n operands, splicer) 176exp_ops["AND"] = (2, splice_bitwise_and) 177exp_ops["UGTE"] = (2, splice_ugte) 178exp_ops["ULT"] = (2, splice_ult) 179exp_ops["&&"] = (2, splice_logical_and) 180 181 182hw_vars = {} 183hw_vars["$EuCoresTotalCount"] = "perf->sys_vars.n_eus" 184hw_vars["$EuSlicesTotalCount"] = "perf->sys_vars.n_eu_slices" 185hw_vars["$EuSubslicesTotalCount"] = "perf->sys_vars.n_eu_sub_slices" 186hw_vars["$EuThreadsCount"] = "perf->sys_vars.eu_threads_count" 187hw_vars["$SliceMask"] = "perf->sys_vars.slice_mask" 188# subslice_mask is interchangeable with subslice/dual-subslice since Gen12+ 189# only has dual subslices which can be assimilated with 16EUs subslices. 190hw_vars["$SubsliceMask"] = "perf->sys_vars.subslice_mask" 191hw_vars["$DualSubsliceMask"] = "perf->sys_vars.subslice_mask" 192hw_vars["$GpuTimestampFrequency"] = "perf->sys_vars.timestamp_frequency" 193hw_vars["$GpuMinFrequency"] = "perf->sys_vars.gt_min_freq" 194hw_vars["$GpuMaxFrequency"] = "perf->sys_vars.gt_max_freq" 195hw_vars["$SkuRevisionId"] = "perf->sys_vars.revision" 196 197def output_rpn_equation_code(set, counter, equation): 198 c("/* RPN equation: " + equation + " */") 199 tokens = equation.split() 200 stack = [] 201 tmp_id = 0 202 tmp = None 203 204 for token in tokens: 205 stack.append(token) 206 while stack and stack[-1] in ops: 207 op = stack.pop() 208 argc, callback = ops[op] 209 args = [] 210 for i in range(0, argc): 211 operand = stack.pop() 212 if operand[0] == "$": 213 if operand in hw_vars: 214 operand = hw_vars[operand] 215 elif operand in set.counter_vars: 216 reference = set.counter_vars[operand] 217 operand = set.read_funcs[operand[1:]] + "(perf, query, accumulator)" 218 else: 219 raise Exception("Failed to resolve variable " + operand + " in equation " + equation + " for " + set.name + " :: " + counter.get('name')); 220 args.append(operand) 221 222 tmp_id = callback(tmp_id, args) 223 224 tmp = "tmp{0}".format(tmp_id - 1) 225 stack.append(tmp) 226 227 if len(stack) != 1: 228 raise Exception("Spurious empty rpn code for " + set.name + " :: " + 229 counter.get('name') + ".\nThis is probably due to some unhandled RPN function, in the equation \"" + 230 equation + "\"") 231 232 value = stack[-1] 233 234 if value in hw_vars: 235 value = hw_vars[value] 236 if value in set.counter_vars: 237 value = set.read_funcs[value[1:]] + "(perf, query, accumulator)" 238 239 c("\nreturn " + value + ";") 240 241def splice_rpn_expression(set, counter, expression): 242 tokens = expression.split() 243 stack = [] 244 245 for token in tokens: 246 stack.append(token) 247 while stack and stack[-1] in exp_ops: 248 op = stack.pop() 249 argc, callback = exp_ops[op] 250 args = [] 251 for i in range(0, argc): 252 operand = stack.pop() 253 if operand[0] == "$": 254 if operand in hw_vars: 255 operand = hw_vars[operand] 256 else: 257 raise Exception("Failed to resolve variable " + operand + " in expression " + expression + " for " + set.name + " :: " + counter.get('name')); 258 args.append(operand) 259 260 subexp = callback(args) 261 262 stack.append(subexp) 263 264 if len(stack) != 1: 265 raise Exception("Spurious empty rpn expression for " + set.name + " :: " + 266 counter.get('name') + ".\nThis is probably due to some unhandled RPN operation, in the expression \"" + 267 expression + "\"") 268 269 return stack[-1] 270 271def output_counter_read(gen, set, counter): 272 c("\n") 273 c("/* {0} :: {1} */".format(set.name, counter.get('name'))) 274 275 if counter.read_hash in hashed_funcs: 276 c("#define %s \\" % counter.read_sym) 277 c_indent(3) 278 c("%s" % hashed_funcs[counter.read_hash]) 279 c_outdent(3) 280 else: 281 ret_type = counter.get('data_type') 282 if ret_type == "uint64": 283 ret_type = "uint64_t" 284 285 read_eq = counter.get('equation') 286 287 c("static " + ret_type) 288 c(counter.read_sym + "(UNUSED struct gen_perf_config *perf,\n") 289 c_indent(len(counter.read_sym) + 1) 290 c("const struct gen_perf_query_info *query,\n") 291 c("const uint64_t *accumulator)\n") 292 c_outdent(len(counter.read_sym) + 1) 293 294 c("{") 295 c_indent(3) 296 output_rpn_equation_code(set, counter, read_eq) 297 c_outdent(3) 298 c("}") 299 300 hashed_funcs[counter.read_hash] = counter.read_sym 301 302 303def output_counter_max(gen, set, counter): 304 max_eq = counter.get('max_equation') 305 306 if not counter.has_max_func(): 307 return 308 309 c("\n") 310 c("/* {0} :: {1} */".format(set.name, counter.get('name'))) 311 312 if counter.max_hash in hashed_funcs: 313 c("#define %s \\" % counter.max_sym()) 314 c_indent(3) 315 c("%s" % hashed_funcs[counter.max_hash]) 316 c_outdent(3) 317 else: 318 ret_type = counter.get('data_type') 319 if ret_type == "uint64": 320 ret_type = "uint64_t" 321 322 c("static " + ret_type) 323 c(counter.max_sym() + "(struct gen_perf_config *perf)\n") 324 c("{") 325 c_indent(3) 326 output_rpn_equation_code(set, counter, max_eq) 327 c_outdent(3) 328 c("}") 329 330 hashed_funcs[counter.max_hash] = counter.max_sym() 331 332 333c_type_sizes = { "uint32_t": 4, "uint64_t": 8, "float": 4, "double": 8, "bool": 4 } 334def sizeof(c_type): 335 return c_type_sizes[c_type] 336 337def pot_align(base, pot_alignment): 338 return (base + pot_alignment - 1) & ~(pot_alignment - 1); 339 340semantic_type_map = { 341 "duration": "raw", 342 "ratio": "event" 343 } 344 345def output_availability(set, availability, counter_name): 346 expression = splice_rpn_expression(set, counter_name, availability) 347 lines = expression.split(' && ') 348 n_lines = len(lines) 349 if n_lines == 1: 350 c("if (" + lines[0] + ") {") 351 else: 352 c("if (" + lines[0] + " &&") 353 c_indent(4) 354 for i in range(1, (n_lines - 1)): 355 c(lines[i] + " &&") 356 c(lines[(n_lines - 1)] + ") {") 357 c_outdent(4) 358 359 360def output_units(unit): 361 return unit.replace(' ', '_').upper() 362 363 364def output_counter_report(set, counter, current_offset): 365 data_type = counter.get('data_type') 366 data_type_uc = data_type.upper() 367 c_type = data_type 368 369 if "uint" in c_type: 370 c_type = c_type + "_t" 371 372 semantic_type = counter.get('semantic_type') 373 if semantic_type in semantic_type_map: 374 semantic_type = semantic_type_map[semantic_type] 375 376 semantic_type_uc = semantic_type.upper() 377 378 c("\n") 379 380 availability = counter.get('availability') 381 if availability: 382 output_availability(set, availability, counter.get('name')) 383 c_indent(3) 384 385 c("counter = &query->counters[query->n_counters++];\n") 386 c("counter->oa_counter_read_" + data_type + " = " + set.read_funcs[counter.get('symbol_name')] + ";\n") 387 c("counter->name = \"" + counter.get('name') + "\";\n") 388 c("counter->desc = \"" + counter.get('description') + "\";\n") 389 c("counter->symbol_name = \"" + counter.get('symbol_name') + "\";\n") 390 c("counter->category = \"" + counter.get('mdapi_group') + "\";\n") 391 c("counter->type = GEN_PERF_COUNTER_TYPE_" + semantic_type_uc + ";\n") 392 c("counter->data_type = GEN_PERF_COUNTER_DATA_TYPE_" + data_type_uc + ";\n") 393 c("counter->units = GEN_PERF_COUNTER_UNITS_" + output_units(counter.get('units')) + ";\n") 394 c("counter->raw_max = " + set.max_values[counter.get('symbol_name')] + ";\n") 395 396 current_offset = pot_align(current_offset, sizeof(c_type)) 397 c("counter->offset = " + str(current_offset) + ";\n") 398 399 if availability: 400 c_outdent(3); 401 c("}") 402 403 return current_offset + sizeof(c_type) 404 405 406register_types = { 407 'FLEX': 'flex_regs', 408 'NOA': 'mux_regs', 409 'OA': 'b_counter_regs', 410} 411 412def compute_register_lengths(set): 413 register_lengths = {} 414 register_configs = set.findall('register_config') 415 for register_config in register_configs: 416 t = register_types[register_config.get('type')] 417 if t not in register_lengths: 418 register_lengths[t] = len(register_config.findall('register')) 419 else: 420 register_lengths[t] += len(register_config.findall('register')) 421 422 return register_lengths 423 424 425def generate_register_configs(set): 426 register_configs = set.findall('register_config') 427 428 for register_config in register_configs: 429 t = register_types[register_config.get('type')] 430 431 availability = register_config.get('availability') 432 if availability: 433 output_availability(set, availability, register_config.get('type') + ' register config') 434 c_indent(3) 435 436 registers = register_config.findall('register') 437 c("static const struct gen_perf_query_register_prog %s[] = {" % t) 438 c_indent(3) 439 for register in registers: 440 c("{ .reg = %s, .val = %s }," % (register.get('address'), register.get('value'))) 441 c_outdent(3) 442 c("};") 443 c("query->config.%s = %s;" % (t, t)) 444 c("query->config.n_%s = ARRAY_SIZE(%s);" % (t, t)) 445 446 if availability: 447 c_outdent(3) 448 c("}") 449 c("\n") 450 451 452# Wraps a <counter> element from the oa-*.xml files. 453class Counter: 454 def __init__(self, set, xml): 455 self.xml = xml 456 self.set = set 457 self.read_hash = None 458 self.max_hash = None 459 460 self.read_sym = "{0}__{1}__{2}__read".format(self.set.gen.chipset, 461 self.set.underscore_name, 462 self.xml.get('underscore_name')) 463 464 def get(self, prop): 465 return self.xml.get(prop) 466 467 # Compute the hash of a counter's equation by expanding (including all the 468 # sub-equations it depends on) 469 def compute_hashes(self): 470 if self.read_hash is not None: 471 return 472 473 def replace_token(token): 474 if token[0] != "$": 475 return token 476 if token not in self.set.counter_vars: 477 return token 478 self.set.counter_vars[token].compute_hashes() 479 return self.set.counter_vars[token].read_hash 480 481 read_eq = self.xml.get('equation') 482 self.read_hash = ' '.join(map(replace_token, read_eq.split())) 483 484 max_eq = self.xml.get('max_equation') 485 if max_eq: 486 self.max_hash = ' '.join(map(replace_token, max_eq.split())) 487 488 def has_max_func(self): 489 max_eq = self.xml.get('max_equation') 490 if not max_eq: 491 return False 492 493 try: 494 val = float(max_eq) 495 return False 496 except ValueError: 497 pass 498 499 for token in max_eq.split(): 500 if token[0] == '$' and token not in hw_vars: 501 return False 502 return True 503 504 def max_sym(self): 505 assert self.has_max_func() 506 return "{0}__{1}__{2}__max".format(self.set.gen.chipset, 507 self.set.underscore_name, 508 self.xml.get('underscore_name')) 509 510 def max_value(self): 511 max_eq = self.xml.get('max_equation') 512 if not max_eq: 513 return "0 /* undefined */" 514 515 try: 516 return "{0}".format(float(max_eq)) 517 except ValueError: 518 pass 519 520 for token in max_eq.split(): 521 if token[0] == '$' and token not in hw_vars: 522 return "0 /* unsupported (varies over time) */" 523 524 return "{0}__{1}__{2}__max(perf)".format(self.set.gen.chipset, 525 self.set.underscore_name, 526 self.xml.get('underscore_name')) 527 528# Wraps a <set> element from the oa-*.xml files. 529class Set: 530 def __init__(self, gen, xml): 531 self.gen = gen 532 self.xml = xml 533 534 self.counter_vars = {} 535 self.max_values = {} 536 self.read_funcs = {} 537 538 xml_counters = self.xml.findall("counter") 539 self.counters = [] 540 for xml_counter in xml_counters: 541 counter = Counter(self, xml_counter) 542 self.counters.append(counter) 543 self.counter_vars["$" + counter.get('symbol_name')] = counter 544 self.read_funcs[counter.get('symbol_name')] = counter.read_sym 545 self.max_values[counter.get('symbol_name')] = counter.max_value() 546 547 for counter in self.counters: 548 counter.compute_hashes() 549 550 @property 551 def hw_config_guid(self): 552 return self.xml.get('hw_config_guid') 553 554 @property 555 def name(self): 556 return self.xml.get('name') 557 558 @property 559 def symbol_name(self): 560 return self.xml.get('symbol_name') 561 562 @property 563 def underscore_name(self): 564 return self.xml.get('underscore_name') 565 566 def findall(self, path): 567 return self.xml.findall(path) 568 569 def find(self, path): 570 return self.xml.find(path) 571 572 573# Wraps an entire oa-*.xml file. 574class Gen: 575 def __init__(self, filename): 576 self.filename = filename 577 self.xml = et.parse(self.filename) 578 self.chipset = self.xml.find('.//set').get('chipset').lower() 579 self.sets = [] 580 581 for xml_set in self.xml.findall(".//set"): 582 self.sets.append(Set(self, xml_set)) 583 584 585def main(): 586 global c_file 587 global header_file 588 589 parser = argparse.ArgumentParser() 590 parser.add_argument("--header", help="Header file to write", required=True) 591 parser.add_argument("--code", help="C file to write", required=True) 592 parser.add_argument("xml_files", nargs='+', help="List of xml metrics files to process") 593 594 args = parser.parse_args() 595 596 c_file = open(args.code, 'w') 597 header_file = open(args.header, 'w') 598 599 gens = [] 600 for xml_file in args.xml_files: 601 gens.append(Gen(xml_file)) 602 603 604 copyright = textwrap.dedent("""\ 605 /* Autogenerated file, DO NOT EDIT manually! generated by {} 606 * 607 * Copyright (c) 2015 Intel Corporation 608 * 609 * Permission is hereby granted, free of charge, to any person obtaining a 610 * copy of this software and associated documentation files (the "Software"), 611 * to deal in the Software without restriction, including without limitation 612 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 613 * and/or sell copies of the Software, and to permit persons to whom the 614 * Software is furnished to do so, subject to the following conditions: 615 * 616 * The above copyright notice and this permission notice (including the next 617 * paragraph) shall be included in all copies or substantial portions of the 618 * Software. 619 * 620 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 621 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 622 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 623 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 624 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 625 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 626 * DEALINGS IN THE SOFTWARE. 627 */ 628 629 """).format(os.path.basename(__file__)) 630 631 h(copyright) 632 h(textwrap.dedent("""\ 633 #pragma once 634 635 struct gen_perf_config; 636 637 """)) 638 639 c(copyright) 640 c(textwrap.dedent("""\ 641 #include <stdint.h> 642 #include <stdbool.h> 643 644 #include <drm-uapi/i915_drm.h> 645 646 #include "util/hash_table.h" 647 #include "util/ralloc.h" 648 649 """)) 650 651 c("#include \"" + os.path.basename(args.header) + "\"") 652 653 c(textwrap.dedent("""\ 654 #include "perf/gen_perf.h" 655 656 657 #define MIN(a, b) ((a < b) ? (a) : (b)) 658 #define MAX(a, b) ((a > b) ? (a) : (b)) 659 660 661 """)) 662 663 # Print out all equation functions. 664 for gen in gens: 665 for set in gen.sets: 666 for counter in set.counters: 667 output_counter_read(gen, set, counter) 668 output_counter_max(gen, set, counter) 669 670 # Print out all metric sets registration functions for each set in each 671 # generation. 672 for gen in gens: 673 for set in gen.sets: 674 counters = set.counters 675 676 c("\n") 677 c("\nstatic void\n") 678 c("{0}_register_{1}_counter_query(struct gen_perf_config *perf)\n".format(gen.chipset, set.underscore_name)) 679 c("{\n") 680 c_indent(3) 681 682 c("struct gen_perf_query_info *query = rzalloc(perf, struct gen_perf_query_info);\n") 683 c("\n") 684 c("query->kind = GEN_PERF_QUERY_TYPE_OA;\n") 685 c("query->name = \"" + set.name + "\";\n") 686 c("query->symbol_name = \"" + set.symbol_name + "\";\n") 687 c("query->guid = \"" + set.hw_config_guid + "\";\n") 688 689 c("query->counters = rzalloc_array(query, struct gen_perf_query_counter, %u);" % len(counters)) 690 c("query->n_counters = 0;") 691 c("query->oa_metrics_set_id = 0; /* determined at runtime, via sysfs */") 692 693 if gen.chipset == "hsw": 694 c(textwrap.dedent("""\ 695 query->oa_format = I915_OA_FORMAT_A45_B8_C8; 696 /* Accumulation buffer offsets... */ 697 query->gpu_time_offset = 0; 698 query->a_offset = 1; 699 query->b_offset = 46; 700 query->c_offset = 54; 701 """)) 702 else: 703 c(textwrap.dedent("""\ 704 query->oa_format = I915_OA_FORMAT_A32u40_A4u32_B8_C8; 705 /* Accumulation buffer offsets... */ 706 query->gpu_time_offset = 0; 707 query->gpu_clock_offset = 1; 708 query->a_offset = 2; 709 query->b_offset = 38; 710 query->c_offset = 46; 711 """)) 712 713 714 c("\n") 715 c("struct gen_perf_query_counter *counter = query->counters;\n") 716 717 c("\n") 718 c("/* Note: we're assuming there can't be any variation in the definition ") 719 c(" * of a query between contexts so it's ok to describe a query within a ") 720 c(" * global variable which only needs to be initialized once... */") 721 c("\nif (!query->data_size) {") 722 c_indent(3) 723 724 generate_register_configs(set) 725 726 offset = 0 727 for counter in counters: 728 offset = output_counter_report(set, counter, offset) 729 730 731 c("\nquery->data_size = counter->offset + gen_perf_query_counter_get_size(counter);\n") 732 733 c_outdent(3) 734 c("}"); 735 736 c("\n_mesa_hash_table_insert(perf->oa_metrics_table, query->guid, query);") 737 738 c_outdent(3) 739 c("}\n") 740 741 h("void gen_oa_register_queries_" + gen.chipset + "(struct gen_perf_config *perf);\n") 742 743 c("\nvoid") 744 c("gen_oa_register_queries_" + gen.chipset + "(struct gen_perf_config *perf)") 745 c("{") 746 c_indent(3) 747 748 for set in gen.sets: 749 c("{0}_register_{1}_counter_query(perf);".format(gen.chipset, set.underscore_name)) 750 751 c_outdent(3) 752 c("}") 753 754 755if __name__ == '__main__': 756 main() 757