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