1*c8dee2aaSAndroid Build Coastguard Worker# Copyright 2016 Google Inc. 2*c8dee2aaSAndroid Build Coastguard Worker# 3*c8dee2aaSAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*c8dee2aaSAndroid Build Coastguard Worker# found in the LICENSE file. 5*c8dee2aaSAndroid Build Coastguard Worker 6*c8dee2aaSAndroid Build Coastguard Workerimport time 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Workerclass Hardware: 9*c8dee2aaSAndroid Build Coastguard Worker """Locks down and monitors hardware for benchmarking. 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker This is a common base for classes that can control the specific hardware 12*c8dee2aaSAndroid Build Coastguard Worker we are running on. Its purpose is to lock the hardware into a constant 13*c8dee2aaSAndroid Build Coastguard Worker benchmarking mode for the duration of a 'with' block. e.g.: 14*c8dee2aaSAndroid Build Coastguard Worker 15*c8dee2aaSAndroid Build Coastguard Worker with hardware: 16*c8dee2aaSAndroid Build Coastguard Worker run_benchmark() 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard Worker While benchmarking, the caller must call sanity_check() frequently to verify 19*c8dee2aaSAndroid Build Coastguard Worker the hardware state has not changed. 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker """ 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Worker def __init__(self): 24*c8dee2aaSAndroid Build Coastguard Worker self.warmup_time = 0 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker def __enter__(self): 27*c8dee2aaSAndroid Build Coastguard Worker return self 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Worker def __exit__(self, exception_type, exception_value, traceback): 30*c8dee2aaSAndroid Build Coastguard Worker pass 31*c8dee2aaSAndroid Build Coastguard Worker 32*c8dee2aaSAndroid Build Coastguard Worker def filter_line(self, line): 33*c8dee2aaSAndroid Build Coastguard Worker """Returns False if the provided output line can be suppressed.""" 34*c8dee2aaSAndroid Build Coastguard Worker return True 35*c8dee2aaSAndroid Build Coastguard Worker 36*c8dee2aaSAndroid Build Coastguard Worker def sanity_check(self): 37*c8dee2aaSAndroid Build Coastguard Worker """Raises a HardwareException if any hardware state is not as expected.""" 38*c8dee2aaSAndroid Build Coastguard Worker pass 39*c8dee2aaSAndroid Build Coastguard Worker 40*c8dee2aaSAndroid Build Coastguard Worker def print_debug_diagnostics(self): 41*c8dee2aaSAndroid Build Coastguard Worker """Prints any info that may help improve or debug hardware monitoring.""" 42*c8dee2aaSAndroid Build Coastguard Worker pass 43*c8dee2aaSAndroid Build Coastguard Worker 44*c8dee2aaSAndroid Build Coastguard Worker 45*c8dee2aaSAndroid Build Coastguard Workerclass HardwareException(Exception): 46*c8dee2aaSAndroid Build Coastguard Worker """Gets thrown when certain hardware state is not what we expect. 47*c8dee2aaSAndroid Build Coastguard Worker 48*c8dee2aaSAndroid Build Coastguard Worker Generally this happens because of thermal conditions or other variables beyond 49*c8dee2aaSAndroid Build Coastguard Worker our control, and the appropriate course of action is to take a short nap 50*c8dee2aaSAndroid Build Coastguard Worker before resuming the benchmark. 51*c8dee2aaSAndroid Build Coastguard Worker 52*c8dee2aaSAndroid Build Coastguard Worker """ 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker def __init__(self, message, sleeptime=60): 55*c8dee2aaSAndroid Build Coastguard Worker Exception.__init__(self, message) 56*c8dee2aaSAndroid Build Coastguard Worker self.sleeptime = sleeptime 57*c8dee2aaSAndroid Build Coastguard Worker 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Workerclass Expectation: 60*c8dee2aaSAndroid Build Coastguard Worker """Simple helper for checking the readings on hardware gauges.""" 61*c8dee2aaSAndroid Build Coastguard Worker def __init__(self, value_type, min_value=None, max_value=None, 62*c8dee2aaSAndroid Build Coastguard Worker exact_value=None, name=None, sleeptime=60): 63*c8dee2aaSAndroid Build Coastguard Worker self.value_type = value_type 64*c8dee2aaSAndroid Build Coastguard Worker self.min_value = min_value 65*c8dee2aaSAndroid Build Coastguard Worker self.max_value = max_value 66*c8dee2aaSAndroid Build Coastguard Worker self.exact_value = exact_value 67*c8dee2aaSAndroid Build Coastguard Worker self.name = name 68*c8dee2aaSAndroid Build Coastguard Worker self.sleeptime = sleeptime 69*c8dee2aaSAndroid Build Coastguard Worker 70*c8dee2aaSAndroid Build Coastguard Worker def check(self, stringvalue): 71*c8dee2aaSAndroid Build Coastguard Worker typedvalue = self.value_type(stringvalue) 72*c8dee2aaSAndroid Build Coastguard Worker if self.min_value is not None and typedvalue < self.min_value: 73*c8dee2aaSAndroid Build Coastguard Worker raise HardwareException("%s is too low (%s, min=%s)" % 74*c8dee2aaSAndroid Build Coastguard Worker (self.name, stringvalue, str(self.min_value)), 75*c8dee2aaSAndroid Build Coastguard Worker sleeptime=self.sleeptime) 76*c8dee2aaSAndroid Build Coastguard Worker if self.max_value is not None and typedvalue > self.max_value: 77*c8dee2aaSAndroid Build Coastguard Worker raise HardwareException("%s is too high (%s, max=%s)" % 78*c8dee2aaSAndroid Build Coastguard Worker (self.name, stringvalue, str(self.max_value)), 79*c8dee2aaSAndroid Build Coastguard Worker sleeptime=self.sleeptime) 80*c8dee2aaSAndroid Build Coastguard Worker if self.exact_value is not None and typedvalue != self.exact_value: 81*c8dee2aaSAndroid Build Coastguard Worker raise HardwareException("unexpected %s (%s, expected=%s)" % 82*c8dee2aaSAndroid Build Coastguard Worker (self.name, stringvalue, str(self.exact_value)), 83*c8dee2aaSAndroid Build Coastguard Worker sleeptime=self.sleeptime) 84*c8dee2aaSAndroid Build Coastguard Worker 85*c8dee2aaSAndroid Build Coastguard Worker @staticmethod 86*c8dee2aaSAndroid Build Coastguard Worker def check_all(expectations, stringvalues): 87*c8dee2aaSAndroid Build Coastguard Worker if len(stringvalues) != len(expectations): 88*c8dee2aaSAndroid Build Coastguard Worker raise Exception("unexpected reading from hardware gauges " 89*c8dee2aaSAndroid Build Coastguard Worker "(expected %i values):\n%s" % 90*c8dee2aaSAndroid Build Coastguard Worker (len(expectations), '\n'.join(stringvalues))) 91*c8dee2aaSAndroid Build Coastguard Worker 92*c8dee2aaSAndroid Build Coastguard Worker for value, expected in zip(stringvalues, expectations): 93*c8dee2aaSAndroid Build Coastguard Worker expected.check(value) 94