# Copyright (c) 2005 The Regents of The University of Michigan # Copyright (c) 2010 Advanced Micro Devices, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer; # redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution; # neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Authors: Nathan Binkert # Gabe Black import six if six.PY3: long = int # metric prefixes atto = 1.0e-18 femto = 1.0e-15 pico = 1.0e-12 nano = 1.0e-9 micro = 1.0e-6 milli = 1.0e-3 kilo = 1.0e3 mega = 1.0e6 giga = 1.0e9 tera = 1.0e12 peta = 1.0e15 exa = 1.0e18 # power of 2 prefixes kibi = 1024 mebi = kibi * 1024 gibi = mebi * 1024 tebi = gibi * 1024 pebi = tebi * 1024 exbi = pebi * 1024 metric_prefixes = { 'Ei': exbi, 'E': exa, 'Pi': pebi, 'P': peta, 'Ti': tebi, 'T': tera, 'Gi': gibi, 'G': giga, 'M': mega, 'ki': kibi, 'k': kilo, 'Mi': mebi, 'm': milli, 'u': micro, 'n': nano, 'p': pico, 'f': femto, 'a': atto, } binary_prefixes = { 'Ei': exbi, 'E' : exbi, 'Pi': pebi, 'P' : pebi, 'Ti': tebi, 'T' : tebi, 'Gi': gibi, 'G' : gibi, 'Mi': mebi, 'M' : mebi, 'ki': kibi, 'k' : kibi, } def assertStr(value): if not isinstance(value, str): raise TypeError("wrong type '%s' should be str" % type(value)) # memory size configuration stuff def toNum(value, target_type, units, prefixes, converter): assertStr(value) def convert(val): try: return converter(val) except ValueError: raise ValueError( "cannot convert '%s' to %s" % (value, target_type)) if units and not value.endswith(units): units = None if not units: return convert(value) value = value[:-len(units)] prefix = next((p for p in prefixes.keys() if value.endswith(p)), None) if not prefix: return convert(value) value = value[:-len(prefix)] return convert(value) * prefixes[prefix] def toFloat(value, target_type='float', units=None, prefixes=[]): return toNum(value, target_type, units, prefixes, float) def toMetricFloat(value, target_type='float', units=None): return toFloat(value, target_type, units, metric_prefixes) def toBinaryFloat(value, target_type='float', units=None): return toFloat(value, target_type, units, binary_prefixes) def toInteger(value, target_type='integer', units=None, prefixes=[]): intifier = lambda x: int(x, 0) return toNum(value, target_type, units, prefixes, intifier) def toMetricInteger(value, target_type='integer', units=None): return toInteger(value, target_type, units, metric_prefixes) def toBinaryInteger(value, target_type='integer', units=None): return toInteger(value, target_type, units, binary_prefixes) def toBool(value): assertStr(value) value = value.lower() if value in ('true', 't', 'yes', 'y', '1'): return True if value in ('false', 'f', 'no', 'n', '0'): return False return result def toFrequency(value): return toMetricFloat(value, 'frequency', 'Hz') def toLatency(value): return toMetricFloat(value, 'latency', 's') def anyToLatency(value): """result is a clock period""" try: return 1 / toFrequency(value) except (ValueError, ZeroDivisionError): pass try: return toLatency(value) except ValueError: pass raise ValueError("cannot convert '%s' to clock period" % value) def anyToFrequency(value): """result is a clock period""" try: return toFrequency(value) except ValueError: pass try: return 1 / toLatency(value) except ValueError as ZeroDivisionError: pass raise ValueError("cannot convert '%s' to clock period" % value) def toNetworkBandwidth(value): return toMetricFloat(value, 'network bandwidth', 'bps') def toMemoryBandwidth(value): return toBinaryFloat(value, 'memory bandwidth', 'B/s') def toMemorySize(value): return toBinaryInteger(value, 'memory size', 'B') def toIpAddress(value): if not isinstance(value, str): raise TypeError("wrong type '%s' should be str" % type(value)) bytes = value.split('.') if len(bytes) != 4: raise ValueError('invalid ip address %s' % value) for byte in bytes: if not 0 <= int(byte) <= 0xff: raise ValueError('invalid ip address %s' % value) return (int(bytes[0]) << 24) | (int(bytes[1]) << 16) | \ (int(bytes[2]) << 8) | (int(bytes[3]) << 0) def toIpNetmask(value): if not isinstance(value, str): raise TypeError("wrong type '%s' should be str" % type(value)) (ip, netmask) = value.split('/') ip = toIpAddress(ip) netmaskParts = netmask.split('.') if len(netmaskParts) == 1: if not 0 <= int(netmask) <= 32: raise ValueError('invalid netmask %s' % netmask) return (ip, int(netmask)) elif len(netmaskParts) == 4: netmaskNum = toIpAddress(netmask) if netmaskNum == 0: return (ip, 0) testVal = 0 for i in range(32): testVal |= (1 << (31 - i)) if testVal == netmaskNum: return (ip, i + 1) raise ValueError('invalid netmask %s' % netmask) else: raise ValueError('invalid netmask %s' % netmask) def toIpWithPort(value): if not isinstance(value, str): raise TypeError("wrong type '%s' should be str" % type(value)) (ip, port) = value.split(':') ip = toIpAddress(ip) if not 0 <= int(port) <= 0xffff: raise ValueError('invalid port %s' % port) return (ip, int(port)) def toVoltage(value): return toMetricFloat(value, 'voltage', 'V') def toCurrent(value): return toMetricFloat(value, 'current', 'A') def toEnergy(value): return toMetricFloat(value, 'energy', 'J')