Home | History | Annotate | Download | only in skpbench
      1 # Copyright 2017 Google Inc.
      2 #
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 from _hardware import HardwareException, Expectation
      7 from _hardware_android import HardwareAndroid
      8 from collections import namedtuple
      9 import itertools
     10 
     11 CPU_CLOCK_RATE = 1670400
     12 GPU_CLOCK_RATE = 510000000
     13 
     14 DEVFREQ_DIRNAME = '/sys/class/devfreq'
     15 DEVFREQ_THROTTLE = 0.74
     16 DEVFREQ_BLACKLIST = ('b00000.qcom,kgsl-3d0', 'soc:qcom,kgsl-busmon',
     17                      'soc:qcom,m4m')
     18 DevfreqKnobs = namedtuple('knobs',
     19                           ('available_governors', 'available_frequencies',
     20                            'governor', 'min_freq', 'max_freq', 'cur_freq'))
     21 
     22 class HardwarePixel(HardwareAndroid):
     23   def __init__(self, adb):
     24     HardwareAndroid.__init__(self, adb)
     25     self._discover_devfreqs()
     26 
     27   def __enter__(self):
     28     HardwareAndroid.__enter__(self)
     29     if not self._adb.is_root():
     30       return self
     31 
     32     self._adb.shell('\n'.join(['''\
     33       stop thermal-engine
     34       stop thermald
     35       stop perfd
     36       stop mpdecision''',
     37 
     38       # enable and lock the two fast cores.
     39       '''
     40       for N in 3 2; do
     41         echo 1 > /sys/devices/system/cpu/cpu$N/online
     42         echo userspace > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
     43         echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
     44         echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
     45         echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
     46       done''' % tuple(CPU_CLOCK_RATE for _ in range(3)),
     47 
     48       # turn off the two slow cores
     49       '''
     50       for N in 1 0; do
     51         echo 0 > /sys/devices/system/cpu/cpu$N/online
     52       done''',
     53 
     54       # gpu perf commands from
     55       # https://developer.qualcomm.com/qfile/28823/lm80-p0436-11_adb_commands.pdf
     56       '''
     57       echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split
     58       echo 1 > /sys/class/kgsl/kgsl-3d0/force_bus_on
     59       echo 1 > /sys/class/kgsl/kgsl-3d0/force_rail_on
     60       echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on
     61       echo 1000000 > /sys/class/kgsl/kgsl-3d0/idle_timer
     62       echo userspace > /sys/class/kgsl/kgsl-3d0/devfreq/governor
     63       echo 2 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
     64       echo 2 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel
     65       echo 2 > /sys/class/kgsl/kgsl-3d0/thermal_pwrlevel
     66       echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
     67       echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
     68       echo %i > /sys/class/kgsl/kgsl-3d0/max_gpuclk
     69       echo %i > /sys/class/kgsl/kgsl-3d0/gpuclk''' %
     70       tuple(GPU_CLOCK_RATE for _ in range(4))] + \
     71 
     72       self._devfreq_lock_cmds))
     73 
     74     return self
     75 
     76   def sanity_check(self):
     77     HardwareAndroid.sanity_check(self)
     78 
     79     if not self._adb.is_root():
     80       return
     81 
     82     result = self._adb.check(' '.join(
     83       ['cat',
     84        '/sys/class/power_supply/battery/capacity',
     85        '/sys/devices/system/cpu/online'] + \
     86       ['/sys/devices/system/cpu/cpu%i/cpufreq/scaling_cur_freq' % i
     87        for i in range(2, 4)] + \
     88       ['/sys/class/kgsl/kgsl-3d0/thermal_pwrlevel',
     89        '/sys/kernel/debug/clk/gpu_gx_gfx3d_clk/measure',
     90        '/sys/kernel/debug/clk/bimc_clk/measure',
     91        '/sys/class/thermal/thermal_zone22/temp',
     92        '/sys/class/thermal/thermal_zone23/temp'] + \
     93       self._devfreq_sanity_knobs))
     94 
     95     expectations = \
     96       [Expectation(int, min_value=30, name='battery', sleeptime=30*60),
     97        Expectation(str, exact_value='2-3', name='online cpus')] + \
     98       [Expectation(int, exact_value=CPU_CLOCK_RATE, name='cpu_%i clock rate' %i)
     99        for i in range(2, 4)] + \
    100       [Expectation(int, exact_value=2, name='gpu thermal power level'),
    101        Expectation(long, min_value=(GPU_CLOCK_RATE - 5000),
    102                    max_value=(GPU_CLOCK_RATE + 5000),
    103                    name='measured gpu clock'),
    104        Expectation(long, min_value=902390000, max_value=902409999,
    105                    name='measured ddr clock', sleeptime=10),
    106        Expectation(int, max_value=41000, name='pm8994_tz temperature'),
    107        Expectation(int, max_value=40, name='msm_therm temperature')] + \
    108       self._devfreq_sanity_expectations
    109 
    110     Expectation.check_all(expectations, result.splitlines())
    111 
    112   def _discover_devfreqs(self):
    113     self._devfreq_lock_cmds = list()
    114     self._devfreq_sanity_knobs = list()
    115     self._devfreq_sanity_expectations = list()
    116 
    117     results = iter(self._adb.check('''\
    118       KNOBS='%s'
    119       for DEVICE in %s/*; do
    120         if cd $DEVICE && ls $KNOBS >/dev/null; then
    121           basename $DEVICE
    122           cat $KNOBS
    123         fi
    124       done 2>/dev/null''' %
    125       (' '.join(DevfreqKnobs._fields), DEVFREQ_DIRNAME)).splitlines())
    126 
    127     while True:
    128       batch = tuple(itertools.islice(results, 1 + len(DevfreqKnobs._fields)))
    129       if not batch:
    130         break
    131 
    132       devfreq = batch[0]
    133       if devfreq in DEVFREQ_BLACKLIST:
    134         continue
    135 
    136       path = '%s/%s' % (DEVFREQ_DIRNAME, devfreq)
    137 
    138       knobs = DevfreqKnobs(*batch[1:])
    139       if not 'performance' in knobs.available_governors.split():
    140         print('WARNING: devfreq %s does not have performance governor' % path)
    141         continue
    142 
    143       self._devfreq_lock_cmds.append('echo performance > %s/governor' % path)
    144 
    145       frequencies = map(int, knobs.available_frequencies.split())
    146       if frequencies:
    147         # choose the lowest frequency that is >= DEVFREQ_THROTTLE * max.
    148         frequencies.sort()
    149         target = DEVFREQ_THROTTLE * frequencies[-1]
    150         idx = len(frequencies) - 1
    151         while idx > 0 and frequencies[idx - 1] >= target:
    152           idx -= 1
    153         bench_frequency = frequencies[idx]
    154         self._devfreq_lock_cmds.append('echo %i > %s/min_freq' %
    155                                       (bench_frequency, path))
    156         self._devfreq_lock_cmds.append('echo %i > %s/max_freq' %
    157                                       (bench_frequency, path))
    158         self._devfreq_sanity_knobs.append('%s/cur_freq' % path)
    159         self._devfreq_sanity_expectations.append(
    160           Expectation(int, exact_value=bench_frequency,
    161                       name='%s/cur_freq' % path))
    162