Gabe Black has submitted this change and it was merged. ( https://gem5-review.googlesource.com/5621 )

Change subject: util: Simplify/consolidate the python conversion module.
......................................................................

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 <[email protected]>
Reviewed-by: Andreas Sandberg <[email protected]>
Maintainer: Andreas Sandberg <[email protected]>
---
M src/python/m5/util/convert.py
1 file changed, 104 insertions(+), 181 deletions(-)

Approvals:
  Jason Lowe-Power: Looks good to me, approved
  Andreas Sandberg: Looks good to me, approved; Looks good to me, approved



diff --git a/src/python/m5/util/convert.py b/src/python/m5/util/convert.py
index 351ee1e..cffa1bb 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 @@
 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:
-        return float(value)

-def toInteger(value):
-    value = toFloat(value)
+# 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 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 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 @@
     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')

--
To view, visit https://gem5-review.googlesource.com/5621
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: Ic8529203cc226c9b551b8535a444e3f2f25ad1eb
Gerrit-Change-Number: 5621
Gerrit-PatchSet: 2
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-Reviewer: Andreas Sandberg <[email protected]>
Gerrit-Reviewer: Gabe Black <[email protected]>
Gerrit-Reviewer: Jason Lowe-Power <[email protected]>
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to