1#!/usr/bin/env vpython
2# Copyright 2020 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import argparse
7import datetime
8import os
9import sys
10import xml.etree.ElementTree as ET
11
12# Add tools/perf to sys.path.
13sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
14
15from core import path_util
16path_util.AddPyUtilsToPath()
17path_util.AddTracingToPath()
18
19from core.perfetto_binary_roller import binary_deps_manager
20from core.tbmv3 import trace_processor
21from py_utils import tempfile_ext
22
23
24def ExtractValues(xml_path):
25  root = ET.parse(xml_path).getroot()
26
27  speeds = []
28  power = []
29  clusters = []
30  for array in root.iter('array'):
31    if array.get('name') == 'cpu.clusters.cores':
32      clusters = [int(value.text) for value in array.iter('value')]
33    if array.get('name').startswith('cpu.core_speeds.'):
34      speeds.append([int(value.text) for value in array.iter('value')])
35    if array.get('name').startswith('cpu.core_power.'):
36      power.append([float(value.text) for value in array.iter('value')])
37
38  values = []
39  cpu = 0
40  for cluster, n_cpus in enumerate(clusters):
41    for _ in range(n_cpus):
42      for freq, drain in zip(speeds[cluster], power[cluster]):
43        # TODO(khokhlov): Remove the correction when power profiles are updated.
44        corrected_drain = drain / n_cpus
45        values.append((cpu, cluster, freq, corrected_drain))
46      cpu += 1
47
48  return values
49
50
51def ExportProfiles(device_xmls, sql_path):
52  sql_values = []
53  for device, xml_path in device_xmls:
54    sql_values += [
55        '("%s", %s, %s, %s, %s)' % ((device, ) + v)
56        for v in ExtractValues(xml_path)
57    ]
58
59  with open(sql_path, 'w') as sql_file:
60    sql_file.write('INSERT INTO power_profile VALUES\n')
61    sql_file.write(',\n'.join(sql_values))
62    sql_file.write(';\n')
63
64
65def main(args):
66  parser = argparse.ArgumentParser()
67  parser.add_argument(
68      '--device-xml',
69      nargs=2,
70      metavar=('DEVICE', 'XML_FILE'),
71      action='append',
72      help='Device name and path to the XML file with the device '
73      'power profile. Can be used multiple times.')
74
75  args = parser.parse_args(args)
76
77  with tempfile_ext.NamedTemporaryDirectory() as tempdir:
78    sql_path = os.path.join(tempdir, trace_processor.POWER_PROFILE_SQL)
79    ExportProfiles(args.device_xml, sql_path)
80    version = datetime.datetime.now().strftime('%Y%m%dT%H%M%S')
81    binary_deps_manager.UploadAndSwitchDataFile(
82        trace_processor.POWER_PROFILE_SQL, sql_path, version)
83
84
85if __name__ == '__main__':
86  sys.exit(main(sys.argv[1:]))
87