convert.py (13696:b303ca652433) convert.py (13719:74853963ddcf)
1# Copyright (c) 2005 The Regents of The University of Michigan
2# Copyright (c) 2010 Advanced Micro Devices, Inc.
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28# Authors: Nathan Binkert
29# Gabe Black
30
1# Copyright (c) 2005 The Regents of The University of Michigan
2# Copyright (c) 2010 Advanced Micro Devices, Inc.
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28# Authors: Nathan Binkert
29# Gabe Black
30
31import six
32if six.PY3:
33 long = int
34
31# metric prefixes
32atto = 1.0e-18
33femto = 1.0e-15
34pico = 1.0e-12
35nano = 1.0e-9
36micro = 1.0e-6
37milli = 1.0e-3
38
39kilo = 1.0e3
40mega = 1.0e6
41giga = 1.0e9
42tera = 1.0e12
43peta = 1.0e15
44exa = 1.0e18
45
46# power of 2 prefixes
47kibi = 1024
48mebi = kibi * 1024
49gibi = mebi * 1024
50tebi = gibi * 1024
51pebi = tebi * 1024
52exbi = pebi * 1024
53
54metric_prefixes = {
55 'Ei': exbi,
56 'E': exa,
57 'Pi': pebi,
58 'P': peta,
59 'Ti': tebi,
60 'T': tera,
61 'Gi': gibi,
62 'G': giga,
63 'M': mega,
64 'ki': kibi,
65 'k': kilo,
66 'Mi': mebi,
67 'm': milli,
68 'u': micro,
69 'n': nano,
70 'p': pico,
71 'f': femto,
72 'a': atto,
73}
74
75binary_prefixes = {
76 'Ei': exbi,
77 'E' : exbi,
78 'Pi': pebi,
79 'P' : pebi,
80 'Ti': tebi,
81 'T' : tebi,
82 'Gi': gibi,
83 'G' : gibi,
84 'Mi': mebi,
85 'M' : mebi,
86 'ki': kibi,
87 'k' : kibi,
88}
89
90def assertStr(value):
91 if not isinstance(value, str):
92 raise TypeError("wrong type '%s' should be str" % type(value))
93
94
95# memory size configuration stuff
96def toNum(value, target_type, units, prefixes, converter):
97 assertStr(value)
98
99 def convert(val):
100 try:
101 return converter(val)
102 except ValueError:
103 raise ValueError(
104 "cannot convert '%s' to %s" % (value, target_type))
105
106 if units and not value.endswith(units):
107 units = None
108 if not units:
109 return convert(value)
110
111 value = value[:-len(units)]
112
113 prefix = next((p for p in prefixes.keys() if value.endswith(p)), None)
114 if not prefix:
115 return convert(value)
116 value = value[:-len(prefix)]
117
118 return convert(value) * prefixes[prefix]
119
120def toFloat(value, target_type='float', units=None, prefixes=[]):
121 return toNum(value, target_type, units, prefixes, float)
122
123def toMetricFloat(value, target_type='float', units=None):
124 return toFloat(value, target_type, units, metric_prefixes)
125
126def toBinaryFloat(value, target_type='float', units=None):
127 return toFloat(value, target_type, units, binary_prefixes)
128
129def toInteger(value, target_type='integer', units=None, prefixes=[]):
130 intifier = lambda x: int(x, 0)
131 return toNum(value, target_type, units, prefixes, intifier)
132
133def toMetricInteger(value, target_type='integer', units=None):
134 return toInteger(value, target_type, units, metric_prefixes)
135
136def toBinaryInteger(value, target_type='integer', units=None):
137 return toInteger(value, target_type, units, binary_prefixes)
138
139def toBool(value):
140 assertStr(value)
141
142 value = value.lower()
143 if value in ('true', 't', 'yes', 'y', '1'):
144 return True
145 if value in ('false', 'f', 'no', 'n', '0'):
146 return False
147 return result
148
149def toFrequency(value):
150 return toMetricFloat(value, 'frequency', 'Hz')
151
152def toLatency(value):
153 return toMetricFloat(value, 'latency', 's')
154
155def anyToLatency(value):
156 """result is a clock period"""
157 try:
158 return 1 / toFrequency(value)
159 except (ValueError, ZeroDivisionError):
160 pass
161
162 try:
163 return toLatency(value)
164 except ValueError:
165 pass
166
167 raise ValueError("cannot convert '%s' to clock period" % value)
168
169def anyToFrequency(value):
170 """result is a clock period"""
171 try:
172 return toFrequency(value)
173 except ValueError:
174 pass
175
176 try:
177 return 1 / toLatency(value)
178 except ValueError as ZeroDivisionError:
179 pass
180
181 raise ValueError("cannot convert '%s' to clock period" % value)
182
183def toNetworkBandwidth(value):
184 return toMetricFloat(value, 'network bandwidth', 'bps')
185
186def toMemoryBandwidth(value):
187 return toBinaryFloat(value, 'memory bandwidth', 'B/s')
188
189def toMemorySize(value):
190 return toBinaryInteger(value, 'memory size', 'B')
191
192def toIpAddress(value):
193 if not isinstance(value, str):
194 raise TypeError("wrong type '%s' should be str" % type(value))
195
196 bytes = value.split('.')
197 if len(bytes) != 4:
198 raise ValueError('invalid ip address %s' % value)
199
200 for byte in bytes:
201 if not 0 <= int(byte) <= 0xff:
202 raise ValueError('invalid ip address %s' % value)
203
204 return (int(bytes[0]) << 24) | (int(bytes[1]) << 16) | \
205 (int(bytes[2]) << 8) | (int(bytes[3]) << 0)
206
207def toIpNetmask(value):
208 if not isinstance(value, str):
209 raise TypeError("wrong type '%s' should be str" % type(value))
210
211 (ip, netmask) = value.split('/')
212 ip = toIpAddress(ip)
213 netmaskParts = netmask.split('.')
214 if len(netmaskParts) == 1:
215 if not 0 <= int(netmask) <= 32:
216 raise ValueError('invalid netmask %s' % netmask)
217 return (ip, int(netmask))
218 elif len(netmaskParts) == 4:
219 netmaskNum = toIpAddress(netmask)
220 if netmaskNum == 0:
221 return (ip, 0)
222 testVal = 0
223 for i in range(32):
224 testVal |= (1 << (31 - i))
225 if testVal == netmaskNum:
226 return (ip, i + 1)
227 raise ValueError('invalid netmask %s' % netmask)
228 else:
229 raise ValueError('invalid netmask %s' % netmask)
230
231def toIpWithPort(value):
232 if not isinstance(value, str):
233 raise TypeError("wrong type '%s' should be str" % type(value))
234
235 (ip, port) = value.split(':')
236 ip = toIpAddress(ip)
237 if not 0 <= int(port) <= 0xffff:
238 raise ValueError('invalid port %s' % port)
239 return (ip, int(port))
240
241def toVoltage(value):
242 return toMetricFloat(value, 'voltage', 'V')
243
244def toCurrent(value):
245 return toMetricFloat(value, 'current', 'A')
246
247def toEnergy(value):
248 return toMetricFloat(value, 'energy', 'J')
35# metric prefixes
36atto = 1.0e-18
37femto = 1.0e-15
38pico = 1.0e-12
39nano = 1.0e-9
40micro = 1.0e-6
41milli = 1.0e-3
42
43kilo = 1.0e3
44mega = 1.0e6
45giga = 1.0e9
46tera = 1.0e12
47peta = 1.0e15
48exa = 1.0e18
49
50# power of 2 prefixes
51kibi = 1024
52mebi = kibi * 1024
53gibi = mebi * 1024
54tebi = gibi * 1024
55pebi = tebi * 1024
56exbi = pebi * 1024
57
58metric_prefixes = {
59 'Ei': exbi,
60 'E': exa,
61 'Pi': pebi,
62 'P': peta,
63 'Ti': tebi,
64 'T': tera,
65 'Gi': gibi,
66 'G': giga,
67 'M': mega,
68 'ki': kibi,
69 'k': kilo,
70 'Mi': mebi,
71 'm': milli,
72 'u': micro,
73 'n': nano,
74 'p': pico,
75 'f': femto,
76 'a': atto,
77}
78
79binary_prefixes = {
80 'Ei': exbi,
81 'E' : exbi,
82 'Pi': pebi,
83 'P' : pebi,
84 'Ti': tebi,
85 'T' : tebi,
86 'Gi': gibi,
87 'G' : gibi,
88 'Mi': mebi,
89 'M' : mebi,
90 'ki': kibi,
91 'k' : kibi,
92}
93
94def assertStr(value):
95 if not isinstance(value, str):
96 raise TypeError("wrong type '%s' should be str" % type(value))
97
98
99# memory size configuration stuff
100def toNum(value, target_type, units, prefixes, converter):
101 assertStr(value)
102
103 def convert(val):
104 try:
105 return converter(val)
106 except ValueError:
107 raise ValueError(
108 "cannot convert '%s' to %s" % (value, target_type))
109
110 if units and not value.endswith(units):
111 units = None
112 if not units:
113 return convert(value)
114
115 value = value[:-len(units)]
116
117 prefix = next((p for p in prefixes.keys() if value.endswith(p)), None)
118 if not prefix:
119 return convert(value)
120 value = value[:-len(prefix)]
121
122 return convert(value) * prefixes[prefix]
123
124def toFloat(value, target_type='float', units=None, prefixes=[]):
125 return toNum(value, target_type, units, prefixes, float)
126
127def toMetricFloat(value, target_type='float', units=None):
128 return toFloat(value, target_type, units, metric_prefixes)
129
130def toBinaryFloat(value, target_type='float', units=None):
131 return toFloat(value, target_type, units, binary_prefixes)
132
133def toInteger(value, target_type='integer', units=None, prefixes=[]):
134 intifier = lambda x: int(x, 0)
135 return toNum(value, target_type, units, prefixes, intifier)
136
137def toMetricInteger(value, target_type='integer', units=None):
138 return toInteger(value, target_type, units, metric_prefixes)
139
140def toBinaryInteger(value, target_type='integer', units=None):
141 return toInteger(value, target_type, units, binary_prefixes)
142
143def toBool(value):
144 assertStr(value)
145
146 value = value.lower()
147 if value in ('true', 't', 'yes', 'y', '1'):
148 return True
149 if value in ('false', 'f', 'no', 'n', '0'):
150 return False
151 return result
152
153def toFrequency(value):
154 return toMetricFloat(value, 'frequency', 'Hz')
155
156def toLatency(value):
157 return toMetricFloat(value, 'latency', 's')
158
159def anyToLatency(value):
160 """result is a clock period"""
161 try:
162 return 1 / toFrequency(value)
163 except (ValueError, ZeroDivisionError):
164 pass
165
166 try:
167 return toLatency(value)
168 except ValueError:
169 pass
170
171 raise ValueError("cannot convert '%s' to clock period" % value)
172
173def anyToFrequency(value):
174 """result is a clock period"""
175 try:
176 return toFrequency(value)
177 except ValueError:
178 pass
179
180 try:
181 return 1 / toLatency(value)
182 except ValueError as ZeroDivisionError:
183 pass
184
185 raise ValueError("cannot convert '%s' to clock period" % value)
186
187def toNetworkBandwidth(value):
188 return toMetricFloat(value, 'network bandwidth', 'bps')
189
190def toMemoryBandwidth(value):
191 return toBinaryFloat(value, 'memory bandwidth', 'B/s')
192
193def toMemorySize(value):
194 return toBinaryInteger(value, 'memory size', 'B')
195
196def toIpAddress(value):
197 if not isinstance(value, str):
198 raise TypeError("wrong type '%s' should be str" % type(value))
199
200 bytes = value.split('.')
201 if len(bytes) != 4:
202 raise ValueError('invalid ip address %s' % value)
203
204 for byte in bytes:
205 if not 0 <= int(byte) <= 0xff:
206 raise ValueError('invalid ip address %s' % value)
207
208 return (int(bytes[0]) << 24) | (int(bytes[1]) << 16) | \
209 (int(bytes[2]) << 8) | (int(bytes[3]) << 0)
210
211def toIpNetmask(value):
212 if not isinstance(value, str):
213 raise TypeError("wrong type '%s' should be str" % type(value))
214
215 (ip, netmask) = value.split('/')
216 ip = toIpAddress(ip)
217 netmaskParts = netmask.split('.')
218 if len(netmaskParts) == 1:
219 if not 0 <= int(netmask) <= 32:
220 raise ValueError('invalid netmask %s' % netmask)
221 return (ip, int(netmask))
222 elif len(netmaskParts) == 4:
223 netmaskNum = toIpAddress(netmask)
224 if netmaskNum == 0:
225 return (ip, 0)
226 testVal = 0
227 for i in range(32):
228 testVal |= (1 << (31 - i))
229 if testVal == netmaskNum:
230 return (ip, i + 1)
231 raise ValueError('invalid netmask %s' % netmask)
232 else:
233 raise ValueError('invalid netmask %s' % netmask)
234
235def toIpWithPort(value):
236 if not isinstance(value, str):
237 raise TypeError("wrong type '%s' should be str" % type(value))
238
239 (ip, port) = value.split(':')
240 ip = toIpAddress(ip)
241 if not 0 <= int(port) <= 0xffff:
242 raise ValueError('invalid port %s' % port)
243 return (ip, int(port))
244
245def toVoltage(value):
246 return toMetricFloat(value, 'voltage', 'V')
247
248def toCurrent(value):
249 return toMetricFloat(value, 'current', 'A')
250
251def toEnergy(value):
252 return toMetricFloat(value, 'energy', 'J')