summaryrefslogtreecommitdiff
path: root/src/python
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2017-11-10 02:04:00 -0800
committerGabe Black <gabeblack@google.com>2017-11-13 09:03:46 +0000
commit0a67a7a7ce42fd1af0f5013b9723126e18f45378 (patch)
treea58af955496f680b7b6dbf72b164b36d96868414 /src/python
parent49cf9fded08741099d25848807442a89c4d21399 (diff)
downloadgem5-0a67a7a7ce42fd1af0f5013b9723126e18f45378.tar.xz
util: Simplify/consolidate the python conversion module.
The python conversion module was really repetitive and fragmented, where some types of conversions use common code, and some use hand written case statements which did something very similar. Also, some types like Voltage could only handle V and mV but no other scaling prefix. This change restructures the module to centralize a lot of the unit handling code into toFloat, and makes the various other functions use it. Change-Id: Ic8529203cc226c9b551b8535a444e3f2f25ad1eb Reviewed-on: https://gem5-review.googlesource.com/5621 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Diffstat (limited to 'src/python')
-rw-r--r--src/python/m5/util/convert.py283
1 files changed, 103 insertions, 180 deletions
diff --git a/src/python/m5/util/convert.py b/src/python/m5/util/convert.py
index 351ee1ee0..cffa1bb49 100644
--- a/src/python/m5/util/convert.py
+++ b/src/python/m5/util/convert.py
@@ -29,19 +29,19 @@
# Gabe Black
# metric prefixes
-exa = 1.0e18
-peta = 1.0e15
-tera = 1.0e12
-giga = 1.0e9
-mega = 1.0e6
-kilo = 1.0e3
-
-milli = 1.0e-3
-micro = 1.0e-6
-nano = 1.0e-9
-pico = 1.0e-12
-femto = 1.0e-15
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
@@ -51,122 +51,115 @@ tebi = gibi * 1024
pebi = tebi * 1024
exbi = pebi * 1024
-# memory size configuration stuff
-def toFloat(value):
+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)
- if value.endswith('Ei'):
- return float(value[:-2]) * exbi
- elif value.endswith('Pi'):
- return float(value[:-2]) * pebi
- elif value.endswith('Ti'):
- return float(value[:-2]) * tebi
- elif value.endswith('Gi'):
- return float(value[:-2]) * gibi
- elif value.endswith('Mi'):
- return float(value[:-2]) * mebi
- elif value.endswith('ki'):
- return float(value[:-2]) * kibi
- elif value.endswith('E'):
- return float(value[:-1]) * exa
- elif value.endswith('P'):
- return float(value[:-1]) * peta
- elif value.endswith('T'):
- return float(value[:-1]) * tera
- elif value.endswith('G'):
- return float(value[:-1]) * giga
- elif value.endswith('M'):
- return float(value[:-1]) * mega
- elif value.endswith('k'):
- return float(value[:-1]) * kilo
- elif value.endswith('m'):
- return float(value[:-1]) * milli
- elif value.endswith('u'):
- return float(value[:-1]) * micro
- elif value.endswith('n'):
- return float(value[:-1]) * nano
- elif value.endswith('p'):
- return float(value[:-1]) * pico
- elif value.endswith('f'):
- return float(value[:-1]) * femto
- else:
+
+# memory size configuration stuff
+def toFloat(value, target_type='float', units=None, prefixes=[]):
+ assertStr(value)
+
+ if units and not value.endswith(units):
+ units = None
+ if not units:
+ try:
+ return float(value)
+ except ValueError:
+ raise ValueError, "cannot convert '%s' to %s" % \
+ (value, target_type)
+
+ value = value[:-len(units)]
+
+ prefix = next((p for p in prefixes.keys() if value.endswith(p)), None)
+ if not prefix:
return float(value)
+ value = value[:-len(prefix)]
+
+ return float(value) * prefixes[prefix]
+
+def toMetricFloat(value, target_type='float', units=None):
+ return toFloat(value, target_type, units, metric_prefixes)
-def toInteger(value):
- value = toFloat(value)
+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=[]):
+ value = toFloat(value, target_type, units, prefixes)
result = long(value)
if value != result:
- raise ValueError, "cannot convert '%s' to integer" % value
+ raise ValueError, "cannot convert '%s' to integer %s" % \
+ (value, target_type)
return result
-_bool_dict = {
- 'true' : True, 't' : True, 'yes' : True, 'y' : True, '1' : True,
- 'false' : False, 'f' : False, 'no' : False, 'n' : False, '0' : False
- }
+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):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
+ assertStr(value)
value = value.lower()
- result = _bool_dict.get(value, None)
- if result == None:
- raise ValueError, "cannot convert '%s' to bool" % value
+ 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):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('THz'):
- return float(value[:-3]) * tera
- elif value.endswith('GHz'):
- return float(value[:-3]) * giga
- elif value.endswith('MHz'):
- return float(value[:-3]) * mega
- elif value.endswith('kHz'):
- return float(value[:-3]) * kilo
- elif value.endswith('Hz'):
- return float(value[:-2])
-
- raise ValueError, "cannot convert '%s' to frequency" % value
+ return toMetricFloat(value, 'frequency', 'Hz')
def toLatency(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('ps'):
- return float(value[:-2]) * pico
- elif value.endswith('ns'):
- return float(value[:-2]) * nano
- elif value.endswith('us'):
- return float(value[:-2]) * micro
- elif value.endswith('ms'):
- return float(value[:-2]) * milli
- elif value.endswith('s'):
- return float(value[:-1])
-
- raise ValueError, "cannot convert '%s' to latency" % value
+ return toMetricFloat(value, 'latency', 's')
def anyToLatency(value):
"""result is a clock period"""
-
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
try:
- val = toFrequency(value)
- if val != 0:
- val = 1 / val
- return val
- except ValueError:
+ return 1 / toFrequency(value)
+ except ValueError, ZeroDivisionError:
pass
try:
- val = toLatency(value)
- return val
+ return toLatency(value)
except ValueError:
pass
@@ -174,82 +167,26 @@ def anyToLatency(value):
def anyToFrequency(value):
"""result is a clock period"""
-
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
try:
- val = toFrequency(value)
- return val
+ return toFrequency(value)
except ValueError:
pass
try:
- val = toLatency(value)
- if val != 0:
- val = 1 / val
- return val
- except ValueError:
+ return 1 / toLatency(value)
+ except ValueError, ZeroDivisionError:
pass
raise ValueError, "cannot convert '%s' to clock period" % value
def toNetworkBandwidth(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('Tbps'):
- return float(value[:-4]) * tera
- elif value.endswith('Gbps'):
- return float(value[:-4]) * giga
- elif value.endswith('Mbps'):
- return float(value[:-4]) * mega
- elif value.endswith('kbps'):
- return float(value[:-4]) * kilo
- elif value.endswith('bps'):
- return float(value[:-3])
- else:
- return float(value)
-
- raise ValueError, "cannot convert '%s' to network bandwidth" % value
+ return toMetricFloat(value, 'network bandwidth', 'bps')
def toMemoryBandwidth(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('PB/s'):
- return float(value[:-4]) * pebi
- elif value.endswith('TB/s'):
- return float(value[:-4]) * tebi
- elif value.endswith('GB/s'):
- return float(value[:-4]) * gibi
- elif value.endswith('MB/s'):
- return float(value[:-4]) * mebi
- elif value.endswith('kB/s'):
- return float(value[:-4]) * kibi
- elif value.endswith('B/s'):
- return float(value[:-3])
-
- raise ValueError, "cannot convert '%s' to memory bandwidth" % value
+ return toBinaryFloat(value, 'memory bandwidth', 'B/s')
def toMemorySize(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('PB'):
- return long(value[:-2]) * pebi
- elif value.endswith('TB'):
- return long(value[:-2]) * tebi
- elif value.endswith('GB'):
- return long(value[:-2]) * gibi
- elif value.endswith('MB'):
- return long(value[:-2]) * mebi
- elif value.endswith('kB'):
- return long(value[:-2]) * kibi
- elif value.endswith('B'):
- return long(value[:-1])
-
- raise ValueError, "cannot convert '%s' to memory size" % value
+ return toBinaryInteger(value, 'memory size', 'B')
def toIpAddress(value):
if not isinstance(value, str):
@@ -301,21 +238,7 @@ def toIpWithPort(value):
return (ip, int(port))
def toVoltage(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('mV'):
- return float(value[:-2]) * milli
- elif value.endswith('V'):
- return float(value[:-1])
-
- raise ValueError, "cannot convert '%s' to voltage" % value
+ return toMetricFloat(value, 'voltage', 'V')
def toCurrent(value):
- if not isinstance(value, str):
- raise TypeError, "wrong type '%s' should be str" % type(value)
-
- if value.endswith('A'):
- return toFloat(value[:-1])
-
- raise ValueError, "cannot convert '%s' to current" % value
+ return toMetricFloat(value, 'current', 'A')