11736SN/A# Copyright (c) 2005 The Regents of The University of Michigan
27778Sgblack@eecs.umich.edu# Copyright (c) 2010 Advanced Micro Devices, Inc.
31736SN/A# All rights reserved.
41736SN/A#
51736SN/A# Redistribution and use in source and binary forms, with or without
61736SN/A# modification, are permitted provided that the following conditions are
71736SN/A# met: redistributions of source code must retain the above copyright
81736SN/A# notice, this list of conditions and the following disclaimer;
91736SN/A# redistributions in binary form must reproduce the above copyright
101736SN/A# notice, this list of conditions and the following disclaimer in the
111736SN/A# documentation and/or other materials provided with the distribution;
121736SN/A# neither the name of the copyright holders nor the names of its
131736SN/A# contributors may be used to endorse or promote products derived from
141736SN/A# this software without specific prior written permission.
151736SN/A#
161736SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171736SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181736SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191736SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201736SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211736SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221736SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231736SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241736SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251736SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261736SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665SN/A#
282665SN/A# Authors: Nathan Binkert
297778Sgblack@eecs.umich.edu#          Gabe Black
301736SN/A
3113719Sandreas.sandberg@arm.comimport six
3213719Sandreas.sandberg@arm.comif six.PY3:
3313719Sandreas.sandberg@arm.com    long = int
3413719Sandreas.sandberg@arm.com
351519SN/A# metric prefixes
3612247Sgabeblack@google.comatto  = 1.0e-18
3712247Sgabeblack@google.comfemto = 1.0e-15
3812247Sgabeblack@google.compico  = 1.0e-12
3912247Sgabeblack@google.comnano  = 1.0e-9
4012247Sgabeblack@google.commicro = 1.0e-6
4112247Sgabeblack@google.commilli = 1.0e-3
4212247Sgabeblack@google.com
4312247Sgabeblack@google.comkilo = 1.0e3
4412247Sgabeblack@google.commega = 1.0e6
4512247Sgabeblack@google.comgiga = 1.0e9
4612247Sgabeblack@google.comtera = 1.0e12
4712247Sgabeblack@google.competa = 1.0e15
481519SN/Aexa  = 1.0e18
491519SN/A
501519SN/A# power of 2 prefixes
511519SN/Akibi = 1024
521519SN/Amebi = kibi * 1024
531519SN/Agibi = mebi * 1024
541519SN/Atebi = gibi * 1024
551519SN/Apebi = tebi * 1024
561519SN/Aexbi = pebi * 1024
571519SN/A
5812247Sgabeblack@google.commetric_prefixes = {
5912247Sgabeblack@google.com    'Ei': exbi,
6012247Sgabeblack@google.com    'E': exa,
6112247Sgabeblack@google.com    'Pi': pebi,
6212247Sgabeblack@google.com    'P': peta,
6312247Sgabeblack@google.com    'Ti': tebi,
6412247Sgabeblack@google.com    'T': tera,
6512247Sgabeblack@google.com    'Gi': gibi,
6612247Sgabeblack@google.com    'G': giga,
6712247Sgabeblack@google.com    'M': mega,
6812247Sgabeblack@google.com    'ki': kibi,
6912247Sgabeblack@google.com    'k': kilo,
7012247Sgabeblack@google.com    'Mi': mebi,
7112247Sgabeblack@google.com    'm': milli,
7212247Sgabeblack@google.com    'u': micro,
7312247Sgabeblack@google.com    'n': nano,
7412247Sgabeblack@google.com    'p': pico,
7512247Sgabeblack@google.com    'f': femto,
7612247Sgabeblack@google.com    'a': atto,
7712247Sgabeblack@google.com}
7812247Sgabeblack@google.com
7912247Sgabeblack@google.combinary_prefixes = {
8012247Sgabeblack@google.com    'Ei': exbi,
8112247Sgabeblack@google.com    'E' : exbi,
8212247Sgabeblack@google.com    'Pi': pebi,
8312247Sgabeblack@google.com    'P' : pebi,
8412247Sgabeblack@google.com    'Ti': tebi,
8512247Sgabeblack@google.com    'T' : tebi,
8612247Sgabeblack@google.com    'Gi': gibi,
8712247Sgabeblack@google.com    'G' : gibi,
8812247Sgabeblack@google.com    'Mi': mebi,
8912247Sgabeblack@google.com    'M' : mebi,
9012247Sgabeblack@google.com    'ki': kibi,
9112247Sgabeblack@google.com    'k' : kibi,
9212247Sgabeblack@google.com}
9312247Sgabeblack@google.com
9412247Sgabeblack@google.comdef assertStr(value):
951519SN/A    if not isinstance(value, str):
9613663Sandreas.sandberg@arm.com        raise TypeError("wrong type '%s' should be str" % type(value))
971606SN/A
9812247Sgabeblack@google.com
9912247Sgabeblack@google.com# memory size configuration stuff
10013696Sgabeblack@google.comdef toNum(value, target_type, units, prefixes, converter):
10112247Sgabeblack@google.com    assertStr(value)
10212247Sgabeblack@google.com
10313696Sgabeblack@google.com    def convert(val):
10413696Sgabeblack@google.com        try:
10513696Sgabeblack@google.com            return converter(val)
10613696Sgabeblack@google.com        except ValueError:
10713696Sgabeblack@google.com            raise ValueError(
10813696Sgabeblack@google.com                "cannot convert '%s' to %s" % (value, target_type))
10913696Sgabeblack@google.com
11012247Sgabeblack@google.com    if units and not value.endswith(units):
11112247Sgabeblack@google.com        units = None
11212247Sgabeblack@google.com    if not units:
11313696Sgabeblack@google.com        return convert(value)
11412247Sgabeblack@google.com
11512247Sgabeblack@google.com    value = value[:-len(units)]
11612247Sgabeblack@google.com
11712247Sgabeblack@google.com    prefix = next((p for p in prefixes.keys() if value.endswith(p)), None)
11812247Sgabeblack@google.com    if not prefix:
11913696Sgabeblack@google.com        return convert(value)
12012247Sgabeblack@google.com    value = value[:-len(prefix)]
1211606SN/A
12213696Sgabeblack@google.com    return convert(value) * prefixes[prefix]
12313696Sgabeblack@google.com
12413696Sgabeblack@google.comdef toFloat(value, target_type='float', units=None, prefixes=[]):
12513696Sgabeblack@google.com    return toNum(value, target_type, units, prefixes, float)
12612247Sgabeblack@google.com
12712247Sgabeblack@google.comdef toMetricFloat(value, target_type='float', units=None):
12812247Sgabeblack@google.com    return toFloat(value, target_type, units, metric_prefixes)
12912247Sgabeblack@google.com
13012247Sgabeblack@google.comdef toBinaryFloat(value, target_type='float', units=None):
13112247Sgabeblack@google.com    return toFloat(value, target_type, units, binary_prefixes)
13212247Sgabeblack@google.com
13312247Sgabeblack@google.comdef toInteger(value, target_type='integer', units=None, prefixes=[]):
13413696Sgabeblack@google.com    intifier = lambda x: int(x, 0)
13513696Sgabeblack@google.com    return toNum(value, target_type, units, prefixes, intifier)
1361606SN/A
13712247Sgabeblack@google.comdef toMetricInteger(value, target_type='integer', units=None):
13812247Sgabeblack@google.com    return toInteger(value, target_type, units, metric_prefixes)
13912247Sgabeblack@google.com
14012247Sgabeblack@google.comdef toBinaryInteger(value, target_type='integer', units=None):
14112247Sgabeblack@google.com    return toInteger(value, target_type, units, binary_prefixes)
1421858SN/A
1431606SN/Adef toBool(value):
14412247Sgabeblack@google.com    assertStr(value)
1451606SN/A
1461606SN/A    value = value.lower()
14712247Sgabeblack@google.com    if value in ('true', 't', 'yes', 'y', '1'):
14812247Sgabeblack@google.com        return True
14912247Sgabeblack@google.com    if value in ('false', 'f', 'no', 'n', '0'):
15012247Sgabeblack@google.com        return False
1511858SN/A    return result
1521519SN/A
1531589SN/Adef toFrequency(value):
15412247Sgabeblack@google.com    return toMetricFloat(value, 'frequency', 'Hz')
1551519SN/A
1561589SN/Adef toLatency(value):
15712247Sgabeblack@google.com    return toMetricFloat(value, 'latency', 's')
1581606SN/A
1594167SN/Adef anyToLatency(value):
1601606SN/A    """result is a clock period"""
1611606SN/A    try:
16212247Sgabeblack@google.com        return 1 / toFrequency(value)
16313663Sandreas.sandberg@arm.com    except (ValueError, ZeroDivisionError):
1641606SN/A        pass
1651606SN/A
1661606SN/A    try:
16712247Sgabeblack@google.com        return toLatency(value)
1681606SN/A    except ValueError:
1691606SN/A        pass
1701606SN/A
17113663Sandreas.sandberg@arm.com    raise ValueError("cannot convert '%s' to clock period" % value)
1721606SN/A
1734167SN/Adef anyToFrequency(value):
1744167SN/A    """result is a clock period"""
1754167SN/A    try:
17612247Sgabeblack@google.com        return toFrequency(value)
1774167SN/A    except ValueError:
1784167SN/A        pass
1794167SN/A
1804167SN/A    try:
18112247Sgabeblack@google.com        return 1 / toLatency(value)
18213663Sandreas.sandberg@arm.com    except ValueError as ZeroDivisionError:
1834167SN/A        pass
1844167SN/A
18513663Sandreas.sandberg@arm.com    raise ValueError("cannot convert '%s' to clock period" % value)
1861519SN/A
1871589SN/Adef toNetworkBandwidth(value):
18812247Sgabeblack@google.com    return toMetricFloat(value, 'network bandwidth', 'bps')
1891519SN/A
1901589SN/Adef toMemoryBandwidth(value):
19112247Sgabeblack@google.com    return toBinaryFloat(value, 'memory bandwidth', 'B/s')
1921519SN/A
1931589SN/Adef toMemorySize(value):
19412247Sgabeblack@google.com    return toBinaryInteger(value, 'memory size', 'B')
1957777Sgblack@eecs.umich.edu
1967777Sgblack@eecs.umich.edudef toIpAddress(value):
1977777Sgblack@eecs.umich.edu    if not isinstance(value, str):
19813663Sandreas.sandberg@arm.com        raise TypeError("wrong type '%s' should be str" % type(value))
1997777Sgblack@eecs.umich.edu
2007777Sgblack@eecs.umich.edu    bytes = value.split('.')
2017777Sgblack@eecs.umich.edu    if len(bytes) != 4:
20213663Sandreas.sandberg@arm.com        raise ValueError('invalid ip address %s' % value)
2037777Sgblack@eecs.umich.edu
2047777Sgblack@eecs.umich.edu    for byte in bytes:
2057777Sgblack@eecs.umich.edu        if not 0 <= int(byte) <= 0xff:
20613663Sandreas.sandberg@arm.com            raise ValueError('invalid ip address %s' % value)
2077777Sgblack@eecs.umich.edu
2087777Sgblack@eecs.umich.edu    return (int(bytes[0]) << 24) | (int(bytes[1]) << 16) | \
2097777Sgblack@eecs.umich.edu           (int(bytes[2]) << 8)  | (int(bytes[3]) << 0)
2107777Sgblack@eecs.umich.edu
2117777Sgblack@eecs.umich.edudef toIpNetmask(value):
2127777Sgblack@eecs.umich.edu    if not isinstance(value, str):
21313663Sandreas.sandberg@arm.com        raise TypeError("wrong type '%s' should be str" % type(value))
2147777Sgblack@eecs.umich.edu
2157777Sgblack@eecs.umich.edu    (ip, netmask) = value.split('/')
2167777Sgblack@eecs.umich.edu    ip = toIpAddress(ip)
2177777Sgblack@eecs.umich.edu    netmaskParts = netmask.split('.')
2187777Sgblack@eecs.umich.edu    if len(netmaskParts) == 1:
2197777Sgblack@eecs.umich.edu        if not 0 <= int(netmask) <= 32:
22013663Sandreas.sandberg@arm.com            raise ValueError('invalid netmask %s' % netmask)
2217777Sgblack@eecs.umich.edu        return (ip, int(netmask))
2227777Sgblack@eecs.umich.edu    elif len(netmaskParts) == 4:
2237777Sgblack@eecs.umich.edu        netmaskNum = toIpAddress(netmask)
2247777Sgblack@eecs.umich.edu        if netmaskNum == 0:
2257777Sgblack@eecs.umich.edu            return (ip, 0)
2267777Sgblack@eecs.umich.edu        testVal = 0
2277777Sgblack@eecs.umich.edu        for i in range(32):
2287777Sgblack@eecs.umich.edu            testVal |= (1 << (31 - i))
2297777Sgblack@eecs.umich.edu            if testVal == netmaskNum:
2307777Sgblack@eecs.umich.edu                return (ip, i + 1)
23113663Sandreas.sandberg@arm.com        raise ValueError('invalid netmask %s' % netmask)
2327777Sgblack@eecs.umich.edu    else:
23313663Sandreas.sandberg@arm.com        raise ValueError('invalid netmask %s' % netmask)
2347777Sgblack@eecs.umich.edu
2357777Sgblack@eecs.umich.edudef toIpWithPort(value):
2367777Sgblack@eecs.umich.edu    if not isinstance(value, str):
23713663Sandreas.sandberg@arm.com        raise TypeError("wrong type '%s' should be str" % type(value))
2387777Sgblack@eecs.umich.edu
2397777Sgblack@eecs.umich.edu    (ip, port) = value.split(':')
2407777Sgblack@eecs.umich.edu    ip = toIpAddress(ip)
2417777Sgblack@eecs.umich.edu    if not 0 <= int(port) <= 0xffff:
24213663Sandreas.sandberg@arm.com        raise ValueError('invalid port %s' % port)
2437777Sgblack@eecs.umich.edu    return (ip, int(port))
2449827Sakash.bagdia@arm.com
2459827Sakash.bagdia@arm.comdef toVoltage(value):
24612247Sgabeblack@google.com    return toMetricFloat(value, 'voltage', 'V')
2479827Sakash.bagdia@arm.com
24810427Sandreas.hansson@arm.comdef toCurrent(value):
24912247Sgabeblack@google.com    return toMetricFloat(value, 'current', 'A')
25012251Sgabeblack@google.com
25112251Sgabeblack@google.comdef toEnergy(value):
25212251Sgabeblack@google.com    return toMetricFloat(value, 'energy', 'J')
253