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